import { WorkflowRequest } from '../models/WorkflowRequest';
import { ApprovalLevel } from '../models/ApprovalLevel';
import { User } from '../models/User';
import { Participant } from '../models/Participant';
import logger from '../utils/logger';

/**
 * Interface for user reference configuration in form fields
 */
export interface UserReference {
  role: 'initiator' | 'dealer' | 'approver' | 'team_lead' | 'department_lead' | 'current_approver' | 'previous_approver';
  level?: number;  // For approver: which approval level
  field: 'name' | 'email' | 'phone' | 'department' | 'employee_id' | 'all';  // Which user field to reference
  autoPopulate: boolean;  // Auto-fill from user data
  editable: boolean;  // Can user edit the auto-populated value
}

/**
 * Interface for form step configuration
 */
export interface FormStepConfig {
  stepNumber: number;
  stepName: string;
  stepDescription?: string;
  fields: FormFieldConfig[];
  userReferences?: UserReferenceConfig[];
}

export interface FormFieldConfig {
  fieldId: string;
  fieldType: string;
  label: string;
  required: boolean;
  defaultValue?: any;
  userReference?: UserReference;
}

export interface UserReferenceConfig {
  role: string;
  captureFields: string[];
  autoPopulateFrom: 'workflow' | 'user_profile' | 'approval_level';
  allowOverride: boolean;
}

/**
 * Service to resolve user references in template forms
 */
export class TemplateFieldResolver {
  /**
   * Resolve user reference fields in a step
   */
  async resolveUserReferences(
    stepConfig: FormStepConfig,
    request: WorkflowRequest,
    currentUserId: string,
    context?: {
      currentLevel?: number;
      approvers?: Map<number, ApprovalLevel>;
    }
  ): Promise<Record<string, any>> {
    const resolvedFields: Record<string, any> = {};

    try {
      for (const field of stepConfig.fields) {
        if (field.userReference) {
          const userData = await this.getUserDataForReference(
            field.userReference,
            request,
            currentUserId,
            context
          );

          if (field.userReference.autoPopulate && userData) {
            resolvedFields[field.fieldId] = this.extractUserField(
              userData,
              field.userReference.field
            );
          }
        }
      }
    } catch (error) {
      logger.error('[TemplateFieldResolver] Error resolving user references:', error);
    }

    return resolvedFields;
  }

  /**
   * Get user data based on reference configuration
   */
  private async getUserDataForReference(
    userRef: UserReference,
    request: WorkflowRequest,
    currentUserId: string,
    context?: any
  ): Promise<User | null> {
    try {
      switch (userRef.role) {
        case 'initiator':
          return await User.findByPk(request.initiatorId);

        case 'dealer':
          // Get dealer from participants
          const dealerParticipant = await Participant.findOne({
            where: {
              requestId: request.requestId,
              participantType: 'DEALER' as any,
              isActive: true
            },
            include: [{ model: User, as: 'user' }]
          });
          return dealerParticipant?.user || null;

        case 'approver':
          if (userRef.level && context?.approvers) {
            const approverLevel = context.approvers.get(userRef.level);
            if (approverLevel?.approverId) {
              return await User.findByPk(approverLevel.approverId);
            }
          }
          // Fallback to current approver
          const currentLevel = await ApprovalLevel.findOne({
            where: {
              requestId: request.requestId,
              levelNumber: context?.currentLevel || request.currentLevel,
              status: 'PENDING' as any
            }
          });
          if (currentLevel?.approverId) {
            return await User.findByPk(currentLevel.approverId);
          }
          return null;

        case 'team_lead':
          // Find team lead based on initiator's manager
          const initiator = await User.findByPk(request.initiatorId);
          if (initiator?.manager) {
            return await User.findOne({
              where: {
                email: initiator.manager,
                role: 'MANAGEMENT' as any
              }
            });
          }
          return null;

        case 'department_lead':
          const initiatorUser = await User.findByPk(request.initiatorId);
          if (initiatorUser?.department) {
            return await User.findOne({
              where: {
                department: initiatorUser.department,
                role: 'MANAGEMENT' as any
              },
              order: [['created_at', 'DESC']]
            });
          }
          return null;

        case 'current_approver':
          const currentApprovalLevel = await ApprovalLevel.findOne({
            where: {
              requestId: request.requestId,
              status: 'PENDING' as any
            },
            order: [['level_number', 'ASC']]
          });
          if (currentApprovalLevel?.approverId) {
            return await User.findByPk(currentApprovalLevel.approverId);
          }
          return null;

        case 'previous_approver':
          const previousLevel = request.currentLevel - 1;
          if (previousLevel > 0) {
            const previousApprovalLevel = await ApprovalLevel.findOne({
              where: {
                requestId: request.requestId,
                levelNumber: previousLevel
              }
            });
            if (previousApprovalLevel?.approverId) {
              return await User.findByPk(previousApprovalLevel.approverId);
            }
          }
          return null;

        default:
          return null;
      }
    } catch (error) {
      logger.error(`[TemplateFieldResolver] Error getting user data for role ${userRef.role}:`, error);
      return null;
    }
  }

  /**
   * Extract specific field from user data
   */
  private extractUserField(user: User, field: string): any {
    if (!user) return null;

    switch (field) {
      case 'name':
        return user.displayName || `${user.firstName || ''} ${user.lastName || ''}`.trim();
      case 'email':
        return user.email;
      case 'phone':
        return user.phone || user.mobilePhone;
      case 'department':
        return user.department;
      case 'employee_id':
        return user.employeeId;
      case 'all':
        return {
          name: user.displayName || `${user.firstName || ''} ${user.lastName || ''}`.trim(),
          email: user.email,
          phone: user.phone || user.mobilePhone,
          department: user.department,
          employeeId: user.employeeId
        };
      default:
        return null;
    }
  }

  /**
   * Resolve dynamic approver based on configuration
   */
  async resolveDynamicApprover(
    level: number,
    config: any,  // DynamicApproverConfig
    request: WorkflowRequest
  ): Promise<User | null> {
    if (!config?.enabled || !config?.approverSelection?.dynamicRules) {
      return null;
    }

    try {
      const rule = config.approverSelection.dynamicRules.find((r: any) => r.level === level);
      if (!rule) return null;

      const criteria = rule.selectionCriteria;

      switch (criteria.type) {
        case 'role':
          return await User.findOne({
            where: {
              role: criteria.value as any
            },
            order: [['created_at', 'DESC']]
          });

        case 'department':
          const initiator = await User.findByPk(request.initiatorId);
          const deptValue = criteria.value?.replace('${initiator.department}', initiator?.department || '') || initiator?.department;
          if (deptValue) {
            return await User.findOne({
              where: {
                department: deptValue,
                role: 'MANAGEMENT' as any
              }
            });
          }
          return null;

        case 'manager':
          const initiatorUser = await User.findByPk(request.initiatorId);
          if (initiatorUser?.manager) {
            return await User.findOne({
              where: {
                email: initiatorUser.manager
              }
            });
          }
          return null;

        default:
          return null;
      }
    } catch (error) {
      logger.error('[TemplateFieldResolver] Error resolving dynamic approver:', error);
      return null;
    }
  }
}

