import { readFileSync, readdirSync, statSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";

const repo = resolve(import.meta.dirname, "../..");
function filesUnder(root: string): string[] {
  const result: string[] = [];
  for (const entry of readdirSync(root)) {
    const path = resolve(root, entry);
    if (statSync(path).isDirectory()) result.push(...filesUnder(path));
    else if (path.endsWith(".ts")) result.push(path);
  }
  return result;
}
function importsOf(path: string): string[] {
  const source = readFileSync(path, "utf8");
  return [...source.matchAll(/from\s+["']([^"']+)["']/g)].map((match) => match[1] ?? "");
}

describe("architecture fitness", () => {
  it("keeps the domain free of provider/framework SDK imports", () => {
    const forbidden =
      /^(hono|react|@kubernetes|kubernetes|@octokit|@github|fabro|@dbos|dbos|@agentclientprotocol|@modelcontextprotocol)/;
    const imports = filesUnder(resolve(repo, "packages/domain/src")).flatMap(importsOf);
    expect(imports.filter((specifier) => forbidden.test(specifier))).toEqual([]);
  });

  it("keeps gateway imports limited to runtime-neutral contracts", () => {
    const imports = filesUnder(resolve(repo, "apps/gateway/src")).flatMap(importsOf);
    expect(
      imports.filter(
        (specifier) => specifier.startsWith("@awp/") && specifier !== "@awp/contracts",
      ),
    ).toEqual([]);
  });

  it("keeps web placeholder imports limited to contracts", () => {
    const imports = filesUnder(resolve(repo, "apps/web/src")).flatMap(importsOf);
    expect(
      imports.filter(
        (specifier) => specifier.startsWith("@awp/") && specifier !== "@awp/contracts",
      ),
    ).toEqual([]);
  });

  it("has no workstation-local production paths or GOLIVE primitive", () => {
    const production = [
      ...filesUnder(resolve(repo, "apps")),
      ...filesUnder(resolve(repo, "packages")),
    ];
    const source = production.map((path) => readFileSync(path, "utf8")).join("\n");
    expect(source).not.toMatch(/\/home\/|\/Users\//);
    expect(source).not.toMatch(/\bGOLIVE\b/);
  });

  it("separates trusted publication from AgentProvider", () => {
    const source = readFileSync(
      resolve(repo, "packages/application/src/ports/providers.ts"),
      "utf8",
    );
    expect(source).toContain("export interface TrustedPublisher");
    const agent =
      source.match(
        /export interface AgentProvider[\s\S]*?export interface DurableWorkflowProvider/,
      )?.[0] ?? "";
    expect(agent).not.toContain("publish");
    expect(agent).not.toContain("CredentialReference");
  });

  it("version-controls the mandatory dependency-cruiser rules", () => {
    const config = readFileSync(resolve(repo, ".dependency-cruiser.cjs"), "utf8");
    for (const name of [
      "gateway-only-contracts",
      "web-only-contracts",
      "domain-no-outward-packages",
      "domain-no-provider-sdks",
      "gateway-no-infrastructure-sdks",
      "no-circular-package-dependencies",
    ])
      expect(config).toContain(name);
  });
});
