import { toZonedTime } from 'date-fns-tz';
import { autoCheckoutTodaySessions } from '../services/employeeTracker';
import { toKolkataTime } from '../utils/timezone';
import CronRun, { CronRunStatus } from '../models/cronRun';
import logger from '../utils/logger';

const INTERVAL = 60 * 1000; // check every minute
const KOLKATA_TZ = 'Asia/Kolkata';
const JOB_NAME = 'auto_checkout';

let lastRunDateKey: string | null = null;

// Runs at 23:59 so it covers the whole day's check-ins while still being on
// the same date the service treats as "today".
const isRunTimeInKolkata = (now: Date): boolean => {
  const zoned = toZonedTime(now, KOLKATA_TZ);
  return zoned.getHours() === 23 && zoned.getMinutes() === 59;
};

const kolkataDateKey = (now: Date): string => toKolkataTime(now, 'yyyy-MM-dd');

export const runAutoCheckoutCron = async (): Promise<void> => {
  const now = new Date();
  if (!isRunTimeInKolkata(now)) return;

  // The interval polls every minute, so guard against firing twice inside
  // the same run minute (e.g. on a slow tick / restart).
  const runKey = kolkataDateKey(now);
  if (lastRunDateKey === runKey) return;
  lastRunDateKey = runKey;

  // Per-user results are logged inside autoCheckoutTodaySessions; here we log
  // one line for every run (even when nothing was closed) and persist a
  // CronRun record so a missed or failed night is visible.
  const startedAt = new Date();
  logger.info('[Cron] Auto-checkout run started', { runDate: runKey });

  let status: CronRunStatus = 'SUCCESS';
  let result: Record<string, unknown> | undefined;
  let errorMessage: string | undefined;

  try {
    const outcome = await autoCheckoutTodaySessions();
    result = { runDate: runKey, ...outcome };
    if (outcome.failed > 0) status = 'PARTIAL';
    logger.info(
      `[Cron] Auto-checkout run finished: ${outcome.checkedOut} closed, ${outcome.failed} failed`,
      { runDate: runKey, status },
    );
  } catch (e) {
    status = 'FAILED';
    errorMessage = (e as Error).message;
    logger.error('[Cron] Auto-checkout run failed', { runDate: runKey, error: errorMessage });
  }

  const finishedAt = new Date();
  try {
    await CronRun.create({
      job_name: JOB_NAME,
      status,
      started_at: startedAt,
      finished_at: finishedAt,
      duration_ms: finishedAt.getTime() - startedAt.getTime(),
      result,
      error: errorMessage,
    });
  } catch (e) {
    logger.error('[Cron] Failed to save auto-checkout run record', {
      runDate: runKey,
      error: (e as Error).message,
    });
  }
};

export const startAutoCheckoutCron = (): void => {
  setInterval(() => {
    runAutoCheckoutCron().catch((e) =>
      logger.error('[Cron] Auto-checkout failed', { error: (e as Error).message }),
    );
  }, INTERVAL);

  logger.info('[Cron] Auto-checkout scheduler started (daily at 23:59 Asia/Kolkata)');
};
