import { Job } from 'bullmq';
import { notificationService } from '@services/notification.service';
import { ApprovalLevel } from '@models/ApprovalLevel';
import { WorkflowRequest } from '@models/WorkflowRequest';
import { TatAlert, TatAlertType } from '@models/TatAlert';
import { activityService } from '@services/activity.service';
import logger from '@utils/logger';
import dayjs from 'dayjs';
import { calculateElapsedWorkingHours, addWorkingHours, addWorkingHoursExpress } from '@utils/tatTimeUtils';

interface TatJobData {
  type: 'threshold1' | 'threshold2' | 'breach';
  threshold: number;  // Actual percentage (e.g., 55, 80, 100)
  requestId: string;
  levelId: string;
  approverId: string;
}

/**
 * Handle TAT notification jobs
 */
export async function handleTatJob(job: Job<TatJobData>) {
  const { requestId, levelId, approverId, type, threshold } = job.data;

  logger.info(`[TAT Processor] Processing ${type} (${threshold}%) for request ${requestId}`);

  try {
    // Get approval level and workflow details
    const approvalLevel = await ApprovalLevel.findOne({
      where: { levelId }
    });

    if (!approvalLevel) {
      logger.warn(`[TAT Processor] Approval level ${levelId} not found - likely already approved/rejected`);
      return; // Skip notification for non-existent level
    }

    // Check if level is still pending (not already approved/rejected)
    if ((approvalLevel as any).status !== 'PENDING' && (approvalLevel as any).status !== 'IN_PROGRESS') {
      logger.info(`[TAT Processor] Level ${levelId} is already ${(approvalLevel as any).status}. Skipping notification.`);
      return;
    }

    const workflow = await WorkflowRequest.findOne({
      where: { requestId }
    });

    if (!workflow) {
      logger.warn(`[TAT Processor] Workflow ${requestId} not found`);
      return;
    }

    const requestNumber = (workflow as any).requestNumber;
    const title = (workflow as any).title;

    let message = '';
    let activityDetails = '';
    let emoji = '';
    let alertType: TatAlertType;
    let thresholdPercentage: number;

    // Check if level is paused - skip TAT processing if paused
    if ((approvalLevel as any).isPaused) {
      logger.info(`[TAT Processor] Skipping ${type} notification - level ${levelId} is paused`);
      return;
    }

    const tatHours = Number((approvalLevel as any).tatHours || 0);
    const levelStartTime = (approvalLevel as any).levelStartTime || (approvalLevel as any).createdAt || (approvalLevel as any).tatStartTime;
    const now = new Date();
    
    // FIXED: Use proper working hours calculation instead of calendar hours
    // This respects working hours (9 AM - 6 PM), excludes weekends for STANDARD priority, and excludes holidays
    const priority = ((workflow as any).priority || 'STANDARD').toString().toLowerCase();
    
    // Pass pause information if available
    // IMPORTANT: Check both currently paused AND previously paused/resumed levels
    // For resumed levels, we need to include pauseElapsedHours and pauseResumeDate
    // so the calculation includes pre-pause elapsed time
    const isCurrentlyPaused = (approvalLevel as any).isPaused === true;
    const wasResumed = !isCurrentlyPaused && 
      (approvalLevel as any).pauseElapsedHours !== null && 
      (approvalLevel as any).pauseElapsedHours !== undefined &&
      (approvalLevel as any).pauseResumeDate !== null;
    
    const pauseInfo = isCurrentlyPaused ? {
      isPaused: true,
      pausedAt: (approvalLevel as any).pausedAt,
      pauseElapsedHours: (approvalLevel as any).pauseElapsedHours,
      pauseResumeDate: (approvalLevel as any).pauseResumeDate
    } : wasResumed ? {
      // Level was paused but has been resumed - include pre-pause elapsed hours
      isPaused: false,
      pausedAt: null,
      pauseElapsedHours: Number((approvalLevel as any).pauseElapsedHours), // Pre-pause elapsed hours
      pauseResumeDate: (approvalLevel as any).pauseResumeDate // Actual resume timestamp
    } : undefined;
    
    const elapsedHours = await calculateElapsedWorkingHours(levelStartTime, now, priority, pauseInfo);
    let remainingHours = Math.max(0, tatHours - elapsedHours);
    
    // Calculate expected completion time using proper working hours calculation
    // EXPRESS: includes weekends but only during working hours
    // STANDARD: excludes weekends and only during working hours
    const expectedCompletionTime = priority === 'express'
      ? (await addWorkingHoursExpress(levelStartTime, tatHours)).toDate()
      : (await addWorkingHours(levelStartTime, tatHours)).toDate();

    switch (type) {
      case 'threshold1':
        emoji = '';
        alertType = TatAlertType.TAT_50;  // Keep enum for backwards compatibility
        thresholdPercentage = threshold;
        message = `${threshold}% of TAT elapsed for Request ${requestNumber}: ${title}`;
        activityDetails = `${threshold}% of TAT time has elapsed`;
        
        // Update TAT status in database with comprehensive tracking
        await ApprovalLevel.update(
          { 
            tatPercentageUsed: threshold, 
            tat50AlertSent: true,
            elapsedHours: elapsedHours,
            remainingHours: remainingHours
          },
          { where: { levelId } }
        );
        break;

      case 'threshold2':
        emoji = '';
        alertType = TatAlertType.TAT_75;  // Keep enum for backwards compatibility
        thresholdPercentage = threshold;
        message = `${threshold}% of TAT elapsed for Request ${requestNumber}: ${title}. Please take action soon.`;
        activityDetails = `${threshold}% of TAT time has elapsed - Escalation warning`;
        
        // Update TAT status in database with comprehensive tracking
        await ApprovalLevel.update(
          { 
            tatPercentageUsed: threshold, 
            tat75AlertSent: true,
            elapsedHours: elapsedHours,
            remainingHours: remainingHours
          },
          { where: { levelId } }
        );
        break;

      case 'breach':
        emoji = '';
        alertType = TatAlertType.TAT_100;
        thresholdPercentage = 100;
        message = `TAT breached for Request ${requestNumber}: ${title}. Immediate action required!`;
        activityDetails = 'TAT deadline reached - Breach notification';
        
        // When breached, ensure remaining hours is 0 (no rounding errors)
        // If elapsedHours >= tatHours, remainingHours should be exactly 0
        remainingHours = 0;
        
        // Update TAT status in database with comprehensive tracking
        await ApprovalLevel.update(
          { 
            tatPercentageUsed: 100, 
            tatBreached: true,
            elapsedHours: elapsedHours,
            remainingHours: 0 // No time remaining after breach
          },
          { where: { levelId } }
        );
        break;
    }

    // Create TAT alert record for KPI tracking and display
    try {
      await TatAlert.create({
        requestId,
        levelId,
        approverId,
        alertType,
        thresholdPercentage,
        tatHoursAllocated: tatHours,
        tatHoursElapsed: elapsedHours,
        tatHoursRemaining: remainingHours,
        levelStartTime,
        alertSentAt: now,
        expectedCompletionTime,
        alertMessage: message,
        notificationSent: true,
        notificationChannels: ['push'],
        isBreached: type === 'breach',
        metadata: {
          requestNumber,
          requestTitle: title,
          approverName: (approvalLevel as any).approverName,
          approverEmail: (approvalLevel as any).approverEmail,
          priority: (workflow as any).priority,
          levelNumber: (approvalLevel as any).levelNumber,
          testMode: process.env.TAT_TEST_MODE === 'true',
          tatTestMode: process.env.TAT_TEST_MODE === 'true'
        }
      } as any);
      
      logger.info(`[TAT Processor] ✅ Alert created: ${type} (${threshold}%)`);
    } catch (alertError: any) {
      logger.error(`[TAT Processor] ❌ Alert creation failed for ${type}: ${alertError.message}`);
    }

    // Determine notification priority based on TAT threshold
    const notificationPriority = 
      type === 'breach' ? 'URGENT' :
      type === 'threshold2' ? 'HIGH' :
      'MEDIUM';

    // Format time remaining/overdue for email
    const timeRemainingText = remainingHours > 0 
      ? `${remainingHours.toFixed(1)} hours remaining`
      : type === 'breach' 
        ? `${Math.abs(remainingHours).toFixed(1)} hours overdue`
        : 'Time exceeded';

    // Send notification to approver (with error handling to prevent job failure)
    try {
      await notificationService.sendToUsers([approverId], {
        title: type === 'breach' ? 'TAT Breach Alert' : 'TAT Reminder',
        body: message,
        requestId,
        requestNumber,
        url: `/request/${requestNumber}`,
        type: type,
        priority: notificationPriority,
        actionRequired: type === 'breach' || type === 'threshold2', // Require action for critical alerts
        metadata: {
          thresholdPercentage: thresholdPercentage,
          tatInfo: {
            thresholdPercentage: thresholdPercentage,
            timeRemaining: timeRemainingText,
            tatDeadline: expectedCompletionTime,
            assignedDate: levelStartTime,
            timeOverdue: type === 'breach' ? timeRemainingText : undefined
          }
        }
      });
      logger.info(`[TAT Processor] ✅ Notification sent to approver ${approverId} for ${type} (${threshold}%)`);
    } catch (notificationError: any) {
      logger.error(`[TAT Processor] ❌ Failed to send notification to approver ${approverId} for ${type}:`, notificationError?.message || notificationError);
      // Don't fail the job - alert is already created, notification failure is non-critical
      // The alert will still be visible in the UI even if push notification fails
    }

    // If breached, also notify the initiator (workflow creator)
    if (type === 'breach') {
      const initiatorId = (workflow as any).initiatorId;
      if (initiatorId && initiatorId !== approverId) {
        try {
          await notificationService.sendToUsers([initiatorId], {
            title: 'TAT Breach - Request Delayed',
            body: `Your request ${requestNumber}: "${title}" has exceeded its TAT. The approver has been notified.`,
            requestId,
            requestNumber,
            url: `/request/${requestNumber}`,
            type: 'tat_breach_initiator',
            priority: 'HIGH',
            actionRequired: false
          });
          logger.info(`[TAT Processor] ✅ Breach notification sent to initiator ${initiatorId}`);
        } catch (initiatorNotifyError: any) {
          logger.error(`[TAT Processor] ❌ Failed to send breach notification to initiator ${initiatorId}:`, initiatorNotifyError?.message || initiatorNotifyError);
          // Don't fail the job - notification failure is non-critical
        }
      }
    }

    // Log activity (skip if it fails - don't break the TAT notification)
    try {
      await activityService.log({
        requestId,
        type: 'sla_warning',
        user: { userId: null as any, name: 'System' }, // Use null instead of 'system' for UUID field
        timestamp: new Date().toISOString(),
        action: type === 'breach' ? 'TAT Breached' : 'TAT Warning',
        details: activityDetails
      });
      logger.info(`[TAT Processor] Activity logged for ${type}`);
    } catch (activityError: any) {
      logger.warn(`[TAT Processor] Failed to log activity (non-critical):`, activityError.message);
      // Continue - activity logging failure shouldn't break TAT notification
    }

    // 🔥 CRITICAL: Emit TAT alert to frontend via socket.io for real-time updates
    try {
      const { emitToRequestRoom } = require('../realtime/socket');
      if (emitToRequestRoom) {
        // Fetch the newly created alert to send complete data to frontend
        const newAlert = await TatAlert.findOne({
          where: { requestId, levelId, alertType },
          order: [['createdAt', 'DESC']]
        });
        
        if (newAlert) {
          emitToRequestRoom(requestId, 'tat:alert', {
            alert: newAlert,
            requestId,
            levelId,
            type,
            thresholdPercentage,
            message
          });
          logger.info(`[TAT Processor] ✅ TAT alert emitted to frontend via socket.io for request ${requestId}`);
        }
      }
    } catch (socketError) {
      logger.error(`[TAT Processor] Failed to emit TAT alert via socket:`, socketError);
      // Don't fail the job if socket emission fails
    }

    logger.info(`[TAT Processor] ✅ ${type} notification sent for request ${requestId}`);
  } catch (error) {
    logger.error(`[TAT Processor] Failed to process ${type} job:`, error);
    throw error; // Re-throw to trigger retry
  }
}

