/* Auto-poll worker for ZKTeco machines (started by app.js via tsx).
   Every minute, polls each active ZK_POLL machine whose pollMinutes has
   elapsed. Failures never crash the loop — devices go offline all the
   time; the machine simply waits for the next round. */

import { prisma } from "../src/lib/prisma";
import { zkSync } from "../src/lib/zk-poll";

const TICK_MS = 60_000;
const lastRun = new Map<number, number>();

async function tick() {
  const machines = await prisma.attendanceMachine.findMany({
    where: { isActive: true, mode: "ZK_POLL", ipAddress: { not: null }, pollMinutes: { not: null } },
    select: { id: true, name: true, pollMinutes: true, lastSeenAt: true },
  }).catch(() => [] as { id: number; name: string; pollMinutes: number | null; lastSeenAt: Date | null }[]);

  for (const m of machines) {
    const every = Math.max(1, m.pollMinutes ?? 5) * 60_000;
    const last = lastRun.get(m.id) ?? m.lastSeenAt?.getTime() ?? 0;
    if (Date.now() - last < every) continue;
    lastRun.set(m.id, Date.now());
    const res = await zkSync(m.id);
    if (res.ok) {
      console.log(`[zk-autopoll] ${m.name}: +${res.created} punches (${res.matched} matched, ${res.unmatched} unmatched)`);
    } else if (res.error !== "DEVICE_UNREACHABLE") {
      console.warn(`[zk-autopoll] ${m.name}: ${res.error}`);
    }
  }
}

async function main() {
  console.log("[zk-autopoll] watching attendance machines");
  const run = () => tick().catch(() => undefined);
  run();
  setInterval(run, TICK_MS);
}

main().catch(() => process.exit(1));
