import { WorkflowTemplate } from '../models/WorkflowTemplate';
import { WorkflowRequest } from '../models/WorkflowRequest';
import { User } from '../models/User';
import { Op } from 'sequelize';
import logger from '../utils/logger';

/**
 * Template Service
 * Handles CRUD operations for workflow templates
 */
export class TemplateService {
  /**
   * Create a new workflow template
   */
  async createTemplate(
    userId: string,
    templateData: {
      templateName: string;
      templateCode?: string;
      templateDescription?: string;
      templateCategory?: string;
      workflowType?: string;
      approvalLevelsConfig?: any;
      defaultTatHours?: number;
      formStepsConfig?: any;
      userFieldMappings?: any;
      dynamicApproverConfig?: any;
      isActive?: boolean;
    }
  ): Promise<WorkflowTemplate> {
    try {
      // Validate template code uniqueness if provided
      if (templateData.templateCode) {
        const existing = await WorkflowTemplate.findOne({
          where: { templateCode: templateData.templateCode }
        });
        if (existing) {
          throw new Error(`Template code '${templateData.templateCode}' already exists`);
        }
      }

      const template = await WorkflowTemplate.create({
        templateName: templateData.templateName,
        templateCode: templateData.templateCode,
        templateDescription: templateData.templateDescription,
        templateCategory: templateData.templateCategory,
        workflowType: templateData.workflowType || templateData.templateCode?.toUpperCase(),
        approvalLevelsConfig: templateData.approvalLevelsConfig,
        defaultTatHours: templateData.defaultTatHours || 24,
        formStepsConfig: templateData.formStepsConfig,
        userFieldMappings: templateData.userFieldMappings,
        dynamicApproverConfig: templateData.dynamicApproverConfig,
        isActive: templateData.isActive !== undefined ? templateData.isActive : true,
        isSystemTemplate: false, // Admin-created templates are not system templates
        usageCount: 0,
        createdBy: userId,
      });

      logger.info(`[TemplateService] Created template: ${template.templateId}`);
      return template;
    } catch (error) {
      logger.error('[TemplateService] Error creating template:', error);
      throw error;
    }
  }

  /**
   * Get template by ID
   */
  async getTemplate(templateId: string): Promise<WorkflowTemplate | null> {
    try {
      return await WorkflowTemplate.findByPk(templateId, {
        include: [{ model: User, as: 'creator' }]
      });
    } catch (error) {
      logger.error('[TemplateService] Error getting template:', error);
      throw error;
    }
  }

  /**
   * Get template by code
   */
  async getTemplateByCode(templateCode: string): Promise<WorkflowTemplate | null> {
    try {
      return await WorkflowTemplate.findOne({
        where: { templateCode },
        include: [{ model: User, as: 'creator' }]
      });
    } catch (error) {
      logger.error('[TemplateService] Error getting template by code:', error);
      throw error;
    }
  }

  /**
   * List all templates with filters
   */
  async listTemplates(filters?: {
    category?: string;
    workflowType?: string;
    isActive?: boolean;
    isSystemTemplate?: boolean;
    search?: string;
  }): Promise<WorkflowTemplate[]> {
    try {
      const where: any = {};

      if (filters?.category) {
        where.templateCategory = filters.category;
      }

      if (filters?.workflowType) {
        where.workflowType = filters.workflowType;
      }

      if (filters?.isActive !== undefined) {
        where.isActive = filters.isActive;
      }

      if (filters?.isSystemTemplate !== undefined) {
        where.isSystemTemplate = filters.isSystemTemplate;
      }

      if (filters?.search) {
        where[Op.or] = [
          { templateName: { [Op.iLike]: `%${filters.search}%` } },
          { templateCode: { [Op.iLike]: `%${filters.search}%` } },
          { templateDescription: { [Op.iLike]: `%${filters.search}%` } }
        ];
      }

      return await WorkflowTemplate.findAll({
        where,
        include: [{ model: User, as: 'creator' }],
        order: [['createdAt', 'DESC']]
      });
    } catch (error) {
      logger.error('[TemplateService] Error listing templates:', error);
      throw error;
    }
  }

  /**
   * Update template
   */
  async updateTemplate(
    templateId: string,
    userId: string,
    updateData: {
      templateName?: string;
      templateDescription?: string;
      templateCategory?: string;
      approvalLevelsConfig?: any;
      defaultTatHours?: number;
      formStepsConfig?: any;
      userFieldMappings?: any;
      dynamicApproverConfig?: any;
      isActive?: boolean;
    }
  ): Promise<WorkflowTemplate> {
    try {
      const template = await WorkflowTemplate.findByPk(templateId);
      if (!template) {
        throw new Error('Template not found');
      }

      // Check if template is system template (system templates should not be modified)
      if (template.isSystemTemplate && updateData.approvalLevelsConfig) {
        throw new Error('Cannot modify approval levels of system templates');
      }

      await template.update(updateData);

      logger.info(`[TemplateService] Updated template: ${templateId}`);
      return template;
    } catch (error) {
      logger.error('[TemplateService] Error updating template:', error);
      throw error;
    }
  }

  /**
   * Delete template (soft delete by setting isActive to false)
   */
  async deleteTemplate(templateId: string): Promise<void> {
    try {
      const template = await WorkflowTemplate.findByPk(templateId);
      if (!template) {
        throw new Error('Template not found');
      }

      // Check if template is in use
      const usageCount = await WorkflowRequest.count({
        where: { templateId }
      });

      if (usageCount > 0) {
        throw new Error(`Cannot delete template: ${usageCount} request(s) are using this template`);
      }

      // System templates cannot be deleted
      if (template.isSystemTemplate) {
        throw new Error('Cannot delete system templates');
      }

      // Soft delete by deactivating
      await template.update({ isActive: false });

      logger.info(`[TemplateService] Deleted (deactivated) template: ${templateId}`);
    } catch (error) {
      logger.error('[TemplateService] Error deleting template:', error);
      throw error;
    }
  }

  /**
   * Get active templates for workflow creation
   */
  async getActiveTemplates(): Promise<WorkflowTemplate[]> {
    try {
      return await WorkflowTemplate.findAll({
        where: { isActive: true },
        order: [['templateName', 'ASC']]
      });
    } catch (error) {
      logger.error('[TemplateService] Error getting active templates:', error);
      throw error;
    }
  }

  /**
   * Increment usage count when template is used
   */
  async incrementUsageCount(templateId: string): Promise<void> {
    try {
      await WorkflowTemplate.increment('usageCount', {
        where: { templateId }
      });
    } catch (error) {
      logger.error('[TemplateService] Error incrementing usage count:', error);
      // Don't throw - this is not essential
    }
  }
}

