import { Request, Response } from 'express';
import { ApprovalService } from '@services/approval.service';
import { DealerClaimApprovalService } from '@services/dealerClaimApproval.service';
import { ApprovalLevel } from '@models/ApprovalLevel';
import { WorkflowRequest } from '@models/WorkflowRequest';
import { validateApprovalAction } from '@validators/approval.validator';
import { ResponseHandler } from '@utils/responseHandler';
import type { AuthenticatedRequest } from '../types/express';
import { getRequestMetadata } from '@utils/requestUtils';

const approvalService = new ApprovalService();
const dealerClaimApprovalService = new DealerClaimApprovalService();

export class ApprovalController {
  async approveLevel(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      const { levelId } = req.params;
      const validatedData = validateApprovalAction(req.body);
      
      // Determine which service to use based on workflow type
      const level = await ApprovalLevel.findByPk(levelId);
      if (!level) {
        ResponseHandler.notFound(res, 'Approval level not found');
        return;
      }

      const workflow = await WorkflowRequest.findByPk(level.requestId);
      if (!workflow) {
        ResponseHandler.notFound(res, 'Workflow not found');
        return;
      }

      const workflowType = (workflow as any)?.workflowType;
      const requestMeta = getRequestMetadata(req);
      
      // Route to appropriate service based on workflow type
      let approvedLevel: any;
      if (workflowType === 'CLAIM_MANAGEMENT') {
        // Use DealerClaimApprovalService for claim management workflows
        approvedLevel = await dealerClaimApprovalService.approveLevel(
          levelId, 
          validatedData, 
          req.user.userId, 
          {
            ipAddress: requestMeta.ipAddress,
            userAgent: requestMeta.userAgent
          }
        );
      } else {
        // Use ApprovalService for custom workflows
        approvedLevel = await approvalService.approveLevel(
          levelId, 
          validatedData, 
          req.user.userId, 
          {
            ipAddress: requestMeta.ipAddress,
            userAgent: requestMeta.userAgent
          }
        );
      }
      
      if (!approvedLevel) {
        ResponseHandler.notFound(res, 'Approval level not found');
        return;
      }

      ResponseHandler.success(res, approvedLevel, 'Approval level updated successfully');
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      ResponseHandler.error(res, 'Failed to update approval level', 400, errorMessage);
    }
  }

  async getCurrentApprovalLevel(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      
      // Determine which service to use based on workflow type
      const workflow = await WorkflowRequest.findByPk(id);
      if (!workflow) {
        ResponseHandler.notFound(res, 'Workflow not found');
        return;
      }

      const workflowType = (workflow as any)?.workflowType;
      
      // Route to appropriate service based on workflow type
      let level: any;
      if (workflowType === 'CLAIM_MANAGEMENT') {
        level = await dealerClaimApprovalService.getCurrentApprovalLevel(id);
      } else {
        level = await approvalService.getCurrentApprovalLevel(id);
      }
      
      ResponseHandler.success(res, level, 'Current approval level retrieved successfully');
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      ResponseHandler.error(res, 'Failed to get current approval level', 500, errorMessage);
    }
  }

  async getApprovalLevels(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      
      // Determine which service to use based on workflow type
      const workflow = await WorkflowRequest.findByPk(id);
      if (!workflow) {
        ResponseHandler.notFound(res, 'Workflow not found');
        return;
      }

      const workflowType = (workflow as any)?.workflowType;
      
      // Route to appropriate service based on workflow type
      let levels: any[];
      if (workflowType === 'CLAIM_MANAGEMENT') {
        levels = await dealerClaimApprovalService.getApprovalLevels(id);
      } else {
        levels = await approvalService.getApprovalLevels(id);
      }
      
      ResponseHandler.success(res, levels, 'Approval levels retrieved successfully');
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      ResponseHandler.error(res, 'Failed to get approval levels', 500, errorMessage);
    }
  }
}
