import { INestApplication } from "@nestjs/common";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import request from "supertest";
import { buildTestApp, type TestAppHandle } from "./helpers/test-app";

describe("Providers catalog (e2e)", () => {
  let handle: TestAppHandle;
  let app: INestApplication;

  beforeAll(async () => {
    handle = await buildTestApp();
    app = handle.app;
  });

  afterAll(async () => {
    await handle.close();
  });

  it("GET /providers is public (no auth) and returns the catalog", async () => {
    const res = await request(app.getHttpServer()).get("/providers");
    expect(res.status).toBe(200);
    expect(Array.isArray(res.body.providers)).toBe(true);
    expect(res.body.providers.length).toBeGreaterThan(0);
  });

  it("includes dlocal as available with PY support and card method", async () => {
    const res = await request(app.getHttpServer()).get("/providers");
    const dlocal = res.body.providers.find((p: { id: string }) => p.id === "dlocal");
    expect(dlocal).toBeDefined();
    expect(dlocal.available).toBe(true);
    expect(dlocal.countries).toContain("PY");
    expect(dlocal.paymentMethods).toContain("card");
    expect(dlocal.modes).toEqual(expect.arrayContaining(["sandbox", "live"]));
    expect(typeof dlocal.displayName).toBe("string");
  });

  it("marks roadmap providers (bancard, pagopar, dinelco) with available=false", async () => {
    const res = await request(app.getHttpServer()).get("/providers");
    const byId = Object.fromEntries(
      res.body.providers.map((p: { id: string; available: boolean }) => [p.id, p.available]),
    );
    expect(byId.bancard).toBe(false);
    expect(byId.pagopar).toBe(false);
    expect(byId.dinelco).toBe(false);
  });

  it("never leaks internal fields beyond the documented catalog shape", async () => {
    const res = await request(app.getHttpServer()).get("/providers");
    const allowed = new Set([
      "id",
      "displayName",
      "countries",
      "paymentMethods",
      "modes",
      "available",
      "docsUrl",
    ]);
    for (const entry of res.body.providers) {
      for (const key of Object.keys(entry)) {
        expect(allowed.has(key)).toBe(true);
      }
    }
  });
});
