/**
 * Support Controller
 * Unified controller for handling support tickets and callback requests for all roles
 * Includes Customer, Driver, Vendor, and Admin operations
 */

const { catchAsyncErrors } = require('../middlewares/catchAsyncErrors');
const ErrorHandler = require('../utils/ErrorHandler');
const supportService = require('../services/support.service');
const {
    userCreateTicketSchema,
    userCallbackRequestSchema,
    updateTicketStatusSchema,
    escalateTicketSchema,
    assignTicketSchema,
    addTicketMessageSchema,
    proposeCompensationSchema,
    processCompensationSchema,
    rejectCompensationSchema,
    scheduleCallbackSchema,
    completeCallbackSchema,
} = require('../validation/support.validation');

// ==========================================
// TICKET ENDPOINTS (COMMON & USER/DRIVER/VENDOR)
// ==========================================

/**
 * Create a new support ticket
 */
exports.createTicket = catchAsyncErrors(async (req, res, next) => {
    // Basic validation for common fields
    const { category, subject, text, orderId } = req.body;
    if (!category || !text) {
        return next(new ErrorHandler("Category and message text are required", 400));
    }

    // Handle attachments if any
    const attachments = req.files?.map(file => ({
        url: file.path,
        filename: file.originalname,
        mimetype: file.mimetype
    })) || [];

    const ticket = await supportService.createTicket(req.user, {
        category,
        subject,
        text,
        orderId,
        attachments
    });

    res.status(201).json({
        success: true,
        message: "Ticket created successfully",
        data: ticket
    });
});

/**
 * Get tickets for the logged-in user (role-aware)
 * If admin, this still returns their "personal" tickets unless they use the admin-specific getAllTickets
 */
exports.getMyTickets = catchAsyncErrors(async (req, res, next) => {
    const { page, limit, status, category } = req.query;

    const result = await supportService.getTickets(req.user, {
        page,
        limit,
        status,
        category
    });

    res.status(200).json({
        success: true,
        ...result
    });
});

/**
 * Get ticket details (role-aware)
 */
exports.getTicketDetails = catchAsyncErrors(async (req, res, next) => {
    const ticket = await supportService.getTicketDetails(req.params.id, req.user);

    res.status(200).json({
        success: true,
        data: ticket
    });
});

/**
 * Add message to ticket (role-aware)
 */
exports.addMessage = catchAsyncErrors(async (req, res, next) => {
    const { text, isInternal } = req.body;
    if (!text) return next(new ErrorHandler("Message text is required", 400));

    // Handle attachments if any
    const attachments = req.files?.map(file => ({
        url: file.path,
        filename: file.originalname,
        mimetype: file.mimetype
    })) || [];

    // Admins/Admins can send internal messages
    const isInternalMsg = (req.user.role === 'super-admin' || req.user.role === 'zone-admin') ? (isInternal === 'true' || isInternal === true) : false;

    const ticket = await supportService.addMessage(req.params.id, req.user, {
        text,
        attachments,
        isInternal: isInternalMsg
    });

    res.status(200).json({
        success: true,
        message: "Message sent successfully",
        data: ticket
    });
});

/**
 * Update ticket status (Admin/Vendor only)
 */
exports.updateStatus = catchAsyncErrors(async (req, res, next) => {
    const { error } = updateTicketStatusSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { status } = req.body;
    const ticket = await supportService.updateTicketStatus(req.params.id, status, req.user);

    res.status(200).json({
        success: true,
        message: `Ticket status updated to ${status}`,
        data: ticket
    });
});

/**
 * Get user's orders for ticket creation (User only)
 */
exports.getMyOrders = catchAsyncErrors(async (req, res, next) => {
    const orders = await supportService.getUserOrders(req.user._id);

    res.status(200).json({
        success: true,
        data: orders
    });
});

// ==========================================
// CALLBACK REQUEST ENDPOINTS (COMMON & USER/DRIVER/VENDOR)
// ==========================================

/**
 * Request a callback (role-aware)
 */
exports.requestCallback = catchAsyncErrors(async (req, res, next) => {
    const { error } = userCallbackRequestSchema.validate(req.body);
    if (error) {
        return next(new ErrorHandler(error.details[0].message, 400));
    }

    const { name, contact, reasonCategory, preferredSlot } = req.body;

    const callbackRequest = await supportService.createCallbackRequest(req.user, {
        name,
        contact,
        reasonCategory,
        preferredSlot
    });

    res.status(201).json({
        success: true,
        message: "Callback request submitted successfully",
        data: callbackRequest
    });
});

/**
 * Get callback requests for the logged-in user (role-aware)
 */
exports.getMyCallbackRequests = catchAsyncErrors(async (req, res, next) => {
    const { page, limit, status } = req.query;

    const result = await supportService.getCallbackRequests(req.user, {
        page,
        limit,
        status
    });

    res.status(200).json({
        success: true,
        ...result
    });
});

/**
 * Cancel callback request (role-aware)
 */
exports.cancelCallback = catchAsyncErrors(async (req, res, next) => {
    await supportService.cancelCallbackRequest(req.params.id, req.user);

    res.status(200).json({
        success: true,
        message: "Callback request cancelled successfully"
    });
});

// ==========================================
// ADMIN SUPPORT MANAGEMENT (Super-Admin / Zone-Admin)
// ==========================================

/**
 * Get support management dashboard
 */
exports.getManagementDashboard = catchAsyncErrors(async (req, res, next) => {
    const dashboardData = await supportService.getSupportDashboard(req.user);
    res.status(200).json({ success: true, data: dashboardData });
});

/**
 * Get tickets with advanced filters (Management only)
 */
exports.getManagementTickets = catchAsyncErrors(async (req, res, next) => {
    const { page, limit, status, category, zone, vendor, search, dateRange, creatorType, escalated, priority } = req.query;

    // Reuse service method for multi-role ticket retrieval
    const result = await supportService.getTickets(req.user, {
        page,
        limit,
        status,
        category,
        zone,
        vendor,
        search,
        dateRange,
        creatorType,
        escalated,
        priority
    });

    res.status(200).json({ success: true, ...result });
});

/**
 * Escalate ticket
 */
exports.escalateTicket = catchAsyncErrors(async (req, res, next) => {
    const { error } = escalateTicketSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { reason, priority } = req.body;
    const ticket = await supportService.escalateTicket(req.params.id, req.user, {
        reason,
        priority
    });

    res.status(200).json({ success: true, message: "Ticket escalated", data: ticket });
});

/**
 * Assign ticket
 */
exports.assignTicket = catchAsyncErrors(async (req, res, next) => {
    const { error } = assignTicketSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { assignTo, assignType } = req.body;
    const ticket = await supportService.assignTicket(req.params.id, req.user, {
        assignTo,
        assignType
    });

    res.status(200).json({ success: true, message: "Ticket assigned", data: ticket });
});

/**
 * Propose compensation
 */
exports.proposeCompensation = catchAsyncErrors(async (req, res, next) => {
    const { error } = proposeCompensationSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { ticketId, amount, reason } = req.body;
    const compensation = await supportService.proposeCompensation(req.user, {
        ticketId,
        amount,
        reason
    });

    res.status(201).json({ success: true, data: compensation });
});

/**
 * Get all compensations
 */
exports.getCompensations = catchAsyncErrors(async (req, res, next) => {
    const { page, limit, status } = req.query;
    const result = await supportService.getCompensations(req.user, { page, limit, status });
    res.status(200).json({ success: true, ...result });
});

/**
 * Approve compensation
 */
exports.approveCompensation = catchAsyncErrors(async (req, res, next) => {
    const compensation = await supportService.approveCompensation(req.params.id, req.user);
    res.status(200).json({ success: true, data: compensation });
});

/**
 * Process compensation
 */
exports.processCompensation = catchAsyncErrors(async (req, res, next) => {
    const { error } = processCompensationSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { paymentMethod, transactionId, notes } = req.body;
    const compensation = await supportService.processCompensation(req.params.id, req.user, {
        paymentMethod,
        transactionId,
        notes
    });

    res.status(200).json({ success: true, data: compensation });
});

/**
 * Reject compensation
 */
exports.rejectCompensation = catchAsyncErrors(async (req, res, next) => {
    const { error } = rejectCompensationSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { reason } = req.body;
    const compensation = await supportService.rejectCompensation(req.params.id, req.user, {
        reason
    });

    res.status(200).json({ success: true, data: compensation });
});

/**
 * Get callback requests (Management version)
 */
exports.getManagementCallbackRequests = catchAsyncErrors(async (req, res, next) => {
    const { page, limit, status } = req.query;
    const result = await supportService.getCallbackRequests(req.user, { page, limit, status });
    res.status(200).json({ success: true, ...result });
});

/**
 * Schedule callback
 */
exports.scheduleCallback = catchAsyncErrors(async (req, res, next) => {
    const { error } = scheduleCallbackSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { scheduledAt, assignedTo, notes } = req.body;
    const callbackRequest = await supportService.scheduleCallback(req.params.id, req.user, {
        scheduledAt,
        assignedTo,
        notes
    });

    res.status(200).json({ success: true, data: callbackRequest });
});

/**
 * Complete callback
 */
exports.completeCallback = catchAsyncErrors(async (req, res, next) => {
    const { error } = completeCallbackSchema.validate(req.body);
    if (error) return next(new ErrorHandler(error.details[0].message, 400));

    const { notes } = req.body;
    const callbackRequest = await supportService.completeCallback(req.params.id, req.user, { notes });
    res.status(200).json({ success: true, data: callbackRequest });
});

/**
 * Get support analytics
 */
exports.getAnalytics = catchAsyncErrors(async (req, res, next) => {
    const { period, startDate, endDate } = req.query;
    const analytics = await supportService.getSupportAnalytics(req.user, { period, startDate, endDate });
    res.status(200).json({ success: true, data: analytics });
});

// ==========================================
// SUPPORT INFO ENDPOINTS
// ==========================================

/**
 * Get ticket categories based on role
 */
exports.getCategories = catchAsyncErrors(async (req, res, next) => {
    const categories = supportService.getTicketCategories(req.user.role);

    res.status(200).json({
        success: true,
        data: categories
    });
});

/**
 * Get general callback reason categories
 */
exports.getCallbackReasons = catchAsyncErrors(async (req, res, next) => {
    const reasons = supportService.getCallbackReasons();

    res.status(200).json({
        success: true,
        data: reasons
    });
});

/**
 * Get available time slots for callbacks
 */
exports.getTimeSlots = catchAsyncErrors(async (req, res, next) => {
    const slots = supportService.getTimeSlots();

    res.status(200).json({
        success: true,
        data: slots
    });
});

/**
 * Get support statistics (role-aware)
 */
exports.getSupportStats = catchAsyncErrors(async (req, res, next) => {
    const stats = await supportService.getSupportStats(req.user);

    res.status(200).json({
        success: true,
        data: stats
    });
});

