// Integration tests for GET/POST /api/companies (Task 2 of
// docs/superpowers/plans/2026-07-31-local-app.md). Boots the app builder
// against a throwaway DB, hitting the admin pool the routes actually use.

import { describe, it, expect } from "vitest";
import { createTestDb } from "../helpers/db.js";
// Where the database is, resolved once for the whole run: your ADMIN_URL /
// DATABASE_URL if you set one, otherwise the PostgreSQL Balanced Sum installed on
// this machine. Every file in this directory used to carry its own copy of that
// decision, hardcoded to the Docker container that no longer exists.
import { dbUrl } from "../helpers/test-db-admin.js";
import { buildApp } from "../../server/src/app.js";

async function buildTestApp(dbName: string) {
  return buildApp({
    databaseUrl: await dbUrl(dbName, "app", "app"),
    adminDatabaseUrl: await dbUrl(dbName),
  });
}

// Unlike most suites here, these tests provision a database inside the test
// body (each one needs a pristine company list), so they carry the same
// 60s budget the rest of the suite gives its beforeAll provisioning. Even off
// the per-run template, several workers copying it at once can push a single
// CREATE DATABASE past vitest's 5s default.
const PROVISION = 60_000;

describe("GET/POST /api/companies", () => {
  it("creates a company via POST and lists it (with the pre-seeded ones) via GET", async () => {
    const db = await createTestDb();
    const app = await buildTestApp(db.dbName);
    try {
      const postRes = await app.inject({
        method: "POST", url: "/api/companies", payload: { name: "Gamma LLC" },
      });
      expect(postRes.statusCode).toBe(201);
      const created = postRes.json() as { id: string; name: string; created: boolean };
      expect(created.name).toBe("Gamma LLC");
      expect(created.created).toBe(true);

      const getRes = await app.inject({ method: "GET", url: "/api/companies" });
      expect(getRes.statusCode).toBe(200);
      const body = getRes.json() as {
        companies: Array<{ id: string; name: string; createdAt: string; entryCount: number }>;
      };
      const names = body.companies.map((c) => c.name);
      expect(names).toEqual(expect.arrayContaining(["Alpha LLC", "Beta LLC", "Gamma LLC"]));

      const gamma = body.companies.find((c) => c.name === "Gamma LLC");
      expect(gamma?.id).toBe(created.id);
      expect(gamma?.entryCount).toBe(0);
    } finally {
      await app.close();
      await db.close();
    }
  }, PROVISION);

  it("rejects an empty name with a 400 and creates nothing", async () => {
    const db = await createTestDb();
    const app = await buildTestApp(db.dbName);
    try {
      const res = await app.inject({ method: "POST", url: "/api/companies", payload: { name: "" } });
      expect(res.statusCode).toBe(400);

      const getRes = await app.inject({ method: "GET", url: "/api/companies" });
      const body = getRes.json() as { companies: Array<{ name: string }> };
      expect(body.companies).toHaveLength(2); // just the seeded Alpha/Beta
    } finally {
      await app.close();
      await db.close();
    }
  }, PROVISION);

  it("reuses the existing company+owner when POSTed again with the same name (idempotent)", async () => {
    const db = await createTestDb();
    const app = await buildTestApp(db.dbName);
    try {
      const first = await app.inject({
        method: "POST", url: "/api/companies", payload: { name: "Delta Co" },
      });
      expect(first.statusCode).toBe(201);
      const firstBody = first.json() as { id: string; created: boolean };
      expect(firstBody.created).toBe(true);

      const second = await app.inject({
        method: "POST", url: "/api/companies", payload: { name: "Delta Co" },
      });
      expect(second.statusCode).toBe(201);
      const secondBody = second.json() as { id: string; created: boolean };
      expect(secondBody.created).toBe(false);
      expect(secondBody.id).toBe(firstBody.id);

      const getRes = await app.inject({ method: "GET", url: "/api/companies" });
      const body = getRes.json() as { companies: Array<{ name: string }> };
      expect(body.companies.filter((c) => c.name === "Delta Co")).toHaveLength(1);
    } finally {
      await app.close();
      await db.close();
    }
  }, PROVISION);
});
