import { Request, Response } from 'express';
import { TatAlert } from '@models/TatAlert';
import { ApprovalLevel } from '@models/ApprovalLevel';
import { User } from '@models/User';
import { WorkflowRequest } from '@models/WorkflowRequest';
import logger from '@utils/logger';
import { sequelize } from '@config/database';
import { QueryTypes } from 'sequelize';
import { activityService } from '@services/activity.service';
import { getRequestMetadata } from '@utils/requestUtils';
import type { AuthenticatedRequest } from '../types/express';

/**
 * Get TAT alerts for a specific request
 */
export const getTatAlertsByRequest = async (req: Request, res: Response) => {
  try {
    const { requestId } = req.params;
    
    const alerts = await TatAlert.findAll({
      where: { requestId },
      include: [
        {
          model: ApprovalLevel,
          as: 'level',
          attributes: ['levelNumber', 'levelName', 'approverName', 'status']
        },
        {
          model: User,
          as: 'approver',
          attributes: ['userId', 'displayName', 'email', 'department']
        }
      ],
      order: [['alertSentAt', 'ASC']]
    });
    
    res.json({
      success: true,
      data: alerts
    });
  } catch (error) {
    logger.error('[TAT Controller] Error fetching TAT alerts:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch TAT alerts'
    });
  }
};

/**
 * Get TAT alerts for a specific approval level
 */
export const getTatAlertsByLevel = async (req: Request, res: Response) => {
  try {
    const { levelId } = req.params;
    
    const alerts = await TatAlert.findAll({
      where: { levelId },
      order: [['alertSentAt', 'ASC']]
    });
    
    res.json({
      success: true,
      data: alerts
    });
  } catch (error) {
    logger.error('[TAT Controller] Error fetching TAT alerts by level:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch TAT alerts'
    });
  }
};

/**
 * Get TAT compliance summary
 */
export const getTatComplianceSummary = async (req: Request, res: Response) => {
  try {
    const { startDate, endDate } = req.query;
    
    let dateFilter = '';
    if (startDate && endDate) {
      dateFilter = `AND alert_sent_at BETWEEN '${startDate}' AND '${endDate}'`;
    }
    
    const summary = await sequelize.query(`
      SELECT 
        COUNT(*) as total_alerts,
        COUNT(CASE WHEN alert_type = 'TAT_50' THEN 1 END) as alerts_50,
        COUNT(CASE WHEN alert_type = 'TAT_75' THEN 1 END) as alerts_75,
        COUNT(CASE WHEN alert_type = 'TAT_100' THEN 1 END) as breaches,
        COUNT(CASE WHEN was_completed_on_time = true THEN 1 END) as completed_on_time,
        COUNT(CASE WHEN was_completed_on_time = false THEN 1 END) as completed_late,
        ROUND(
          COUNT(CASE WHEN was_completed_on_time = true THEN 1 END) * 100.0 / 
          NULLIF(COUNT(CASE WHEN was_completed_on_time IS NOT NULL THEN 1 END), 0),
          2
        ) as compliance_percentage
      FROM tat_alerts
      WHERE 1=1 ${dateFilter}
    `, { type: QueryTypes.SELECT });
    
    res.json({
      success: true,
      data: summary[0] || {}
    });
  } catch (error) {
    logger.error('[TAT Controller] Error fetching TAT compliance summary:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch TAT compliance summary'
    });
  }
};

/**
 * Get TAT breach report
 */
export const getTatBreachReport = async (req: Request, res: Response) => {
  try {
    const breaches = await sequelize.query(`
      SELECT 
        ta.alert_id,
        ta.request_id,
        w.request_number,
        w.title as request_title,
        w.priority,
        al.level_number,
        al.approver_name,
        ta.tat_hours_allocated,
        ta.tat_hours_elapsed,
        ta.alert_sent_at,
        ta.completion_time,
        ta.was_completed_on_time,
        CASE
          WHEN ta.completion_time IS NULL THEN 'Still Pending'
          WHEN ta.was_completed_on_time = false THEN 'Completed Late'
          ELSE 'Completed On Time'
        END as completion_status
      FROM tat_alerts ta
      JOIN workflow_requests w ON ta.request_id = w.request_id
      JOIN approval_levels al ON ta.level_id = al.level_id
      WHERE ta.is_breached = true
      ORDER BY ta.alert_sent_at DESC
      LIMIT 100
    `, { type: QueryTypes.SELECT });
    
    res.json({
      success: true,
      data: breaches
    });
  } catch (error) {
    logger.error('[TAT Controller] Error fetching TAT breach report:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch TAT breach report'
    });
  }
};

/**
 * Update breach reason for a TAT alert
 */
export const updateBreachReason = async (req: Request, res: Response) => {
  try {
    const { levelId } = req.params;
    const { breachReason } = req.body;
    const userId = (req as AuthenticatedRequest).user?.userId;
    const requestMeta = getRequestMetadata(req);

    if (!userId) {
      return res.status(401).json({
        success: false,
        error: 'Unauthorized'
      });
    }

    if (!breachReason || typeof breachReason !== 'string' || breachReason.trim().length === 0) {
      return res.status(400).json({
        success: false,
        error: 'Breach reason is required'
      });
    }

    // Get the approval level to verify permissions
    const level = await ApprovalLevel.findByPk(levelId);
    if (!level) {
      return res.status(404).json({
        success: false,
        error: 'Approval level not found'
      });
    }

    // Get user to check role
    const user = await User.findByPk(userId);
    if (!user) {
      return res.status(404).json({
        success: false,
        error: 'User not found'
      });
    }

    const userRole = (user as any).role;
    const approverId = (level as any).approverId;

    // Check permissions: ADMIN, MANAGEMENT, or the approver
    const hasPermission = 
      userRole === 'ADMIN' || 
      userRole === 'MANAGEMENT' || 
      approverId === userId;

    if (!hasPermission) {
      return res.status(403).json({
        success: false,
        error: 'You do not have permission to update breach reason'
      });
    }

    // Get user details for activity logging
    const userDisplayName = (user as any).displayName || (user as any).email || 'Unknown User';
    const isUpdate = !!(level as any).breachReason; // Check if this is an update or first time
    const levelNumber = (level as any).levelNumber;
    const approverName = (level as any).approverName || 'Unknown Approver';

    // Update breach reason directly in approval_levels table
    await level.update({
      breachReason: breachReason.trim()
    });

    // Reload to get updated data
    await level.reload();

    // Log activity for the request
    const userRoleLabel = userRole === 'ADMIN' ? 'Admin' : userRole === 'MANAGEMENT' ? 'Management' : 'Approver';
    await activityService.log({
      requestId: level.requestId,
      type: 'comment', // Using comment type for breach reason entry
      user: { 
        userId: userId, 
        name: userDisplayName,
        email: (user as any).email 
      },
      timestamp: new Date().toISOString(),
      action: isUpdate ? 'Updated TAT breach reason' : 'Added TAT breach reason',
      details: `${userDisplayName} (${userRoleLabel}) ${isUpdate ? 'updated' : 'added'} TAT breach reason for ${approverName} (Level ${levelNumber}): "${breachReason.trim()}"`,
      metadata: {
        levelId: level.levelId,
        levelNumber: levelNumber,
        approverName: approverName,
        breachReason: breachReason.trim(),
        updatedByRole: userRole
      },
      ipAddress: requestMeta.ipAddress,
      userAgent: requestMeta.userAgent
    });

    logger.info(`[TAT Controller] Breach reason ${isUpdate ? 'updated' : 'added'} for level ${levelId} by user ${userId} (${userRole})`);

    return res.json({
      success: true,
      message: `Breach reason ${isUpdate ? 'updated' : 'added'} successfully`,
      data: {
        levelId: level.levelId,
        breachReason: breachReason.trim()
      }
    });
  } catch (error) {
    logger.error('[TAT Controller] Error updating breach reason:', error);
    return res.status(500).json({
      success: false,
      error: 'Failed to update breach reason'
    });
  }
};

/**
 * Get approver TAT performance
 */
export const getApproverTatPerformance = async (req: Request, res: Response) => {
  try {
    const { approverId } = req.params;
    
    const performance = await sequelize.query(`
      SELECT 
        COUNT(DISTINCT ta.level_id) as total_approvals,
        COUNT(CASE WHEN ta.alert_type = 'TAT_50' THEN 1 END) as alerts_50_received,
        COUNT(CASE WHEN ta.alert_type = 'TAT_75' THEN 1 END) as alerts_75_received,
        COUNT(CASE WHEN ta.is_breached = true THEN 1 END) as breaches,
        AVG(ta.tat_hours_elapsed) as avg_hours_taken,
        ROUND(
          COUNT(CASE WHEN ta.was_completed_on_time = true THEN 1 END) * 100.0 / 
          NULLIF(COUNT(CASE WHEN ta.was_completed_on_time IS NOT NULL THEN 1 END), 0),
          2
        ) as compliance_rate
      FROM tat_alerts ta
      WHERE ta.approver_id = :approverId
    `, { 
      replacements: { approverId },
      type: QueryTypes.SELECT 
    });
    
    res.json({
      success: true,
      data: performance[0] || {}
    });
  } catch (error) {
    logger.error('[TAT Controller] Error fetching approver TAT performance:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch approver TAT performance'
    });
  }
};

