const { Service, Category } = require('../models');
const CacheService = require('./cacheService');
const logger = require('../config/logger');
const { Op } = require('sequelize');

/**
 * Admin Service Management Business Logic
 */
class AdminServiceService {
  /**
   * Get all services with pagination and filtering (admin view)
   * @param {Object} options - Query options
   * @returns {Promise<Object>} - Paginated services
   */
  static async getServices({ page = 1, limit = 10, categoryId, status, search }) {
    try {
      const offset = (page - 1) * limit;

      // Build query
      const where = {};
      if (categoryId) {
        where.categoryId = categoryId;
      }
      if (status) {
        where.status = status;
      }
      if (search) {
        where[Op.or] = [
          { titleZh: { [Op.like]: `%${search}%` } },
          { titleEn: { [Op.like]: `%${search}%` } },
          { titleEs: { [Op.like]: `%${search}%` } },
        ];
      }

      // Fetch from database
      const { count, rows } = await Service.findAndCountAll({
        where,
        include: [
          {
            model: Category,
            as: 'category',
            attributes: ['id', 'key', 'nameZh', 'nameEn', 'nameEs', 'icon'],
          },
        ],
        order: [['sortOrder', 'ASC'], ['createdAt', 'DESC']],
        limit: parseInt(limit),
        offset: parseInt(offset),
      });

      return {
        data: rows.map(service => service.toJSON()),
        pagination: {
          page: parseInt(page),
          limit: parseInt(limit),
          total: count,
          totalPages: Math.ceil(count / limit),
        },
      };
    } catch (error) {
      logger.error('Error fetching services (admin):', error);
      throw error;
    }
  }

  /**
   * Create a new service
   * @param {Object} serviceData - Service data
   * @returns {Promise<Object>} - Created service
   */
  static async createService(serviceData) {
    try {
      // Validate category exists
      const category = await Category.findByPk(serviceData.categoryId);
      if (!category) {
        const error = new Error('Category not found');
        error.statusCode = 404;
        error.code = 'CATEGORY_NOT_FOUND';
        throw error;
      }

      // Validate required fields
      const requiredFields = ['categoryId', 'titleZh', 'titleEn', 'titleEs'];
      for (const field of requiredFields) {
        if (!serviceData[field]) {
          const error = new Error(`Missing required field: ${field}`);
          error.statusCode = 400;
          error.code = 'MISSING_REQUIRED_FIELD';
          throw error;
        }
      }

      // Create service
      const service = await Service.create({
        categoryId: serviceData.categoryId,
        serviceType: serviceData.serviceType || null,
        titleZh: serviceData.titleZh,
        titleEn: serviceData.titleEn,
        titleEs: serviceData.titleEs,
        descriptionZh: serviceData.descriptionZh || null,
        descriptionEn: serviceData.descriptionEn || null,
        descriptionEs: serviceData.descriptionEs || null,
        image: serviceData.image || null,
        price: serviceData.price || null,
        status: serviceData.status || 'active',
        sortOrder: serviceData.sortOrder || 0,
      });

      // Invalidate cache
      await CacheService.invalidateServiceCache();

      logger.info(`Service created: ${service.id}`);
      return service.toJSON();
    } catch (error) {
      logger.error('Error creating service:', error);
      throw error;
    }
  }

  /**
   * Update a service
   * @param {string} serviceId - Service ID
   * @param {Object} updateData - Update data
   * @returns {Promise<Object>} - Updated service
   */
  static async updateService(serviceId, updateData) {
    try {
      // Find service
      const service = await Service.findByPk(serviceId);
      if (!service) {
        const error = new Error('Service not found');
        error.statusCode = 404;
        error.code = 'SERVICE_NOT_FOUND';
        throw error;
      }

      // Validate category if being updated
      if (updateData.categoryId) {
        const category = await Category.findByPk(updateData.categoryId);
        if (!category) {
          const error = new Error('Category not found');
          error.statusCode = 404;
          error.code = 'CATEGORY_NOT_FOUND';
          throw error;
        }
      }

      // Update service
      const allowedFields = [
        'categoryId',
        'serviceType',
        'titleZh',
        'titleEn',
        'titleEs',
        'descriptionZh',
        'descriptionEn',
        'descriptionEs',
        'image',
        'price',
        'status',
        'sortOrder',
      ];

      const updateFields = {};
      for (const field of allowedFields) {
        if (updateData[field] !== undefined) {
          updateFields[field] = updateData[field];
        }
      }

      await service.update(updateFields);

      // Invalidate cache
      await CacheService.invalidateServiceCache();
      await CacheService.invalidateServiceDetail(serviceId);

      logger.info(`Service updated: ${serviceId}`);
      return service.toJSON();
    } catch (error) {
      logger.error(`Error updating service ${serviceId}:`, error);
      throw error;
    }
  }

  /**
   * Delete a service
   * @param {string} serviceId - Service ID
   * @returns {Promise<boolean>} - Success status
   */
  static async deleteService(serviceId) {
    try {
      // Find service
      const service = await Service.findByPk(serviceId);
      if (!service) {
        const error = new Error('Service not found');
        error.statusCode = 404;
        error.code = 'SERVICE_NOT_FOUND';
        throw error;
      }

      // Check if service has appointments
      const { Appointment } = require('../models');
      const appointmentCount = await Appointment.count({
        where: { serviceId },
      });

      if (appointmentCount > 0) {
        const error = new Error('Cannot delete service with existing appointments');
        error.statusCode = 400;
        error.code = 'SERVICE_HAS_APPOINTMENTS';
        throw error;
      }

      // Delete service
      await service.destroy();

      // Invalidate cache
      await CacheService.invalidateServiceCache();
      await CacheService.invalidateServiceDetail(serviceId);

      logger.info(`Service deleted: ${serviceId}`);
      return true;
    } catch (error) {
      logger.error(`Error deleting service ${serviceId}:`, error);
      throw error;
    }
  }

  /**
   * Get service by ID (admin view with all fields)
   * @param {string} serviceId - Service ID
   * @returns {Promise<Object>} - Service details
   */
  static async getServiceById(serviceId) {
    try {
      const service = await Service.findByPk(serviceId, {
        include: [
          {
            model: Category,
            as: 'category',
            attributes: ['id', 'key', 'nameZh', 'nameEn', 'nameEs', 'icon'],
          },
        ],
      });

      if (!service) {
        return null;
      }

      return service.toJSON();
    } catch (error) {
      logger.error(`Error fetching service ${serviceId}:`, error);
      throw error;
    }
  }
}

module.exports = AdminServiceService;
