import { PMSchedule } from '../models/PMSchedule';
import { Contract } from '../models/Contract';
import { ComplianceDoc } from '../models/ComplianceDoc';
import { Ticket } from '../models/Ticket';
import { createPMScheduleAlert, createContractExpiryAlert, createComplianceExpiryAlert, createTicketSLAAlert } from './alertService';
import mongoose from 'mongoose';

/**
 * Check PM schedules and create alerts for schedules due soon
 */
export const checkPMSchedules = async (): Promise<void> => {
  try {
    const now = new Date();
    const nextWeek = new Date();
    nextWeek.setDate(now.getDate() + 7);

    const dueSchedules = await PMSchedule.find({
      status: 'Active',
      nextDue: { $lte: nextWeek }
    });

    for (const schedule of dueSchedules) {
      try {
        await createPMScheduleAlert(
          schedule.title,
          schedule.nextDue,
          schedule._id.toString(),
          schedule.projectId?.toString()
        );
      } catch (error) {
        console.error(`Error creating alert for PM Schedule ${schedule._id}:`, error);
      }
    }

    // console.log(`[Scheduled Alerts] Checked ${dueSchedules.length} PM schedules`);
  } catch (error) {
    // console.error('[Scheduled Alerts] Error checking PM schedules:', error);
  }
};

/**
 * Check contracts and create alerts for contracts expiring soon
 */
export const checkContracts = async (): Promise<void> => {
  try {
    const now = new Date();
    const nextMonth = new Date();
    nextMonth.setDate(now.getDate() + 30);

    // Get all active contracts
    const contracts = await Contract.find({
      status: { $in: ['active', 'Active'] },
      endDate: { $exists: true, $lte: nextMonth }
    });

    for (const contract of contracts) {
      try {
        const endDate = new Date(contract.endDate);
        const daysUntilExpiry = Math.ceil((endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
        
        // Only create alert if expiring within 30 days
        if (daysUntilExpiry <= 30) {
          await createContractExpiryAlert(
            contract.contractNumber,
            contract._id.toString(),
            daysUntilExpiry
          );
        }
      } catch (error) {
        console.error(`Error creating alert for Contract ${contract._id}:`, error);
      }
    }

    // console.log(`[Scheduled Alerts] Checked ${contracts.length} contracts`);
  } catch (error) {
    // console.error('[Scheduled Alerts] Error checking contracts:', error);
  }
};

/**
 * Check compliance documents and create alerts for documents expiring soon
 */
export const checkComplianceDocs = async (): Promise<void> => {
  try {
    const now = new Date();
    const nextMonth = new Date();
    nextMonth.setDate(now.getDate() + 30);

    // Get all compliance documents with expiry date
    const docs = await ComplianceDoc.find({
      expiryDate: { $exists: true, $lte: nextMonth }
    });

    for (const doc of docs) {
      try {
        const expiryDate = new Date(doc.expiryDate);
        const daysUntilExpiry = Math.ceil((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
        
        // Only create alert if expiring within 30 days
        if (daysUntilExpiry <= 30) {
          await createComplianceExpiryAlert(
            doc.name,
            doc._id.toString(),
            daysUntilExpiry
          );
        }
      } catch (error) {
        console.error(`Error creating alert for Compliance Doc ${doc._id}:`, error);
      }
    }

    // console.log(`[Scheduled Alerts] Checked ${docs.length} compliance documents`);
  } catch (error) {
    // console.error('[Scheduled Alerts] Error checking compliance documents:', error);
  }
};

/**
 * Check tickets and create alerts for tickets approaching SLA deadline
 */
export const checkTicketSLAs = async (): Promise<void> => {
  try {
    const now = new Date();
    const next8Hours = new Date(now.getTime() + 8 * 60 * 60 * 1000);

    // Get tickets with SLA deadline approaching or overdue
    const tickets = await Ticket.find({
      status: { $nin: ['Resolved', 'Closed'] },
      slaDeadline: { $exists: true, $lte: next8Hours }
    });

    for (const ticket of tickets) {
      try {
        const rawSla = ticket.slaDeadline;
        const slaDeadline =
          rawSla instanceof Date ? rawSla : rawSla != null ? new Date(rawSla) : undefined;

        if (!slaDeadline) continue;

        const assignedToUserId = ticket.assignedTo
          ? (typeof ticket.assignedTo === 'string'
              ? (mongoose.Types.ObjectId.isValid(ticket.assignedTo) ? new mongoose.Types.ObjectId(ticket.assignedTo) : undefined)
              : ticket.assignedTo)
          : undefined;

        await createTicketSLAAlert(
          ticket.ticketCode,
          ticket._id.toString(),
          ticket.priority,
          slaDeadline,
          assignedToUserId
        );
      } catch (error) {
        console.error(`Error creating alert for Ticket ${ticket._id}:`, error);
      }
    }

    // console.log(`[Scheduled Alerts] Checked ${tickets.length} tickets for SLA`);
  } catch (error) {
    // console.error('[Scheduled Alerts] Error checking ticket SLAs:', error);
  }
};

/**
 * Run all scheduled alert checks
 */
export const runAllScheduledAlerts = async (): Promise<void> => {
  // console.log('[Scheduled Alerts] Starting scheduled alert checks...');
  
  await Promise.all([
    checkPMSchedules(),
    checkContracts(),
    checkComplianceDocs(),
    checkTicketSLAs(),
  ]);

  // console.log('[Scheduled Alerts] Completed scheduled alert checks');
};
