import { ActivityType } from '@models/ActivityType';
import { Op } from 'sequelize';
import logger from '@utils/logger';

export class ActivityTypeService {
  /**
   * Get all activity types (optionally filtered by active status)
   */
  async getAllActivityTypes(activeOnly: boolean = false): Promise<ActivityType[]> {
    try {
      const where: any = {};
      if (activeOnly) {
        where.isActive = true;
      }

      const activityTypes = await ActivityType.findAll({
        where,
        order: [['title', 'ASC']],
        include: [
          {
            association: 'creator',
            attributes: ['userId', 'email', 'displayName', 'firstName', 'lastName']
          },
          {
            association: 'updater',
            attributes: ['userId', 'email', 'displayName', 'firstName', 'lastName']
          }
        ]
      });

      return activityTypes;
    } catch (error) {
      logger.error('[ActivityType Service] Error fetching activity types:', error);
      throw error;
    }
  }

  /**
   * Get a single activity type by ID
   */
  async getActivityTypeById(activityTypeId: string): Promise<ActivityType | null> {
    try {
      const activityType = await ActivityType.findByPk(activityTypeId, {
        include: [
          {
            association: 'creator',
            attributes: ['userId', 'email', 'displayName', 'firstName', 'lastName']
          },
          {
            association: 'updater',
            attributes: ['userId', 'email', 'displayName', 'firstName', 'lastName']
          }
        ]
      });

      return activityType;
    } catch (error) {
      logger.error('[ActivityType Service] Error fetching activity type:', error);
      throw error;
    }
  }

  async createActivityType(activityTypeData: {
    title: string;
    itemCode?: string;
    taxationType?: string;
    sapRefNo?: string;
    creditPostingOn?: string;
    createdBy: string;
  }): Promise<ActivityType> {
    try {
      // Check if title already exists
      const existing = await ActivityType.findOne({
        where: {
          title: activityTypeData.title,
          isActive: true
        }
      });

      if (existing) {
        throw new Error(`Activity type with title "${activityTypeData.title}" already exists`);
      }

      const activityType = await ActivityType.create({
        ...activityTypeData,
        isActive: true
      } as any);

      logger.info(`[ActivityType Service] Activity type created: ${activityTypeData.title}`);
      return activityType;
    } catch (error) {
      logger.error('[ActivityType Service] Error creating activity type:', error);
      throw error;
    }
  }

  /**
   * Update an activity type
   */
  async updateActivityType(activityTypeId: string, updates: {
    title?: string;
    itemCode?: string;
    taxationType?: string;
    sapRefNo?: string;
    creditPostingOn?: string;
    isActive?: boolean;
  }, updatedBy: string): Promise<ActivityType | null> {
    try {
      const activityType = await ActivityType.findByPk(activityTypeId);

      if (!activityType) {
        return null;
      }

      // If title is being updated, check for duplicates
      if (updates.title && updates.title !== activityType.title) {
        const existing = await ActivityType.findOne({
          where: {
            title: updates.title,
            activityTypeId: { [Op.ne]: activityTypeId },
            isActive: true
          }
        });

        if (existing) {
          throw new Error(`Activity type with title "${updates.title}" already exists`);
        }
      }

      await activityType.update({
        ...updates,
        updatedBy
      } as any);

      logger.info(`[ActivityType Service] Activity type updated: ${activityTypeId}`);
      return activityType.reload();
    } catch (error) {
      logger.error('[ActivityType Service] Error updating activity type:', error);
      throw error;
    }
  }

  /**
   * Delete (deactivate) an activity type
   */
  async deleteActivityType(activityTypeId: string): Promise<void> {
    try {
      const activityType = await ActivityType.findByPk(activityTypeId);

      if (!activityType) {
        throw new Error('Activity type not found');
      }

      // Soft delete by setting isActive to false
      await activityType.update({
        isActive: false
      } as any);

      logger.info(`[ActivityType Service] Activity type deactivated: ${activityTypeId}`);
    } catch (error) {
      logger.error('[ActivityType Service] Error deleting activity type:', error);
      throw error;
    }
  }
}

export const activityTypeService = new ActivityTypeService();

