import { describe, it, expect, beforeAll, afterAll } from "vitest";
import Fastify from "fastify";
import jwt from "jsonwebtoken";
import prisma from "../config/database";
import { config } from "../config/env";
import dashboardRoutes from "../routes/admin/dashboard";

// ---------------------------------------------------------------------------
// Regression test for the "Docházka dnes" / "Přítomní dnes" dashboard window.
//
// attendance.shift_date is @db.Date and Prisma truncates a filter Date to its
// UTC date part. The dashboard used local-midnight boundaries
// (new Date(y, m, d) = 22:00/23:00 UTC of the PREVIOUS day under
// TZ=Europe/Prague), which truncated to [yesterday, today) — today's punches
// matched zero rows and everyone showed as absent. The boundaries must be
// UTC-midnight instants of the LOCAL calendar day.
//
// Unlike the other suites this one has to use the REAL current date (the
// route computes "today" internally), so fixtures are tracked by id and
// deleted in afterAll.
// ---------------------------------------------------------------------------

let app: Awaited<ReturnType<typeof buildApp>>;
let adminUserId: number;
let adminToken: string;
const createdIds: number[] = [];

async function buildApp() {
  const a = Fastify({ logger: false });
  await a.register(dashboardRoutes, { prefix: "/api/admin/dashboard" });
  return a;
}

beforeAll(async () => {
  app = await buildApp();

  const admin = await prisma.users.findFirst({
    where: { roles: { name: "admin" } },
    include: { roles: true },
  });
  if (!admin) throw new Error("Test setup: admin user not found");
  adminUserId = admin.id;
  adminToken = jwt.sign(
    { sub: admin.id, username: admin.username, role: "admin" },
    config.jwt.secret,
    { expiresIn: "15m" },
  );
});

afterAll(async () => {
  if (createdIds.length) {
    await prisma.attendance.deleteMany({ where: { id: { in: createdIds } } });
  }
  if (app) await app.close();
});

describe("GET /api/admin/dashboard — today's attendance window", () => {
  it("counts a punched-in user as present (local-noon @db.Date row)", async () => {
    const now = new Date();
    // The attendance regime stores shift_date at LOCAL NOON (so the UTC date
    // part equals the Prague calendar date) — same as punchAction does.
    const row = await prisma.attendance.create({
      data: {
        user_id: adminUserId,
        shift_date: new Date(
          now.getFullYear(),
          now.getMonth(),
          now.getDate(),
          12,
          0,
          0,
        ),
        leave_type: "work",
        arrival_time: now,
        departure_time: null,
        notes: "dashboard_window_test",
      },
    });
    createdIds.push(row.id);

    const res = await app.inject({
      method: "GET",
      url: "/api/admin/dashboard",
      headers: { Authorization: `Bearer ${adminToken}` },
    });

    expect(res.statusCode).toBe(200);
    const body = res.json();
    expect(body.success).toBe(true);

    const attendance = body.data.attendance;
    expect(attendance).toBeTruthy();
    const me = attendance.users.find(
      (u: { user_id: number }) => u.user_id === adminUserId,
    );
    expect(me).toBeTruthy();
    expect(me.status).toBe("in");
    expect(attendance.present_today).toBeGreaterThanOrEqual(1);
  });
});
