/**
 * Unified Support Service
 * Handles tickets, callback requests, and compensation for all roles
 */

const Ticket = require('../models/ticket.model');
const CallbackRequest = require('../models/callback-request.model');
const Booking = require('../models/booking.model');
const User = require('../models/user.model');
const Driver = require('../models/driver.model');
const Vendor = require('../models/vendor.model');
const Zone = require('../models/zone.model');
const Compensation = require('../models/compensation.model');

// ==========================================
// HELPER FUNCTIONS (Internal)
// ==========================================

const _checkTicketAccess = async (ticket, user) => {
    if (!ticket) throw { message: "Ticket not found", statusCode: 404 };
    const userId = user._id.toString();
    const role = user.role;

    const isAuthorized =
        role === 'super-admin' ||
        (role === 'zone-admin' && await Zone.exists({ _id: ticket.zone, zoneAdmin: userId })) ||
        (role === 'user' && ticket.user?.toString() === userId) ||
        (role === 'driver' && ticket.driver?.toString() === userId) ||
        (role === 'vendor' && ticket.vendor?.toString() === userId);

    if (!isAuthorized) throw { message: "Unauthorized access to this ticket", statusCode: 403 };
};

const _checkCallbackAccess = async (callback, user) => {
    if (!callback) throw { message: "Callback request not found", statusCode: 404 };
    const userId = user._id.toString();
    const role = user.role;

    const isAuthorized =
        role === 'super-admin' ||
        (role === 'zone-admin' && await Zone.exists({ _id: callback.zone, zoneAdmin: userId })) ||
        (role === 'vendor' && callback.vendor?.toString() === userId) ||
        (callback.user?.toString() === userId) ||
        (callback.customer?.toString() === userId) ||
        (callback.driver?.toString() === userId);

    if (!isAuthorized) throw { message: "Unauthorized access to this callback request", statusCode: 403 };
};

// ==========================================
// TICKET SERVICES
// ==========================================

/**
 * Create a new support ticket
 * @param {Object} user - Authenticated user object (req.user)
 * @param {Object} data - { category, subject, text, orderId, attachments }
 */
exports.createTicket = async (user, data) => {
    const userId = user._id;
    const role = user.role;

    let ticketData = {
        creatorType: role,
        category: data.category,
        messages: [{
            sender: userId,
            senderModel: role.charAt(0).toUpperCase() + role.slice(1),
            text: data.text,
            attachments: data.attachments || []
        }]
    };

    if (data.subject) ticketData.subject = data.subject;
    if (data.orderId) ticketData.orderId = data.orderId;

    // Role-specific logic
    if (role === 'driver') {
        const driver = await Driver.findById(userId);
        if (!driver) throw { message: "Driver not found", statusCode: 404 };

        const vendorId = driver.assignmentDetails?.vendorId;
        if (!vendorId) throw { message: "No vendor assigned to this driver", statusCode: 400 };

        ticketData.driver = userId;
        ticketData.vendor = vendorId;
    } else if (role === 'vendor') {
        ticketData.vendor = userId;
    } else {
        ticketData.user = userId;
    }

    // Always try to resolve booking details if orderId is provided
    if (data.orderId) {
        const booking = await Booking.findOne({ orderId: data.orderId })
            .populate('vendor')
            .populate('zone');

        if (booking) {
            ticketData.booking = booking._id;
            ticketData.orderId = booking.orderId;
            ticketData.zone = booking.zone?._id || booking.zone;
            ticketData.vendor = booking.vendor?._id || booking.vendor;
            if (booking.driver) ticketData.driver = booking.driver;

            // If it's a user ticket, verify they own the booking
            if (role === 'user' && booking.customer.toString() !== userId.toString()) {
                throw { message: "This order does not belong to you", statusCode: 403 };
            }
        } else {
            throw { message: "Invalid Order ID", statusCode: 404 };
        }
    }

    const ticket = new Ticket(ticketData);
    await ticket.save();
    return ticket;
};

/**
 * Get tickets with filters based on role
 * @param {Object} user - Authenticated user object
 * @param {Object} options - { page, limit, status, category, creatorType, zone, vendor, search, dateRange }
 */
exports.getTickets = async (user, options = {}) => {
    const {
        page = 1,
        limit = 10,
        status,
        category,
        creatorType,
        zone,
        vendor,
        search,
        dateRange,
        escalated,
        priority
    } = options;

    const skip = (page - 1) * limit;
    const userId = user._id;
    const role = user.role;

    let filter = {};

    // Role-based visibility
    if (role === 'user') {
        filter = { user: userId };
    } else if (role === 'driver') {
        filter = { driver: userId };
    } else if (role === 'vendor') {
        filter = { vendor: userId };
    } else if (role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: userId }).select('_id');
        filter = { zone: { $in: managedZones.map(z => z._id) } };
    } else if (role === 'super-admin') {
        if (creatorType && creatorType !== 'all') filter.creatorType = creatorType;

        // Advanced Admin Filters
        if (zone && zone !== 'All Status') {
            const zoneDoc = await Zone.findOne({ zoneName: zone });
            if (zoneDoc) filter.zone = zoneDoc._id;
        }

        if (vendor && vendor !== 'All Status') {
            const vendorDoc = await Vendor.findOne({ vendorName: vendor });
            if (vendorDoc) filter.vendor = vendorDoc._id;
        }

        if (search) {
            filter.$or = [
                { ticketId: { $regex: search, $options: 'i' } },
                { subject: { $regex: search, $options: 'i' } },
                { 'messages.text': { $regex: search, $options: 'i' } }
            ];
        }

        if (dateRange) {
            const [start, end] = dateRange.split(',');
            if (start && end) {
                filter.createdAt = {
                    $gte: new Date(start),
                    $lte: new Date(end)
                };
            }
        }
    }

    if (status && status !== 'all' && status !== 'All Status') filter.status = status;
    if (category && category !== 'all' && category !== 'All Status') filter.category = category;
    if (escalated === 'true' || escalated === true) filter.escalated = true;
    if (priority && priority !== 'all') filter.priority = priority;

    const [tickets, total] = await Promise.all([
        Ticket.find(filter)
            .populate('booking', 'orderId pickupLocation dropLocation status fare')
            .populate('driver', 'fullName phone profileImageUrl')
            .populate('user', 'fullName phone email profileImageUrl')
            .populate('vendor', 'vendorName phone')
            .populate('zone', 'zoneName')
            .sort({ updatedAt: -1 })
            .skip(skip)
            .limit(parseInt(limit)),
        Ticket.countDocuments(filter)
    ]);

    // Format tickets for response
    const formattedTickets = tickets.map(ticket => {
        const lastMessage = ticket.messages[ticket.messages.length - 1];
        return {
            _id: ticket._id,
            ticketId: ticket.ticketId,
            subject: ticket.subject,
            category: ticket.category,
            status: ticket.status,
            orderId: ticket.orderId,
            zone: ticket.zone?.zoneName,
            vendorName: ticket.vendor?.vendorName,
            createdAt: ticket.createdAt,
            updatedAt: ticket.updatedAt,
            lastMessage: lastMessage ? {
                text: lastMessage.text,
                timestamp: lastMessage.timestamp,
                senderModel: lastMessage.senderModel
            } : null
        };
    });

    return {
        tickets: formattedTickets,
        pagination: {
            total,
            page: parseInt(page),
            limit: parseInt(limit),
            pages: Math.ceil(total / limit)
        }
    };
};

/**
 * Get ticket details by ID
 */
exports.getTicketDetails = async (ticketId, user) => {
    const ticket = await Ticket.findById(ticketId)
        .populate('user', 'fullName phone email profileImageUrl')
        .populate('driver', 'fullName phone profileImageUrl')
        .populate('vendor', 'vendorName phone email profileImageUrl')
        .populate('booking', 'orderId pickupLocation dropLocation status fare pickupDate');

    if (!ticket) throw { message: "Ticket not found", statusCode: 404 };

    // Authorization check
    await _checkTicketAccess(ticket, user);
    const userId = user._id.toString();
    const role = user.role;

    // Filter messages for non-admins
    let messages = ticket.messages;
    if (role !== 'super-admin' && role !== 'zone-admin') {
        messages = messages.filter(msg => !msg.isInternal);
    }

    // For admins, include related items
    if (role === 'super-admin' || role === 'zone-admin') {
        const [compensation, callbackRequest] = await Promise.all([
            Compensation.findOne({ ticket: ticketId }).populate('proposedBy approvedBy processedBy', 'fullName'),
            CallbackRequest.findOne({ ticket: ticketId }).populate('user customer driver vendor assignedTo', 'fullName phone')
        ]);

        return {
            ...ticket.toObject(),
            messages: messages.map(msg => ({
                ...msg.toObject(),
                isFromMe: msg.sender.toString() === userId,
                senderName: msg.senderModel === 'User' ? (ticket.user?._id.toString() === msg.sender.toString() ? 'You' : 'Support') :
                    (msg.senderModel === 'Driver' ? (ticket.driver?._id.toString() === msg.sender.toString() ? 'You' : 'Driver') :
                        (msg.senderModel === 'Vendor' ? (ticket.vendor?._id.toString() === msg.sender.toString() ? 'You' : 'Vendor') : 'Support'))
            })),
            compensation,
            callbackRequest
        };
    }

    return {
        ...ticket.toObject(),
        messages: messages.map(msg => ({
            ...msg,
            isFromMe: msg.sender.toString() === userId,
            senderName: msg.senderModel === 'User' ? (ticket.user?._id.toString() === msg.sender.toString() ? 'You' : 'Support') :
                (msg.senderModel === 'Driver' ? (ticket.driver?._id.toString() === msg.sender.toString() ? 'You' : 'Driver') :
                    (msg.senderModel === 'Vendor' ? (ticket.vendor?._id.toString() === msg.sender.toString() ? 'You' : 'Vendor') : 'Support'))
        }))
    };
};

/**
 * Add message to ticket
 */
exports.addMessage = async (ticketId, user, data) => {
    const ticket = await Ticket.findById(ticketId);
    await _checkTicketAccess(ticket, user);
    const role = user.role;
    const userId = user._id.toString();
    if (ticket.status === 'closed') throw { message: "Ticket is closed", statusCode: 400 };

    ticket.messages.push({
        sender: userId,
        senderModel: role.charAt(0).toUpperCase() + role.slice(1),
        text: data.text,
        attachments: data.attachments || [],
        isInternal: data.isInternal || false
    });

    // Reopen if pending and user/driver replies
    if (ticket.status === 'pending' && (role === 'user' || role === 'driver')) {
        ticket.status = 'open';
    }

    ticket.updatedAt = Date.now();
    await ticket.save();
    return ticket;
};

// Alias for addMessage to support existing controller calls
exports.addTicketMessage = async (ticketId, data) => {
    const ticket = await Ticket.findByIdAndUpdate(
        ticketId,
        {
            $push: {
                messages: {
                    sender: data.sender,
                    senderModel: data.senderModel || 'User',
                    text: data.text,
                    isInternal: data.isInternal || false,
                    timestamp: Date.now()
                }
            },
            updatedAt: Date.now()
        },
        { new: true }
    );
    if (!ticket) throw { message: "Ticket not found", statusCode: 404 };
    return ticket;
};

/**
 * Update ticket status
 */
exports.updateTicketStatus = async (ticketId, status, user) => {
    const ticket = await Ticket.findById(ticketId);
    await _checkTicketAccess(ticket, user);

    ticket.status = status;
    ticket.updatedAt = Date.now();
    ticket.messages.push({
        sender: user._id,
        senderModel: user.role === 'driver' ? 'Driver' : (user.role === 'vendor' ? 'Vendor' : 'User'),
        text: `Ticket status updated to ${status}`,
        isInternal: user.role === 'super-admin' || user.role === 'zone-admin'
    });

    await ticket.save();
    return ticket.populate('driver vendor user');

    if (!ticket) throw { message: "Ticket not found", statusCode: 404 };
    return ticket;
};

// ==========================================
// COMPENSATION SERVICES
// ==========================================

exports.proposeCompensation = async (user, data) => {
    const { ticketId, amount, reason } = data;

    const ticket = await Ticket.findById(ticketId);
    await _checkTicketAccess(ticket, user);

    const proposedBy = user._id;

    // Check if compensation already proposed
    const existingCompensation = await Compensation.findOne({ ticket: ticketId, status: { $in: ['proposed', 'approved'] } });
    if (existingCompensation) throw { message: "Compensation already proposed or approved for this ticket", statusCode: 400 };

    let customerId = ticket.user;
    if (!customerId && ticket.driver) {
        const driver = await Driver.findById(ticket.driver);
        customerId = driver?.userId;
    }

    if (!customerId) throw { message: "Customer not found for this ticket", statusCode: 404 };

    const compensation = new Compensation({
        ticket: ticketId,
        customer: customerId,
        amount,
        reason,
        proposedBy
    });

    await compensation.save();
    return compensation;
};

/**
 * Get all compensations with filters
 */
exports.getCompensations = async (user, options = {}) => {
    const { page = 1, limit = 10, status } = options;
    const skip = (page - 1) * limit;

    let filter = {};
    if (status && status !== 'All Status') filter.status = status;

    // Role-based visibility for compensations
    if (user.role === 'vendor') {
        const vendorTickets = await Ticket.find({ vendor: user._id }).select('_id');
        filter.ticket = { $in: vendorTickets.map(t => t._id) };
    } else if (user.role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: user._id }).select('_id');
        const zoneTickets = await Ticket.find({ zone: { $in: managedZones.map(z => z._id) } }).select('_id');
        filter.ticket = { $in: zoneTickets.map(t => t._id) };
    }

    const [compensations, total] = await Promise.all([
        Compensation.find(filter)
            .populate('ticket', 'ticketId category')
            .populate('customer', 'fullName phone')
            .populate('proposedBy approvedBy processedBy', 'fullName')
            .sort({ createdAt: -1 })
            .skip(skip)
            .limit(parseInt(limit)),
        Compensation.countDocuments(filter)
    ]);

    return {
        compensations,
        pagination: {
            total,
            page: parseInt(page),
            limit: parseInt(limit),
            pages: Math.ceil(total / limit)
        }
    };
};

/**
 * Approve compensation
 */
exports.approveCompensation = async (compensationId, user) => {
    const compensation = await Compensation.findById(compensationId).populate('ticket');
    if (!compensation) throw { message: "Compensation not found", statusCode: 404 };

    // Strict Super Admin only for approval
    if (user.role !== 'super-admin') throw { message: "Only Super Admin can approve compensation", statusCode: 403 };

    compensation.status = 'approved';
    compensation.approvedBy = user._id;
    compensation.approvedAt = Date.now();

    await compensation.save();
    return compensation;
};

/**
 * Process compensation
 */
exports.processCompensation = async (compensationId, user, data) => {
    const compensation = await Compensation.findById(compensationId).populate('ticket');
    if (!compensation) throw { message: "Compensation not found", statusCode: 404 };

    // Strict Super Admin only for processing
    if (user.role !== 'super-admin') throw { message: "Only Super Admin can process compensation", statusCode: 403 };

    const { paymentMethod, transactionId, notes } = data;

    compensation.status = 'processed';
    compensation.paymentMethod = paymentMethod;
    compensation.transactionId = transactionId;
    compensation.notes = notes;
    compensation.processedBy = user._id;
    compensation.processedAt = Date.now();

    await compensation.save();
    return compensation;
};

/**
 * Reject compensation
 */
exports.rejectCompensation = async (compensationId, user, data) => {
    const compensation = await Compensation.findById(compensationId).populate('ticket');
    if (!compensation) throw { message: "Compensation not found", statusCode: 404 };

    // Authorization check via associated ticket
    await _checkTicketAccess(compensation.ticket, user);

    if (compensation.status !== 'proposed') throw { message: "Only proposed compensations can be rejected", statusCode: 400 };

    const { reason } = data;

    compensation.status = 'rejected';
    compensation.notes = reason;
    compensation.rejectedBy = user._id;
    compensation.rejectedAt = Date.now();

    await compensation.save();
    return compensation;
    return compensation;
};

// ==========================================
// ADMIN SUPPORT SERVICES
// ==========================================

/**
 * Get support dashboard data (role-aware)
 */
exports.getSupportDashboard = async (user) => {
    if (!user) throw { message: "User not found", statusCode: 404 };
    let ticketFilter = {};
    let callbackFilter = {};
    let compensationFilter = {};

    const userId = user._id;
    const role = user.role;

    if (role === 'vendor') {
        ticketFilter = { vendor: userId };
        callbackFilter = { vendor: userId };
        const vendorTickets = await Ticket.find({ vendor: userId }).select('_id');
        compensationFilter = { ticket: { $in: vendorTickets.map(t => t._id) } };
    } else if (role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: userId }).select('_id');
        const zoneIds = managedZones.map(z => z._id);
        ticketFilter = { zone: { $in: zoneIds } };
        callbackFilter = { zone: { $in: zoneIds } };
        const zoneTickets = await Ticket.find({ zone: { $in: zoneIds } }).select('_id');
        compensationFilter = { ticket: { $in: zoneTickets.map(t => t._id) } };
    }

    const [
        totalTickets, openTickets, inProgressTickets, resolvedTickets, escalatedTickets, urgentTickets,
        totalCallbacks, pendingCallbacks, scheduledCallbacks, completedCallbacks,
        compensationStats
    ] = await Promise.all([
        Ticket.countDocuments(ticketFilter),
        Ticket.countDocuments({ ...ticketFilter, status: 'open' }),
        Ticket.countDocuments({ ...ticketFilter, status: 'pending' }),
        Ticket.countDocuments({ ...ticketFilter, status: 'closed' }),
        Ticket.countDocuments({ ...ticketFilter, escalated: true, status: { $ne: 'closed' } }),
        Ticket.countDocuments({ ...ticketFilter, priority: 'urgent', status: { $ne: 'closed' } }),
        CallbackRequest.countDocuments(callbackFilter),
        CallbackRequest.countDocuments({ ...callbackFilter, status: 'pending' }),
        CallbackRequest.countDocuments({ ...callbackFilter, status: 'scheduled' }),
        CallbackRequest.countDocuments({ ...callbackFilter, status: 'completed' }),
        Compensation.aggregate([
            { $match: compensationFilter },
            {
                $group: {
                    _id: '$status',
                    count: { $sum: 1 },
                    totalAmount: { $sum: '$amount' }
                }
            }
        ])
    ]);

    // Format compensation stats
    const compData = {
        total: 0, totalAmount: 0,
        proposed: 0, proposedAmount: 0,
        approved: 0, approvedAmount: 0,
        processed: 0, processedAmount: 0
    };

    compensationStats.forEach(stat => {
        compData.total += stat.count;
        compData.totalAmount += stat.totalAmount;
        if (stat._id === 'proposed') { compData.proposed = stat.count; compData.proposedAmount = stat.totalAmount; }
        if (stat._id === 'approved') { compData.approved = stat.count; compData.approvedAmount = stat.totalAmount; }
        if (stat._id === 'processed') { compData.processed = stat.count; compData.processedAmount = stat.totalAmount; }
    });

    return {
        tickets: {
            total: totalTickets,
            open: openTickets,
            inProgress: inProgressTickets,
            resolved: resolvedTickets,
            escalated: escalatedTickets,
            urgent: urgentTickets
        },
        callbacks: { total: totalCallbacks, pending: pendingCallbacks, scheduled: scheduledCallbacks, completed: completedCallbacks },
        compensations: compData
    };
};

/**
 * Escalate ticket
 */
exports.escalateTicket = async (ticketId, user, escalationData) => {
    const { reason, priority } = escalationData;
    const ticket = await Ticket.findById(ticketId);
    await _checkTicketAccess(ticket, user);

    ticket.priority = priority || 'high';
    ticket.escalated = true;
    ticket.escalatedAt = Date.now();
    ticket.escalatedBy = user._id;
    ticket.messages.push({
        sender: user._id,
        senderModel: 'User',
        text: `Ticket escalated. Reason: ${reason}`,
        timestamp: Date.now()
    });

    await ticket.save();
    return ticket;

};

/**
 * Assign ticket
 */
exports.assignTicket = async (ticketId, user, assignmentData) => {
    const { assignTo, assignType } = assignmentData;
    const ticket = await Ticket.findById(ticketId);
    await _checkTicketAccess(ticket, user);

    ticket.assignedTo = assignTo;
    ticket.assignedType = assignType;
    ticket.assignedBy = user._id;
    ticket.assignedAt = Date.now();
    ticket.messages.push({
        sender: user._id,
        senderModel: 'User',
        text: `Ticket assigned to ${assignType}`,
        timestamp: Date.now()
    });

    await ticket.save();
    return ticket;

};

/**
 * Schedule callback
 */
exports.scheduleCallback = async (callbackId, user, scheduleData) => {
    const { scheduledAt, assignedTo, notes } = scheduleData;
    const callbackRequest = await CallbackRequest.findById(callbackId);
    await _checkCallbackAccess(callbackRequest, user);

    callbackRequest.status = 'scheduled';
    callbackRequest.scheduledAt = scheduledAt;
    callbackRequest.assignedTo = assignedTo;
    callbackRequest.notes = notes;

    await callbackRequest.save();
    return callbackRequest;
};

/**
 * Complete callback
 */
exports.completeCallback = async (callbackId, user, completionData) => {
    const { notes } = completionData;
    const callbackRequest = await CallbackRequest.findById(callbackId);
    await _checkCallbackAccess(callbackRequest, user);

    callbackRequest.status = 'completed';
    callbackRequest.completedAt = Date.now();
    callbackRequest.notes = notes;

    await callbackRequest.save();
    return callbackRequest;
};

/**
 * Get support analytics
 */
exports.getSupportAnalytics = async (user, options = {}) => {
    const { period = 'weekly', startDate, endDate } = options;
    const userId = user._id;
    const role = user.role;

    let roleFilter = {};
    if (role === 'vendor') {
        roleFilter = { vendor: userId };
    } else if (role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: userId }).select('_id');
        roleFilter = { zone: { $in: managedZones.map(z => z._id) } };
    }

    let dateFilter = {};
    if (startDate && endDate) {
        dateFilter = { createdAt: { $gte: new Date(startDate), $lte: new Date(endDate) } };
    }

    const matchFilter = { ...roleFilter, ...dateFilter };

    const ticketAnalytics = await Ticket.aggregate([
        { $match: matchFilter },
        { $group: { _id: { status: '$status', category: '$category' }, count: { $sum: 1 } } }
    ]);

    const resolutionTimeAnalytics = await Ticket.aggregate([
        { $match: { status: 'closed', ...matchFilter } },
        { $project: { resolutionTime: { $divide: [{ $subtract: ['$updatedAt', '$createdAt'] }, 1000 * 60 * 60] } } },
        { $group: { _id: null, avgResolutionTime: { $avg: '$resolutionTime' }, minResolutionTime: { $min: '$resolutionTime' }, maxResolutionTime: { $max: '$resolutionTime' } } }
    ]);

    return { ticketAnalytics, resolutionTimeAnalytics: resolutionTimeAnalytics[0] || {} };
};


// ==========================================
// CALLBACK SERVICES
// ==========================================

/**
 * Create callback request
 */
exports.createCallbackRequest = async (arg1, arg2) => {
    let user = arg1;
    let data = arg2;

    const userId = user._id;
    const role = user.role || 'user';

    // Find if user/driver/vendor already has a pending callback for this slot
    // We check specifically for the user's role-based field to be accurate
    let userFilter = {};
    if (role === 'driver') {
        userFilter = { driver: userId };
    } else if (role === 'vendor') {
        userFilter = { vendor: userId };
    } else {
        userFilter = { $or: [{ user: userId }, { customer: userId }] };
    }

    if (data.orderId) {
        userFilter = { ...userFilter, orderId: data.orderId };
    }

    const existingCallbackRequest = await CallbackRequest.findOne({
        ...userFilter,
        status: 'pending'
    });

    if (existingCallbackRequest) {
        throw { message: "You already have a pending callback request. Please wait for 24 hours.", statusCode: 400 };
    }
    // Handle admin call where only data is passed
    if (!arg2 && arg1.customerId) {
        data = arg1;
        user = await User.findById(data.customerId);
    }

    // const userId = user?._id;
    // const role = user?.role || 'user';

    const callbackData = {
        creatorType: role,
        name: data.name || user?.fullName,
        contact: data.contact || user?.phone,
        reasonCategory: data.reasonCategory || 'General Inquiry',
        preferredSlot: data.preferredSlot || {}
    };

    if (data.orderId) {
        const booking = await Booking.findOne({ orderId: data.orderId });
        if (booking) {
            callbackData.booking = booking._id;
            callbackData.orderId = booking.orderId;
            callbackData.zone = booking.zone;
            callbackData.vendor = booking.vendor;
            if (booking.driver) callbackData.driver = booking.driver;
        } else {
            throw { message: "Invalid Order ID", statusCode: 404 };
        }
    }

    if (role === 'driver' && !callbackData.driver) callbackData.driver = userId;
    else if (role === 'vendor' && !callbackData.vendor) callbackData.vendor = userId;
    else if (role === 'user' && !callbackData.user) {
        callbackData.user = userId;
        callbackData.customer = userId; // Legacy support
    }

    const request = new CallbackRequest(callbackData);
    await request.save();
    return request;
};

/**
 * Get callback requests
 */
exports.getCallbackRequests = async (user, options = {}) => {
    const { page = 1, limit = 10, status } = options;
    const skip = (page - 1) * limit;
    const userId = user._id;
    const role = user.role;

    let filter = {};
    if (role === 'user') {
        filter = { $or: [{ user: userId }, { customer: userId }] };
    } else if (role === 'driver') {
        filter = { driver: userId };
    } else if (role === 'vendor') {
        filter = { vendor: userId };
    } else if (role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: userId }).select('_id');
        filter = { zone: { $in: managedZones.map(z => z._id) } };
    }

    if (status && status !== 'all' && status !== 'All Status') filter.status = status;

    const [requests, total] = await Promise.all([
        CallbackRequest.find(filter)
            .populate('ticket', 'ticketId subject')
            .populate('user', 'fullName phone')
            .populate('driver', 'fullName phone')
            .populate('vendor', 'vendorName phone')
            .populate('zone', 'zoneName')
            .sort({ createdAt: -1 })
            .skip(skip)
            .limit(parseInt(limit)),
        CallbackRequest.countDocuments(filter)
    ]);

    return {
        callbackRequests: requests,
        pagination: {
            total,
            page: parseInt(page),
            limit: parseInt(limit),
            pages: Math.ceil(total / limit)
        }
    };
};

/**
 * Cancel callback request
 */
exports.cancelCallbackRequest = async (requestId, user) => {
    const request = await CallbackRequest.findById(requestId);
    await _checkCallbackAccess(request, user);

    if (request.status !== 'pending') throw { message: "Only pending requests can be cancelled", statusCode: 400 };

    request.status = 'cancelled';
    await request.save();
    return request;
};

// ==========================================
// SUPPORT INFO SERVICES
// ==========================================

exports.getTicketCategories = (role) => {
    const common = [
        { value: 'Booking Issue', label: 'Booking Issue' },
        { value: 'Payment Inquiry', label: 'Payment Inquiry' },
        { value: 'Driver Issue', label: 'Driver Issue' },
        { value: 'Other', label: 'Other' }
    ];

    if (role === 'driver') {
        return [...common, { value: 'Request Off Time', label: 'Request Off Time' }];
    }

    return [
        ...common,
        { value: 'Refund Request', label: 'Refund Request' },
        { value: 'Safety Concern', label: 'Safety Concern' },
        { value: 'Lost Item', label: 'Lost Item' },
        { value: 'Fare Dispute', label: 'Fare Dispute' },
        { value: 'App Issue', label: 'App Issue' }
    ];
};

exports.getCallbackReasons = () => {
    return [
        { value: 'Booking Inquiry', label: 'Booking Inquiry' },
        { value: 'Payment Issue', label: 'Payment Issue' },
        { value: 'Refund Request', label: 'Refund Request' },
        { value: 'Route Information', label: 'Route Information' },
        { value: 'Driver Complaint', label: 'Driver Complaint' },
        { value: 'Lost Item', label: 'Lost Item' },
        { value: 'General Inquiry', label: 'General Inquiry' },
        { value: 'Other', label: 'Other' }
    ];
};

exports.getTimeSlots = () => {
    return [
        { value: '10:00 AM - 12:00 PM', label: '10:00 AM - 12:00 PM' },
        { value: '12:00 PM - 2:00 PM', label: '12:00 PM - 2:00 PM' },
        { value: '2:00 PM - 4:00 PM', label: '2:00 PM - 4:00 PM' },
        { value: '4:00 PM - 6:00 PM', label: '4:00 PM - 6:00 PM' }
    ];
};

/**
 * Get support stats
 */
exports.getSupportStats = async (user) => {
    const userId = user._id;
    const role = user.role;

    let ticketFilter = {};
    let callbackFilter = {};

    if (role === 'user') {
        ticketFilter = { user: userId };
        callbackFilter = { $or: [{ user: userId }, { customer: userId }] };
    } else if (role === 'driver') {
        ticketFilter = { driver: userId };
        callbackFilter = { driver: userId };
    } else if (role === 'vendor') {
        ticketFilter = { vendor: userId };
        callbackFilter = { vendor: userId };
    } else if (role === 'zone-admin') {
        const managedZones = await Zone.find({ zoneAdmin: userId }).select('_id');
        const zoneIds = managedZones.map(z => z._id);
        ticketFilter = { zone: { $in: zoneIds } };
        callbackFilter = { zone: { $in: zoneIds } };
    }

    const [
        totalTickets,
        openTickets,
        pendingCallbacks
    ] = await Promise.all([
        Ticket.countDocuments(ticketFilter),
        Ticket.countDocuments({ ...ticketFilter, status: 'open' }),
        CallbackRequest.countDocuments({ ...callbackFilter, status: 'pending' })
    ]);

    return {
        totalTickets,
        openTickets,
        pendingCallbacks
    };
};

/**
 * Get user's orders for ticket creation dropdown
 * @param {String} userId - User ID
 */
exports.getUserOrders = async (userId) => {
    const bookings = await Booking.find({ customer: userId })
        .select('orderId pickupLocation dropLocation status pickupDate createdAt')
        .sort({ createdAt: -1 })
        .limit(20);

    return bookings.map(b => ({
        _id: b._id,
        orderId: b.orderId,
        pickup: b.pickupLocation?.address,
        drop: b.dropLocation?.address,
        status: b.status,
        date: b.pickupDate || b.createdAt
    }));
};
