import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest } from "next/server";

// ── Hoisted mocks ────────────────────────────────────────────────────────────
const { mockDbExecute } = vi.hoisted(() => ({
  mockDbExecute: vi.fn(),
}));

vi.mock("@/app/db/db", () => ({
  db: {
    get execute() {
      return mockDbExecute;
    },
  },
}));

import { GET } from "./route";

// ── Helpers ──────────────────────────────────────────────────────────────────

function makeRequest(query: string) {
  return new NextRequest(
    `http://localhost/api/portfolio/785/reporting/properties${query}`,
  );
}

const props = { params: Promise.resolve({ portfolioId: "785" }) };

const dbRow = {
  id: 41,
  address: "14 Harewood Road",
  postcode: "LS17 8QT",
  epc_band: "D",
  sap: 56,
  bills: 1340,
  carbon: 3.1,
  provenance: "none",
  total: 128,
};

beforeEach(() => {
  mockDbExecute.mockReset();
});

// ── Tests ────────────────────────────────────────────────────────────────────

describe("GET reporting drill-down properties", () => {
  it("rejects an unknown filter", async () => {
    const res = await GET(makeRequest("?filter=vibes"), props);
    expect(res.status).toBe(400);
    expect(await res.json()).toEqual({ error: "Invalid filter" });
  });

  it("rejects a band filter without a valid band", async () => {
    const res = await GET(makeRequest("?filter=band&band=Z"), props);
    expect(res.status).toBe(400);
    expect(await res.json()).toEqual({ error: "Invalid band" });
  });

  it("rejects a measure filter without its scenario and measure type", async () => {
    const res = await GET(makeRequest("?filter=measure"), props);
    expect(res.status).toBe(400);
    expect(await res.json()).toEqual({
      error: "measure filter requires scenarioId and measureType",
    });
  });

  it("lists the homes behind a band with pagination metadata", async () => {
    mockDbExecute.mockResolvedValueOnce({ rows: [dbRow] });
    const res = await GET(makeRequest("?filter=band&band=D"), props);
    expect(res.status).toBe(200);
    expect(await res.json()).toEqual({
      properties: [
        {
          id: 41,
          address: "14 Harewood Road",
          postcode: "LS17 8QT",
          epcBand: "D",
          sap: 56,
          bills: 1340,
          carbon: 3.1,
          provenance: "none",
        },
      ],
      total: 128,
      page: 1,
      pageSize: 25,
    });
  });

  it("caps the page size at 100", async () => {
    mockDbExecute.mockResolvedValueOnce({ rows: [] });
    const res = await GET(
      makeRequest("?filter=estimated&pageSize=500"),
      props,
    );
    const body = await res.json();
    expect(body.pageSize).toBe(100);
  });
});
