import assert from "node:assert/strict";
import test from "node:test";
import { createServer } from "node:http";
import { readFile, mkdtemp, rm } from "node:fs/promises";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { sourceFiles, sourceDigest } from "../scripts/source-files.mjs";

const run = promisify(execFile);
const { default: worker } = await import("../dist/server/index.js");

test("a real Git client clones, verifies, and fetches through smart HTTP and the legacy redirect", async () => {
  const root = await mkdtemp(join(tmpdir(), "amm-git-transport-"));
  const requests = [];
  const server = createServer(async (req, res) => {
    try {
      const origin = `http://127.0.0.1:${server.address().port}`;
      const chunks = []; for await (const chunk of req) chunks.push(chunk);
      requests.push(`${req.method} ${req.url}`);
      const request = new Request(origin + req.url, { method: req.method, headers: req.headers, ...(req.method === "POST" ? { body: Buffer.concat(chunks) } : {}) });
      const response = await worker.fetch(request, { ASSETS: { fetch: async r => {
        try { return new Response(await readFile(new URL("../dist/client" + new URL(r.url).pathname, import.meta.url))); }
        catch { return new Response("Missing asset", { status: 404 }); }
      } } }, { waitUntil() {}, passThroughOnException() {} });
      res.writeHead(response.status, Object.fromEntries(response.headers)); res.end(Buffer.from(await response.arrayBuffer()));
    } catch (error) { res.writeHead(500); res.end(String(error)); }
  });
  await new Promise(resolve => server.listen(0, "127.0.0.1", resolve));
  try {
    const origin = `http://127.0.0.1:${server.address().port}`;
    const cloned = join(root, "amm-correlated-pairs-liquidity");
    await run("git", ["clone", "--verbose", origin + "/amm-correlated-pairs-liquidity.git", cloned], { timeout: 15000 });
    assert.equal(requests.length, 2, JSON.stringify(requests));
    assert.ok(requests[1].startsWith("POST"));
    await run("git", ["-C", cloned, "fsck", "--full"]);
    await run("git", ["-C", cloned, "fetch"], { timeout: 15000 });
    const hosting = JSON.parse(await readFile(join(cloned, ".openai/hosting.json"), "utf8"));
    assert.equal(hosting.project_id, undefined);
    const manifest = JSON.parse(await readFile(new URL("../lib/source-manifest.json", import.meta.url), "utf8"));
    assert.equal(sourceDigest(await sourceFiles(cloned)), manifest.sourceDigest, "The clone must contain the exact deployed source and file modes");
    assert.equal(sourceDigest(await sourceFiles(process.cwd())), manifest.sourceDigest);
    await run("git", ["clone", origin + "/source.git", join(root, "legacy")], { timeout: 15000 });
    const forbidden = await fetch(origin + "/amm-correlated-pairs-liquidity.git/info/refs?service=git-receive-pack");
    assert.equal(forbidden.status, 403);
  } finally { await new Promise(resolve => server.close(resolve)); await rm(root, { recursive: true, force: true }); }
});
