import { resolve } from "node:path";
import SwaggerParser from "@apidevtools/swagger-parser";
import { describe, it, expect, beforeAll } from "vitest";
import {
  DASHBOARD_MOCKUP_PERSONAS,
  DASHBOARD_PERSONA_IDS,
} from "@/lib/fixtures/dashboard-mockup-personas";
import { mapDashboardResponse } from "@/lib/farmer-dashboard";
import { handleDevFarmerDashboard } from "@/lib/dev-api-mock";
import {
  assertFarmerDashboardV2Persona,
  assertFinanceModuleV2,
  assertIdentityModuleV2,
  assertInputsModuleV2,
} from "./schema-assert";

const DASHBOARD_V2_SPEC = resolve(__dirname, "../../specs/contracts/dashboard-v2.openapi.yaml");

describe("Dashboard v2 OpenAPI contract", () => {
  let api: Awaited<ReturnType<typeof SwaggerParser.validate>>;

  beforeAll(async () => {
    api = await SwaggerParser.validate(DASHBOARD_V2_SPEC, { resolve: { external: true } });
  });

  it("validates dashboard-v2.openapi.yaml with external refs", () => {
    const schemas = (api as { components?: { schemas?: Record<string, unknown> } }).components?.schemas ?? {};
    expect(schemas.FarmerDashboardResponseV2).toBeDefined();
    expect(schemas.IdentityModuleV2).toBeDefined();
    expect(schemas.FinanceModuleV2).toBeDefined();
    expect(schemas.InputsModuleV2).toBeDefined();
  });

  it("exposes GET /farmer/dashboard path", () => {
    const paths = (api as { paths?: Record<string, unknown> }).paths ?? {};
    expect(paths["/farmer/dashboard"]).toBeDefined();
  });
});

describe("Dashboard v2 fixture personas (G0 single source of truth)", () => {
  it("islomjon persona satisfies IdentityModuleV2 shape", () => {
    const persona = DASHBOARD_MOCKUP_PERSONAS.islomjon;
    expect(() => assertFarmerDashboardV2Persona(persona, "identity")).not.toThrow();
    expect(persona.identity?.farmerId).toBe("AGID-FMR-00142");
    expect(persona.identity?.gis?.areaHa).toBe(4.52);
    expect(persona.identity?.compliance).toHaveLength(6);
  });

  it("agrobank-case persona satisfies FinanceModuleV2 shape", () => {
    const persona = DASHBOARD_MOCKUP_PERSONAS.agrobankCase;
    expect(() => assertFarmerDashboardV2Persona(persona, "finance")).not.toThrow();
    expect(persona.finance?.eligibilityScore).toBe(78);
    expect(persona.finance?.routedInstitution?.name).toBe("Agrobank (UZ)");
    expect(persona.finance?.sla?.remainingHours).toBe(18);
  });

  it("burkina-inputs persona satisfies InputsModuleV2 shape", () => {
    const persona = DASHBOARD_MOCKUP_PERSONAS.burkinaInputs;
    expect(() => assertFarmerDashboardV2Persona(persona, "inputs")).not.toThrow();
    expect(persona.inputs?.kpis?.seed).toBe(12);
    expect(persona.inputs?.catalog?.length).toBeGreaterThan(0);
    expect(persona.inputs?.delivery?.status).toBe("in_transit");
  });

  it("mapDashboardResponse passes through v2 identity fields", () => {
    const mapped = mapDashboardResponse(DASHBOARD_MOCKUP_PERSONAS.islomjon);
    expect(mapped.identity?.farmerId).toBe("AGID-FMR-00142");
    expect(mapped.identity?.gis?.areaHa).toBe(4.52);
    expect(mapped.identity?.yieldHistory).toHaveLength(5);
    expect(mapped.identity?.compliance).toHaveLength(6);
  });

  it("mapDashboardResponse passes through v2 finance fields", () => {
    const mapped = mapDashboardResponse(DASHBOARD_MOCKUP_PERSONAS.agrobankCase);
    expect(mapped.finance?.eligibilityScore).toBe(78);
    expect(mapped.finance?.bankMatches).toHaveLength(4);
    expect(mapped.finance?.documents).toHaveLength(7);
  });

  it("mapDashboardResponse passes through v2 inputs fields", () => {
    const mapped = mapDashboardResponse(DASHBOARD_MOCKUP_PERSONAS.burkinaInputs);
    expect(mapped.inputs?.kpis?.vouchers).toBe(2);
    expect(mapped.inputs?.suppliers).toHaveLength(3);
    expect(mapped.inputs?.voucher?.code).toBe("VCH-2026-8842");
  });
});

describe("Dashboard v2 module schema assertions", () => {
  it("assertIdentityModuleV2 accepts minimal gis block", () => {
    expect(() =>
      assertIdentityModuleV2({
        farmerId: "AGID-FMR-TEST",
        gis: { areaHa: 1, lat: 41.3, lng: 69.2 },
      }),
    ).not.toThrow();
  });

  it("assertFinanceModuleV2 rejects invalid eligibilityScore type", () => {
    expect(() => assertFinanceModuleV2({ eligibilityScore: "78" })).toThrow();
  });

  it("assertInputsModuleV2 requires numeric kpi fields", () => {
    expect(() =>
      assertInputsModuleV2({
        kpis: { seed: 1, fertiliser: 2, equipment: 3, vouchers: 4, inTransit: "1" },
      }),
    ).toThrow();
  });
});

/**
 * Integration gate — dev-api-mock returns persona payloads for seeded userIds.
 */
describe("Dashboard v2 dev-mock persona wiring", () => {
  it("handleDevFarmerDashboard returns islomjon v2 identity for persona userId", () => {
    const { status, data } = handleDevFarmerDashboard(DASHBOARD_PERSONA_IDS.islomjon);
    expect(status).toBe(200);
    assertFarmerDashboardV2Persona(data, "identity");
  });

  it("handleDevFarmerDashboard returns agrobank v2 finance for persona userId", () => {
    const { status, data } = handleDevFarmerDashboard(DASHBOARD_PERSONA_IDS.agrobankCase);
    expect(status).toBe(200);
    assertFarmerDashboardV2Persona(data, "finance");
  });

  it("handleDevFarmerDashboard returns burkina v2 inputs for persona userId", () => {
    const { status, data } = handleDevFarmerDashboard(DASHBOARD_PERSONA_IDS.burkinaInputs);
    expect(status).toBe(200);
    assertFarmerDashboardV2Persona(data, "inputs");
  });
});
