import { AppContainer } from '../container';
import { todayInCompanyTz } from '../domain/leave/dateUtils';
import { LoggerSingleton } from '../infrastructure/logger/LoggerSingleton';

/**
 * In-process schedulers (accrual, shift reminders, end-of-day absent, compensation).
 * Registered from JobProcessorFactory at bootstrap.
 */
export function registerScheduledJobs(container: AppContainer): void {
  const log = LoggerSingleton.getInstance();

  setInterval(async () => {
    const now = new Date();
    const ist = new Intl.DateTimeFormat('en-CA', {
      timeZone: 'Asia/Kolkata',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      hour12: false,
    }).formatToParts(now);
    const parts = Object.fromEntries(ist.map((p) => [p.type, p.value]));
    const day = parseInt(parts.day!, 10);
    const hour = parseInt(parts.hour!, 10);
    const minute = parseInt(parts.minute!, 10);
    const ym = `${parts.year}-${parts.month}`;

    if (day === 1 && hour === 0 && minute >= 5 && minute < 6) {
      try {
        const r = await container.leaveFacade.accrueAll(ym);
        log.info('monthly-accrual', r);
      } catch (e) {
        log.error('monthly-accrual failed', { error: String(e) });
      }
    }

    if (hour === 6 && minute === 0) {
      try {
        const today = todayInCompanyTz();
        const r = await container.attendanceFacade.syncAutoWeekdayAttendance(today, today);
        log.info('auto-weekday-attendance', r);
      } catch (e) {
        log.error('auto-weekday-attendance failed', { error: String(e) });
      }
    }

    if (hour === 9 && minute === 0) {
      try {
        const r = await container.teamShiftFacade.sendReminders();
        log.info('shift-reminder', r);
      } catch (e) {
        log.error('shift-reminder failed', { error: String(e) });
      }
    }

    if (hour === 23 && minute === 59) {
      try {
        const today = todayInCompanyTz();
        const r = await container.attendanceFacade.markAbsents(today);
        log.info('end-of-day-absent', r);
      } catch (e) {
        log.error('end-of-day-absent failed', { error: String(e) });
      }
    }
  }, 60_000);

  setInterval(async () => {
    try {
      await container.compensationFacade.expireCredits();
      await container.compensationFacade.autoElectAfter30Days();
    } catch (e) {
      log.error('compensation jobs failed', { error: String(e) });
    }
  }, 24 * 60 * 60 * 1000);
}
