import { env } from "cloudflare:test";
import { beforeEach, describe, expect, it } from "vitest";
import app from "../src/app";
import { activateTestSite, authHeaders, seedLicenseAndBucket } from "./helpers";

const SHA = "d".repeat(64);

function signDownload(token: string, sha256: string) {
  return app.request(
    "/v1/storage/blobs/sign-download",
    { method: "POST", headers: authHeaders(token), body: JSON.stringify({ sha256 }) },
    env,
  );
}

describe("POST /v1/storage/blobs/sign-download", () => {
  beforeEach(seedLicenseAndBucket);

  it("signs a GET URL for a stored blob", async () => {
    const { site_id, site_token } = await activateTestSite();
    await env.DB.prepare(
      "INSERT INTO blobs (site_id, sha256, size_bytes, status) VALUES (?, ?, 10, 'stored')",
    )
      .bind(site_id, SHA)
      .run();
    const res = await signDownload(site_token, SHA);
    expect(res.status).toBe(200);
    const body = (await res.json()) as { download_url: string; expires_at: string };
    const u = new URL(body.download_url);
    expect(u.pathname).toBe(`/wpback-test-001/s/${site_id}/blobs/${SHA}`);
    expect(u.searchParams.get("X-Amz-Signature")).toMatch(/^[a-f0-9]{64}$/);
  });

  it("returns 404 for pending blobs and for another site's blob", async () => {
    const a = await activateTestSite("https://a.tld");
    const b = await activateTestSite("https://b.tld");
    await env.DB.prepare(
      "INSERT INTO blobs (site_id, sha256, size_bytes, status) VALUES (?, ?, 10, 'pending')",
    )
      .bind(a.site_id, SHA)
      .run();
    expect((await signDownload(a.site_token, SHA)).status).toBe(404);
    expect((await signDownload(b.site_token, SHA)).status).toBe(404);
  });

  it("returns 404 for another site's stored blob (read isolation)", async () => {
    const a = await activateTestSite("https://a.tld");
    const b = await activateTestSite("https://b.tld");
    await env.DB.prepare(
      "INSERT INTO blobs (site_id, sha256, size_bytes, status) VALUES (?, ?, 10, 'stored')",
    )
      .bind(a.site_id, SHA)
      .run();
    // Le propriétaire y accède…
    expect((await signDownload(a.site_token, SHA)).status).toBe(200);
    // …l'autre site reçoit exactement le même 404 que pour un blob inexistant.
    const res = await signDownload(b.site_token, SHA);
    expect(res.status).toBe(404);
    const body = (await res.json()) as { error: { code: string } };
    expect(body.error.code).toBe("not_found");
  });
});
