import { Router, Request, Response } from 'express';
import { tatQueue } from '../queues/tatQueue';
import { tatWorker } from '../queues/tatWorker';
import { pauseResumeQueue } from '../queues/pauseResumeQueue';
import { pauseResumeWorker } from '../queues/pauseResumeWorker';
import { TatAlert } from '@models/TatAlert';
import { ApprovalLevel } from '@models/ApprovalLevel';
import dayjs from 'dayjs';
import logger from '@utils/logger';

const router = Router();

/**
 * Debug endpoint to check scheduled TAT jobs in the queue
 */
router.get('/tat-jobs/:requestId', async (req: Request, res: Response): Promise<void> => {
  try {
    const { requestId } = req.params;
    
    if (!tatQueue) {
      res.json({
        error: 'TAT queue not available (Redis not connected)',
        jobs: []
      });
      return;
    }

    // Get all jobs for this request
    const waitingJobs = await tatQueue.getJobs(['waiting', 'delayed', 'active']);
    const requestJobs = waitingJobs.filter(job => job.data.requestId === requestId);

    const jobDetails = requestJobs.map(job => {
      const delay = job.opts.delay || 0;
      const scheduledTime = job.timestamp ? new Date(job.timestamp + delay) : null;
      const now = new Date();
      const timeUntilFire = scheduledTime ? Math.round((scheduledTime.getTime() - now.getTime()) / 1000 / 60) : null;

      return {
        jobId: job.id,
        type: job.data.type,
        threshold: job.data.threshold,
        requestId: job.data.requestId,
        levelId: job.data.levelId,
        state: job.getState(),
        delay: delay,
        delayMinutes: Math.round(delay / 1000 / 60),
        delayHours: (delay / 1000 / 60 / 60).toFixed(2),
        timestamp: job.timestamp,
        scheduledTime: scheduledTime?.toISOString(),
        timeUntilFire: timeUntilFire ? `${timeUntilFire} minutes` : 'N/A',
        processedOn: job.processedOn ? new Date(job.processedOn).toISOString() : null,
        finishedOn: job.finishedOn ? new Date(job.finishedOn).toISOString() : null
      };
    });

    // Get TAT alerts from database
    const alerts = await TatAlert.findAll({
      where: { requestId },
      order: [['alertSentAt', 'ASC']]
    });

    const alertDetails = alerts.map((alert: any) => ({
      alertType: alert.alertType,
      thresholdPercentage: alert.thresholdPercentage,
      alertSentAt: alert.alertSentAt,
      levelStartTime: alert.levelStartTime,
      timeSinceStart: alert.levelStartTime 
        ? `${((new Date(alert.alertSentAt).getTime() - new Date(alert.levelStartTime).getTime()) / 1000 / 60 / 60).toFixed(2)} hours`
        : 'N/A',
      notificationSent: alert.notificationSent
    }));

    // Get approval level details
    const levels = await ApprovalLevel.findAll({
      where: { requestId }
    });

    const levelDetails = levels.map((level: any) => ({
      levelId: level.levelId,
      levelNumber: level.levelNumber,
      status: level.status,
      tatHours: level.tatHours,
      levelStartTime: level.levelStartTime,
      tat50AlertSent: level.tat50AlertSent,
      tat75AlertSent: level.tat75AlertSent,
      tatBreached: level.tatBreached,
      tatPercentageUsed: level.tatPercentageUsed
    }));

    res.json({
      requestId,
      currentTime: new Date().toISOString(),
      queuedJobs: jobDetails,
      jobCount: jobDetails.length,
      sentAlerts: alertDetails,
      alertCount: alertDetails.length,
      approvalLevels: levelDetails,
      testMode: process.env.TAT_TEST_MODE === 'true'
    });

  } catch (error: any) {
    logger.error('[Debug] Error checking TAT jobs:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * Debug endpoint to check all queued TAT jobs
 */
router.get('/tat-jobs', async (req: Request, res: Response): Promise<void> => {
  try {
    if (!tatQueue) {
      res.json({
        error: 'TAT queue not available (Redis not connected)',
        jobs: []
      });
      return;
    }

    const waitingJobs = await tatQueue.getJobs(['waiting', 'delayed', 'active']);

    const jobDetails = waitingJobs.map(job => {
      const delay = job.opts.delay || 0;
      const scheduledTime = job.timestamp ? new Date(job.timestamp + delay) : null;
      const now = new Date();
      const timeUntilFire = scheduledTime ? Math.round((scheduledTime.getTime() - now.getTime()) / 1000 / 60) : null;

      return {
        jobId: job.id,
        type: job.data.type,
        threshold: job.data.threshold,
        requestId: job.data.requestId,
        levelId: job.data.levelId,
        state: job.getState(),
        delay: delay,
        delayMinutes: Math.round(delay / 1000 / 60),
        delayHours: (delay / 1000 / 60 / 60).toFixed(2),
        scheduledTime: scheduledTime?.toISOString(),
        timeUntilFire: timeUntilFire ? `${timeUntilFire} minutes` : 'N/A'
      };
    });

    res.json({
      currentTime: new Date().toISOString(),
      jobs: jobDetails,
      totalJobs: jobDetails.length,
      testMode: process.env.TAT_TEST_MODE === 'true'
    });

  } catch (error: any) {
    logger.error('[Debug] Error checking all TAT jobs:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * Debug endpoint to check TAT time calculations
 */
router.post('/tat-calculate', async (req: Request, res: Response): Promise<void> => {
  try {
    const { startTime, tatHours, priority = 'STANDARD' } = req.body;

    const { addWorkingHours, addWorkingHoursExpress, calculateDelay } = await import('@utils/tatTimeUtils');
    const { getTatThresholds } = await import('../services/configReader.service');

    const start = startTime ? new Date(startTime) : new Date();
    const isExpress = priority === 'EXPRESS';
    const thresholds = await getTatThresholds();

    let threshold1Time: Date;
    let threshold2Time: Date;
    let breachTime: Date;

    if (isExpress) {
      const t1 = await addWorkingHoursExpress(start, tatHours * (thresholds.first / 100));
      const t2 = await addWorkingHoursExpress(start, tatHours * (thresholds.second / 100));
      const tBreach = await addWorkingHoursExpress(start, tatHours);
      threshold1Time = t1.toDate();
      threshold2Time = t2.toDate();
      breachTime = tBreach.toDate();
    } else {
      const t1 = await addWorkingHours(start, tatHours * (thresholds.first / 100));
      const t2 = await addWorkingHours(start, tatHours * (thresholds.second / 100));
      const tBreach = await addWorkingHours(start, tatHours);
      threshold1Time = t1.toDate();
      threshold2Time = t2.toDate();
      breachTime = tBreach.toDate();
    }

    const now = new Date();
    const delays = {
      threshold1: calculateDelay(threshold1Time),
      threshold2: calculateDelay(threshold2Time),
      breach: calculateDelay(breachTime)
    };

    res.json({
      input: {
        startTime: start.toISOString(),
        tatHours,
        priority,
        thresholds
      },
      calculations: {
        threshold1: {
          percentage: thresholds.first,
          targetTime: threshold1Time.toISOString(),
          delay: delays.threshold1,
          delayMinutes: Math.round(delays.threshold1 / 1000 / 60),
          delayHours: (delays.threshold1 / 1000 / 60 / 60).toFixed(2),
          isPast: delays.threshold1 === 0
        },
        threshold2: {
          percentage: thresholds.second,
          targetTime: threshold2Time.toISOString(),
          delay: delays.threshold2,
          delayMinutes: Math.round(delays.threshold2 / 1000 / 60),
          delayHours: (delays.threshold2 / 1000 / 60 / 60).toFixed(2),
          isPast: delays.threshold2 === 0
        },
        breach: {
          percentage: 100,
          targetTime: breachTime.toISOString(),
          delay: delays.breach,
          delayMinutes: Math.round(delays.breach / 1000 / 60),
          delayHours: (delays.breach / 1000 / 60 / 60).toFixed(2),
          isPast: delays.breach === 0
        }
      },
      currentTime: now.toISOString(),
      testMode: process.env.TAT_TEST_MODE === 'true'
    });

  } catch (error: any) {
    logger.error('[Debug] Error calculating TAT times:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * Debug endpoint to check queue and worker status
 */
router.get('/queue-status', async (req: Request, res: Response): Promise<void> => {
  try {
    const response: any = {
      timestamp: new Date().toISOString(),
      tatQueue: null,
      pauseResumeQueue: null
    };

    // TAT Queue Status
    if (tatQueue && tatWorker) {
      const [tatWaiting, tatDelayed, tatActive, tatCompleted, tatFailed] = await Promise.all([
        tatQueue.getJobCounts('waiting'),
        tatQueue.getJobCounts('delayed'),
        tatQueue.getJobCounts('active'),
        tatQueue.getJobCounts('completed'),
        tatQueue.getJobCounts('failed')
      ]);

      const tatWaitingJobs = await tatQueue.getJobs(['waiting'], 0, 10);
      const tatDelayedJobs = await tatQueue.getJobs(['delayed'], 0, 10);
      const tatActiveJobs = await tatQueue.getJobs(['active'], 0, 10);

      response.tatQueue = {
        queue: {
          name: tatQueue.name,
          available: true
        },
        worker: {
          available: true,
          running: tatWorker.isRunning(),
          paused: tatWorker.isPaused(),
          closing: tatWorker.closing,
          concurrency: tatWorker.opts.concurrency,
          autorun: tatWorker.opts.autorun
        },
        jobCounts: {
          waiting: tatWaiting.waiting,
          delayed: tatDelayed.delayed,
          active: tatActive.active,
          completed: tatCompleted.completed,
          failed: tatFailed.failed
        },
        recentJobs: {
          waiting: tatWaitingJobs.map(j => ({ id: j.id, name: j.name, data: j.data })),
          delayed: tatDelayedJobs.map(j => ({ 
            id: j.id, 
            name: j.name, 
            data: j.data,
            delay: j.opts.delay,
            timestamp: j.timestamp,
            scheduledFor: new Date(j.timestamp + (j.opts.delay || 0)).toISOString()
          })),
          active: tatActiveJobs.map(j => ({ id: j.id, name: j.name, data: j.data }))
        }
      };
    } else {
      response.tatQueue = {
        error: 'TAT Queue or Worker not available',
        queueAvailable: !!tatQueue,
        workerAvailable: !!tatWorker
      };
    }

    // Pause/Resume Queue Status
    if (pauseResumeQueue && pauseResumeWorker) {
      const [prWaiting, prDelayed, prActive, prCompleted, prFailed] = await Promise.all([
        pauseResumeQueue.getJobCounts('waiting'),
        pauseResumeQueue.getJobCounts('delayed'),
        pauseResumeQueue.getJobCounts('active'),
        pauseResumeQueue.getJobCounts('completed'),
        pauseResumeQueue.getJobCounts('failed')
      ]);

      const prWaitingJobs = await pauseResumeQueue.getJobs(['waiting'], 0, 10);
      const prDelayedJobs = await pauseResumeQueue.getJobs(['delayed'], 0, 10);
      const prActiveJobs = await pauseResumeQueue.getJobs(['active'], 0, 10);

      response.pauseResumeQueue = {
        queue: {
          name: pauseResumeQueue.name,
          available: true
        },
        worker: {
          available: true,
          running: pauseResumeWorker.isRunning(),
          paused: pauseResumeWorker.isPaused(),
          closing: pauseResumeWorker.closing,
          concurrency: pauseResumeWorker.opts.concurrency,
          autorun: pauseResumeWorker.opts.autorun
        },
        jobCounts: {
          waiting: prWaiting.waiting,
          delayed: prDelayed.delayed,
          active: prActive.active,
          completed: prCompleted.completed,
          failed: prFailed.failed
        },
        recentJobs: {
          waiting: prWaitingJobs.map(j => ({ id: j.id, name: j.name, data: j.data })),
          delayed: prDelayedJobs.map(j => ({ 
            id: j.id, 
            name: j.name, 
            data: j.data,
            delay: j.opts.delay,
            timestamp: j.timestamp,
            scheduledFor: new Date(j.timestamp + (j.opts.delay || 0)).toISOString()
          })),
          active: prActiveJobs.map(j => ({ id: j.id, name: j.name, data: j.data }))
        }
      };
    } else {
      response.pauseResumeQueue = {
        error: 'Pause/Resume Queue or Worker not available',
        queueAvailable: !!pauseResumeQueue,
        workerAvailable: !!pauseResumeWorker
      };
    }

    res.json(response);

  } catch (error: any) {
    logger.error('[Debug] Error checking queue status:', error);
    res.status(500).json({ error: error.message, stack: error.stack });
  }
});

/**
 * Debug endpoint to manually trigger a test TAT job (immediate execution)
 */
router.post('/trigger-test-tat', async (req: Request, res: Response): Promise<void> => {
  try {
    if (!tatQueue) {
      res.json({
        error: 'TAT queue not available (Redis not connected)'
      });
      return;
    }

    const { requestId, levelId, approverId } = req.body;

    // Add a test job with 5 second delay
    const job = await tatQueue.add(
      'test-threshold1',
      {
        type: 'threshold1',
        threshold: 50,
        requestId: requestId || 'test-request-123',
        levelId: levelId || 'test-level-456',
        approverId: approverId || 'test-approver-789'
      },
      {
        delay: 5000, // 5 seconds
        jobId: `test-tat-${Date.now()}`,
        removeOnComplete: false, // Keep for debugging
        removeOnFail: false
      }
    );

    res.json({
      success: true,
      message: 'Test TAT job created (will fire in 5 seconds)',
      job: {
        id: job.id,
        name: job.name,
        data: job.data,
        delay: 5000
      }
    });

  } catch (error: any) {
    logger.error('[Debug] Error triggering test TAT:', error);
    res.status(500).json({ error: error.message, stack: error.stack });
  }
});

export default router;
