const { validationResult } = require('express-validator');
const AppointmentService = require('../services/appointmentService');
const logger = require('../config/logger');

/**
 * Appointment Controller
 * Handles appointment API endpoints
 */
class AppointmentController {
  /**
   * Create a new appointment
   * @route POST /api/v1/appointments
   */
  static async createAppointment(req, res, next) {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request data',
            details: errors.array(),
          },
        });
      }

      const appointmentData = req.body;
      const userId = req.userId;

      const appointment = await AppointmentService.createAppointment(appointmentData, userId);

      res.status(201).json({
        success: true,
        data: appointment,
      });
    } catch (error) {
      logger.error('Error in createAppointment:', error);

      if (error.message === 'SERVICE_NOT_FOUND') {
        return res.status(404).json({
          success: false,
          error: {
            code: 'SERVICE_NOT_FOUND',
            message: 'Service not found',
          },
        });
      }

      next(error);
    }
  }

  /**
   * Get user's appointments with filtering and pagination
   * @route GET /api/v1/appointments
   */
  static async getAppointments(req, res, next) {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request parameters',
            details: errors.array(),
          },
        });
      }

      const { page = 1, limit = 10, status } = req.query;
      const userId = req.userId;

      const result = await AppointmentService.getUserAppointments(userId, {
        page: parseInt(page),
        limit: parseInt(limit),
        status,
      });

      res.json({
        success: true,
        data: result.data,
        pagination: result.pagination,
      });
    } catch (error) {
      logger.error('Error in getAppointments:', error);
      next(error);
    }
  }

  /**
   * Get user's appointment statistics
   * @route GET /api/v1/appointments/stats
   */
  static async getAppointmentStats(req, res, next) {
    try {
      const userId = req.userId;
      const stats = await AppointmentService.getUserAppointmentStats(userId);

      res.json({
        code: 0,
        message: 'Success',
        data: stats,
      });
    } catch (error) {
      logger.error('Error in getAppointmentStats:', error);
      next(error);
    }
  }

  /**
   * Get appointment by ID
   * @route GET /api/v1/appointments/:id
   */
  static async getAppointmentById(req, res, next) {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request parameters',
            details: errors.array(),
          },
        });
      }

      const { id } = req.params;
      const userId = req.userId;

      const appointment = await AppointmentService.getAppointmentById(id, userId);

      if (!appointment) {
        return res.status(404).json({
          success: false,
          error: {
            code: 'APPOINTMENT_NOT_FOUND',
            message: 'Appointment not found',
          },
        });
      }

      res.json({
        success: true,
        data: appointment,
      });
    } catch (error) {
      logger.error('Error in getAppointmentById:', error);
      next(error);
    }
  }

  /**
   * Update appointment
   * @route PUT /api/v1/appointments/:id
   */
  static async updateAppointment(req, res, next) {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request data',
            details: errors.array(),
          },
        });
      }

      const { id } = req.params;
      const userId = req.userId;
      const updateData = req.body;

      const appointment = await AppointmentService.updateAppointment(id, userId, updateData);

      res.json({
        success: true,
        data: appointment,
      });
    } catch (error) {
      logger.error('Error in updateAppointment:', error);

      if (error.message === 'APPOINTMENT_NOT_FOUND') {
        return res.status(404).json({
          success: false,
          error: {
            code: 'APPOINTMENT_NOT_FOUND',
            message: 'Appointment not found',
          },
        });
      }

      if (error.message === 'INVALID_STATUS_TRANSITION') {
        return res.status(400).json({
          success: false,
          error: {
            code: 'INVALID_STATUS_TRANSITION',
            message: 'Invalid status transition',
          },
        });
      }

      next(error);
    }
  }

  /**
   * Cancel appointment
   * @route DELETE /api/v1/appointments/:id
   */
  static async cancelAppointment(req, res, next) {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request parameters',
            details: errors.array(),
          },
        });
      }

      const { id } = req.params;
      const userId = req.userId;

      const appointment = await AppointmentService.cancelAppointment(id, userId);

      res.json({
        success: true,
        data: appointment,
      });
    } catch (error) {
      logger.error('Error in cancelAppointment:', error);

      if (error.message === 'APPOINTMENT_NOT_FOUND') {
        return res.status(404).json({
          success: false,
          error: {
            code: 'APPOINTMENT_NOT_FOUND',
            message: 'Appointment not found',
          },
        });
      }

      if (error.message === 'CANNOT_CANCEL_COMPLETED') {
        return res.status(400).json({
          success: false,
          error: {
            code: 'CANNOT_CANCEL_COMPLETED',
            message: 'Cannot cancel completed appointment',
          },
        });
      }

      if (error.message === 'ALREADY_CANCELLED') {
        return res.status(400).json({
          success: false,
          error: {
            code: 'ALREADY_CANCELLED',
            message: 'Appointment is already cancelled',
          },
        });
      }

      if (error.message === 'INVALID_STATUS_TRANSITION') {
        return res.status(400).json({
          success: false,
          error: {
            code: 'INVALID_STATUS_TRANSITION',
            message: 'Invalid status transition',
          },
        });
      }

      next(error);
    }
  }
}

module.exports = AppointmentController;
