/**
 * Integration test for the manager dashboard "Approved This Month" card.
 *
 * Regression: the card previously counted only POs *currently* in MGR_APPROVED,
 * so POs approved this month that had moved on to payment/delivery/closure were
 * dropped from the count. The card must count every PO approved this month
 * regardless of its current (post-approval) status, and the same approval-date
 * window must be reproducible on the /history page (where the card links to).
 */
import { describe, it, expect, beforeAll, afterEach } from "vitest";

import { db } from "@/lib/db";
import { POST_APPROVAL_STATUSES } from "@/lib/utils";
import { deletePosByTitle } from "./helpers";
import type { POStatus } from "@prisma/client";

const PREFIX = "INTTEST_APPROVED_MONTH_";

let submitterId: string;
let vesselId: string;
let accountId: string;

const now = new Date();
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const midThisMonth = new Date(now.getFullYear(), now.getMonth(), 15, 12, 0, 0);
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 15, 12, 0, 0);

beforeAll(async () => {
  // Resolve any existing cost-centre / account / user from the test DB rather
  // than relying on dev-seed fixtures (the test DB is a production mirror).
  const [user, vessel, account] = await Promise.all([
    db.user.findFirstOrThrow({ where: { role: "MANAGER" } }),
    db.vessel.findFirstOrThrow(),
    db.account.findFirstOrThrow(),
  ]);
  submitterId = user.id;
  vesselId = vessel.id;
  accountId = account.id;
});

afterEach(async () => {
  await deletePosByTitle(PREFIX);
});

let seq = 0;
async function makePo(opts: { title: string; status: POStatus; approvedAt: Date | null }) {
  seq += 1;
  return db.purchaseOrder.create({
    data: {
      poNumber: `${PREFIX}${Date.now()}_${seq}`,
      title: opts.title,
      status: opts.status,
      totalAmount: 1000,
      approvedAt: opts.approvedAt,
      submitterId,
      vesselId,
      accountId,
    },
  });
}

/** Mirrors the dashboard "Approved This Month" query. */
function approvedThisMonthWhere() {
  return {
    title: { startsWith: PREFIX },
    status: { in: [...POST_APPROVAL_STATUSES] },
    approvedAt: { gte: startOfMonth },
  };
}

describe("Approved This Month count", () => {
  it("counts POs approved this month across every post-approval status", async () => {
    await makePo({ title: `${PREFIX}approved`, status: "MGR_APPROVED", approvedAt: midThisMonth });
    await makePo({ title: `${PREFIX}sent`, status: "SENT_FOR_PAYMENT", approvedAt: midThisMonth });
    await makePo({ title: `${PREFIX}partpaid`, status: "PARTIALLY_PAID", approvedAt: midThisMonth });
    await makePo({ title: `${PREFIX}paid`, status: "PAID_DELIVERED", approvedAt: midThisMonth });
    await makePo({ title: `${PREFIX}partclosed`, status: "PARTIALLY_CLOSED", approvedAt: midThisMonth });
    await makePo({ title: `${PREFIX}closed`, status: "CLOSED", approvedAt: midThisMonth });

    const count = await db.purchaseOrder.count({ where: approvedThisMonthWhere() });
    expect(count).toBe(6);
  });

  it("excludes POs approved in a previous month and POs never approved", async () => {
    await makePo({ title: `${PREFIX}closed_lastmonth`, status: "CLOSED", approvedAt: lastMonth });
    await makePo({ title: `${PREFIX}awaiting`, status: "MGR_REVIEW", approvedAt: null });
    await makePo({ title: `${PREFIX}closed_thismonth`, status: "CLOSED", approvedAt: midThisMonth });

    const count = await db.purchaseOrder.count({ where: approvedThisMonthWhere() });
    expect(count).toBe(1);
  });

  it("would have missed moved-on POs under the old MGR_APPROVED-only filter", async () => {
    // A PO approved this month that has since closed — the case from issue #32.
    await makePo({ title: `${PREFIX}moved_on`, status: "CLOSED", approvedAt: midThisMonth });

    const oldCount = await db.purchaseOrder.count({
      where: { title: { startsWith: PREFIX }, status: "MGR_APPROVED", approvedAt: { gte: startOfMonth } },
    });
    const newCount = await db.purchaseOrder.count({ where: approvedThisMonthWhere() });

    expect(oldCount).toBe(0);
    expect(newCount).toBe(1);
  });
});
