import { createServer } from "node:http";
import { describe, expect, it } from "vitest";
import { issueModelGatewayCapability } from "@awp/contracts";
import { createModelGateway } from "../../apps/gateway/src/server.js";

async function listen(server: ReturnType<typeof createServer>): Promise<number> {
  await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
  const address = server.address();
  if (!address || typeof address === "string") throw new Error("server did not bind");
  return address.port;
}

describe("Attempt-scoped model gateway", () => {
  it("replaces caller routing/auth headers with signed Attempt claims and the server-owned Subrouter token", async () => {
    let observed: Record<string, string | string[] | undefined> | undefined;
    const upstream = createServer((request, response) => {
      observed = request.headers;
      response.writeHead(200, { "content-type": "application/json" });
      response.end(JSON.stringify({ ok: true }));
    });
    const upstreamPort = await listen(upstream);
    const signingSecret = "s".repeat(64);
    const gateway = createModelGateway({
      subrouterBaseUrl: `http://127.0.0.1:${upstreamPort}`,
      subrouterProxyToken: "server-owned-proxy-token",
      signingSecret,
    });
    const gatewayPort = await listen(gateway);
    try {
      const token = issueModelGatewayCapability(signingSecret, {
        attemptId: "attempt-42",
        accountId: "account-selected-by-owner",
        issuedAtSeconds: Math.floor(Date.now() / 1000),
        ttlSeconds: 3600,
      });
      const response = await fetch(`http://127.0.0.1:${gatewayPort}/v1/responses`, {
        method: "POST",
        headers: {
          authorization: `Bearer ${token}`,
          "content-type": "application/json",
          "x-subrouter-account-id": "spoofed-account",
          "x-api-key": "spoofed-secret",
        },
        body: "{}",
      });
      expect(response.status).toBe(200);
      expect(observed?.authorization).toBe("Bearer server-owned-proxy-token");
      expect(observed?.["x-subrouter-account-id"]).toBe("account-selected-by-owner");
      expect(observed?.["x-subrouter-agent"]).toBe("codex");
      expect(observed?.["x-subrouter-session"]).toBe("attempt-42");
      expect(observed?.["x-api-key"]).toBeUndefined();
    } finally {
      gateway.close();
      upstream.close();
    }
  });

  it("rejects expired capabilities and non-/v1 paths before proxying", async () => {
    let calls = 0;
    const upstream = createServer((_request, response) => {
      calls += 1;
      response.end("unexpected");
    });
    const upstreamPort = await listen(upstream);
    const signingSecret = "t".repeat(64);
    const gateway = createModelGateway({
      subrouterBaseUrl: `http://127.0.0.1:${upstreamPort}`,
      subrouterProxyToken: "proxy-token",
      signingSecret,
    });
    const gatewayPort = await listen(gateway);
    try {
      const current = Math.floor(Date.now() / 1000);
      const expired = issueModelGatewayCapability(signingSecret, {
        attemptId: "attempt-expired",
        accountId: "account-1",
        issuedAtSeconds: current - 120,
        ttlSeconds: 60,
      });
      expect(
        (
          await fetch(`http://127.0.0.1:${gatewayPort}/v1/responses`, {
            headers: { authorization: `Bearer ${expired}` },
          })
        ).status,
      ).toBe(401);
      const valid = issueModelGatewayCapability(signingSecret, {
        attemptId: "attempt-valid",
        accountId: "account-1",
      });
      expect(
        (
          await fetch(`http://127.0.0.1:${gatewayPort}/_subrouter/accounts`, {
            headers: { authorization: `Bearer ${valid}` },
          })
        ).status,
      ).toBe(404);
      expect(calls).toBe(0);
    } finally {
      gateway.close();
      upstream.close();
    }
  });

  it("routes Planning capabilities with PlanningSession/turn identity without weakening execution isolation", async () => {
    let observed: Record<string, string | string[] | undefined> | undefined;
    const upstream = createServer((request, response) => {
      observed = request.headers;
      response.writeHead(200, { "content-type": "application/json" });
      response.end(JSON.stringify({ ok: true }));
    });
    const upstreamPort = await listen(upstream);
    const signingSecret = "p".repeat(64);
    const gateway = createModelGateway({
      subrouterBaseUrl: `http://127.0.0.1:${upstreamPort}`,
      subrouterProxyToken: "server-owned-proxy-token",
      signingSecret,
    });
    const gatewayPort = await listen(gateway);
    try {
      const token = issueModelGatewayCapability(signingSecret, {
        purpose: "planning",
        planningSessionId: "planning:session-7",
        planningTurnId: "planning-turn:9",
        accountId: "account-planner",
        ttlSeconds: 900,
      });
      const response = await fetch(`http://127.0.0.1:${gatewayPort}/v1/responses`, {
        method: "POST",
        headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
        body: "{}",
      });
      expect(response.status).toBe(200);
      expect(observed?.authorization).toBe("Bearer server-owned-proxy-token");
      expect(observed?.["x-subrouter-account-id"]).toBe("account-planner");
      expect(observed?.["x-subrouter-session"]).toBe("planning:session-7:planning-turn:9");
      expect(observed?.["x-awp-model-purpose"]).toBe("planning");
      expect(observed?.["x-subrouter-agent"]).toBe("codex");
    } finally {
      gateway.close();
      upstream.close();
    }
  });
});
