import cron from "node-cron";
import { runEmployeeSync } from "../src/jobs/sync-employees";
import { runAttendanceSync } from "../src/jobs/sync-attendance";

const isDev = process.env.NODE_ENV !== "production";

console.log("\n" + "=".repeat(60));
console.log("ZKTeco Cron Runner Started");
console.log("=".repeat(60));
console.log("Environment:", isDev ? "DEVELOPMENT" : "PRODUCTION");
console.log("Current Time:", new Date().toLocaleString());
console.log("\nScheduled Jobs:");

if (isDev) {
  console.log("  DEV MODE: Every 5 minutes → employee sync");
  console.log("  DEV MODE: Every 10 minutes → attendance sync");
  console.log(
    "\nTo test immediately, set schedules to '* * * * *' (every minute)",
  );
} else {
  console.log("01:00 AM → employee sync");
  console.log("02:00 AM → yesterday attendance sync + auto-mark absent");
}
console.log("\n" + "=".repeat(60) + "\n");

function isoDate(d: Date) {
  return d.toISOString().split("T")[0];
}

function buildRangeForDate(d: Date) {
  const day = isoDate(d);
  return { startTime: `${day} 00:00:00`, endTime: `${day} 23:59:59` };
}

// ─── Employee Sync Job ────────────────────────────────────────────────────────

const employeeSchedule = isDev ? "*/5 * * * *" : "0 1 * * *";

cron.schedule(employeeSchedule, async () => {
  console.log(`\n[${new Date().toLocaleString()}] Employee sync started...`);
  try {
    const r = await runEmployeeSync();
    console.log(
      `Employee sync complete: created=${r.employeesCreated} updated=${r.employeesUpdated} errors=${r.errors.length}`,
    );
    if (r.errors.length > 0) {
      console.error("Errors:", r.errors.slice(0, 3)); // Show first 3 errors
    }
  } catch (err) {
    console.error("Employee sync failed:", err);
  }
});

console.log(`Employee sync scheduled: ${employeeSchedule}`);

// ─── Attendance Sync Job ──────────────────────────────────────────────────────

const attendanceSchedule = isDev ? "*/10 * * * *" : "0 2 * * *";

cron.schedule(attendanceSchedule, async () => {
  console.log(`\n[${new Date().toLocaleString()}] Attendance sync started...`);
  try {
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    const range = buildRangeForDate(yesterday);
    console.log(`   Syncing date: ${isoDate(yesterday)}`);

    const r = await runAttendanceSync({ ...range, markAbsent: true });
    console.log(
      `Attendance sync complete: present/late=${r.created + r.updated} absent=${r.absent} skipped=${r.skipped} errors=${r.errors.length}`,
    );
    if (r.errors.length > 0) {
      console.error("Errors:", r.errors.slice(0, 3)); // Show first 3 errors
    }
  } catch (err) {
    console.error("Attendance sync failed:", err);
  }
});

console.log(`Attendance sync scheduled: ${attendanceSchedule}`);

// ─── Heartbeat (every 30 minutes) ─────────────────────────────────────────────

cron.schedule("*/30 * * * *", () => {
  console.log(
    `Heartbeat: ${new Date().toLocaleString()} - Cron runner is alive`,
  );
});

// ─── Graceful Shutdown ────────────────────────────────────────────────────────

process.on("SIGINT", () => {
  console.log("\n\nReceived SIGINT, shutting down gracefully...");
  process.exit(0);
});

process.on("SIGTERM", () => {
  console.log("\n\nReceived SIGTERM, shutting down gracefully...");
  process.exit(0);
});

// ─── Keep Process Alive ───────────────────────────────────────────────────────

// Keep the process running indefinitely
setInterval(
  () => {
    // This keeps the Node.js event loop active
  },
  1000 * 60 * 60,
); // Check every hour (but does nothing)
