import { createHash } from "node:crypto";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";

import { afterEach, describe, expect, it } from "vitest";

import { loadConfiguredRuntimeAssets } from "../../apps/api/src/runtime-assets.js";

const temporaryDirectories: string[] = [];

afterEach(() => {
  for (const directory of temporaryDirectories.splice(0)) {
    if (resolve(directory).startsWith(resolve(tmpdir()))) rmSync(directory, { force: true, recursive: true });
  }
});

function fixture() {
  const base = mkdtempSync(join(tmpdir(), "dada-postv1-assets-"));
  temporaryDirectories.push(base);
  const assetRoot = join(base, "assets");
  const dataRoot = join(base, "data");
  const configFile = join(base, "instance.json");
  const trustedManifestPath = join(base, "trusted-manifest.json");
  const bytes = Buffer.from("synthetic sticker bytes");
  const entry = {
    assetId: "STK001",
    mimeType: "image/png",
    relativePath: "p0a-static-v1/STK001.png",
    resourceVersion: "p0a-static-v1",
    rootRef: "p0a_runtime_assets",
    sha256: createHash("sha256").update(bytes).digest("hex"),
  };
  const manifest = {
    counts: { dynamic_fonts: 0, dynamic_images: 0, font_panel_items: 0, static_stickers: 1 },
    entries: [entry],
    root_ref: "p0a_runtime_assets",
    schema_version: "DadaRuntimeAssets/v1",
    source: "external_read_only",
  };
  mkdirSync(join(assetRoot, "p0a-static-v1"), { recursive: true });
  writeFileSync(join(assetRoot, entry.relativePath), bytes);
  writeFileSync(join(assetRoot, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);
  writeFileSync(trustedManifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
  writeFileSync(configFile, JSON.stringify({ asset_root: assetRoot }));
  return { assetRoot, configFile, dataRoot, trustedManifestPath };
}

describe("POSTV1-06 portable runtime assets", () => {
  it("activates a validated external asset root without exposing its path", () => {
    const input = fixture();
    const loaded = loadConfiguredRuntimeAssets(input);

    expect(loaded.state).toMatchObject({ configured: true, pause_reason: null, status: "active" });
    expect(loaded.publicAssets?.read("p0a-static-v1", "STK001")?.bytes.toString()).toBe("synthetic sticker bytes");
    expect(JSON.stringify(loaded.state)).not.toContain(input.assetRoot);
  });

  it("rejects a changed external manifest and leaves unrelated API features available", () => {
    const input = fixture();
    writeFileSync(join(input.assetRoot, "manifest.json"), "{}\n");
    const loaded = loadConfiguredRuntimeAssets(input);

    expect(loaded.publicAssets).toBeUndefined();
    expect(loaded.state).toMatchObject({ configured: true, pause_reason: "asset_manifest_invalid", status: "unavailable" });
  });
});
