import { mkdirSync, writeFileSync } from "node:fs";
import { resolve } from "node:path";

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

import type { StaticStickerCatalog } from "../../packages/static-sticker-catalog/src/index.js";
import {
  P0A_COLOR_CARD_IDS,
  P0A_DYNAMIC_STICKER_IDS,
  P0A_TEXT_TEMPLATE_IDS,
  createP0aPublicManifest,
} from "../../packages/template-registry/src/index.js";
import {
  P0A_COLOR_CARD_DEFINITIONS,
  createP0aColorCardRenderPlans,
} from "../../packages/asset-renderer/src/index.js";

type RegistryItem = {
  canonical_id: string;
  family: "color_card" | "font_panel" | "interactive_sticker" | "text_template";
  font_panel_references?: string[];
  release_status: "enabled" | "imported" | "passed";
  release_tier: "full_p0";
  renderer_id?: string;
  validation_status: "metadata_validated";
};

const referencedFontIds = [
  "FONT005", "FONT008", "FONT011", "FONT021", "FONT022",
  "FONT027", "FONT039", "FONT043", "FONT046", "FONT052",
] as const;

function numberedIds(prefix: string, count: number) {
  return Array.from({ length: count }, (_, index) => `${prefix}${String(index + 1).padStart(3, "0")}`);
}

function registryItem(canonicalId: string, family: RegistryItem["family"], patch: Partial<RegistryItem> = {}): RegistryItem {
  return {
    canonical_id: canonicalId,
    family,
    release_status: "imported",
    release_tier: "full_p0",
    validation_status: "metadata_validated",
    ...patch,
  };
}

function fullComplexManifest() {
  const textIds = [
    ...numberedIds("FLOWER", 145),
    ...numberedIds("H", 119),
    ...numberedIds("TAG", 51),
    ...numberedIds("SIMPLE", 17),
  ];
  const selectedIndex = new Map(P0A_TEXT_TEMPLATE_IDS.map((id, index) => [id, index]));
  const items: RegistryItem[] = [
    ...textIds.map((id) => registryItem(id, "text_template", {
      font_panel_references: selectedIndex.has(id)
        ? [referencedFontIds[selectedIndex.get(id)! % referencedFontIds.length]!]
        : [],
    })),
    ...numberedIds("FONT", 86).map((id) => registryItem(id, "font_panel")),
    ...numberedIds("COLOR", 16).map((id, index) => registryItem(id, "color_card", { renderer_id: `style_${String(index + 1).padStart(2, "0")}` })),
    ...numberedIds("DYN", 35).map((id) => registryItem(id, "interactive_sticker")),
  ];
  return {
    compiler: "dada-asset-compiler",
    items,
    release_version: "fixture-complex-v1",
    schema_version: "asset-release-compiler/v1",
  } as const;
}

function staticCatalog(): StaticStickerCatalog {
  const items = Array.from({ length: 1_407 }, (_, index) => {
    const stableId = `STK${String(index + 1).padStart(index + 1 < 1_000 ? 3 : 4, "0")}`;
    const part = (index % 25) + 1;
    return {
      enabled: true,
      height: 100,
      mime: "image/png" as const,
      mime_type: "image/png" as const,
      order: Math.floor(index / 25) + 1,
      original_filename: `${stableId}.png`,
      original_reference: `/api/v1/assets/public/fixture-static-v1/${stableId}`,
      origin: "bundled_read_only" as const,
      part,
      relative_path: `sticker_part${part}/${stableId}.png`,
      resource_version: "fixture-static-v1",
      sha256: String(index + 1).padStart(64, "0"),
      stable_id: stableId,
      thumbnail_reference: {
        media: "thumbnail" as const,
        resource_id: stableId,
        resource_version: "fixture-static-v1",
        url: `/api/v1/assets/public/fixture-static-v1/${stableId}?variant=thumbnail`,
      },
      width: 100,
    };
  });
  return {
    count: items.length,
    duplicate_sha256_groups: [],
    items,
    manifest_sha256: "A".repeat(64),
    part_counts: Object.fromEntries(Array.from({ length: 25 }, (_, index) => [String(index + 1), items.filter((item) => item.part === index + 1).length])),
    release_version: "fixture-static-v1",
    schema_version: "StaticStickerCatalog/v1",
  };
}

function evidence(name: string, value: unknown) {
  const root = process.env.DADA_EVIDENCE_DIR_TEMPLATE_REGISTRY;
  if (!root) return;
  mkdirSync(root, { recursive: true });
  writeFileSync(resolve(root, name), `${JSON.stringify(value, null, 2)}\n`);
}

describe("TDD-WP5-WHITE-001 P0-A public allowlist", () => {
  it("registers the complete archive while publishing only the exact P0-A allowlist", () => {
    const source = fullComplexManifest();
    const before = structuredClone(source);
    const manifest = createP0aPublicManifest({ complexManifest: source, staticCatalog: staticCatalog() });

    expect(source).toEqual(before);
    expect(P0A_TEXT_TEMPLATE_IDS).toHaveLength(32);
    expect(P0A_COLOR_CARD_IDS).toEqual(["COLOR001", "COLOR002", "COLOR008", "COLOR016"]);
    expect(P0A_DYNAMIC_STICKER_IDS).toEqual([
      "DYN001", "DYN002", "DYN003", "DYN004", "DYN007",
      "DYN008", "DYN011", "DYN012", "DYN015", "DYN016",
    ]);
    expect(manifest.counts).toEqual({
      color_cards: 4,
      dynamic_stickers: 10,
      font_panel_items: 11,
      static_parts: 25,
      static_stickers: 1_407,
      text_templates: 32,
    });
    expect(manifest.assets.text_templates.map((item) => item.canonical_id)).toEqual(P0A_TEXT_TEMPLATE_IDS);
    expect(manifest.assets.font_panel_items.map((item) => item.canonical_id)).toEqual([...referencedFontIds, "FONT081"]);
    expect(manifest.assets.color_cards.map((item) => item.canonical_id)).toEqual(P0A_COLOR_CARD_IDS);
    expect(manifest.assets.dynamic_stickers.map((item) => item.canonical_id)).toEqual(P0A_DYNAMIC_STICKER_IDS);
    expect(manifest.assets.static_stickers).toHaveLength(1_407);
    expect(manifest.assets.static_stickers.every((item) => item.part >= 1 && item.part <= 25)).toBe(true);

    const publicComplex = [
      ...manifest.assets.text_templates,
      ...manifest.assets.font_panel_items,
      ...manifest.assets.color_cards,
      ...manifest.assets.dynamic_stickers,
    ];
    expect(publicComplex.every((item) => item.release_status === "enabled"
      && item.release_tier === "alpha_whitelist"
      && item.validation_status === "passed")).toBe(true);
    const serialized = JSON.stringify(manifest);
    expect(serialized).not.toContain("FLOWER009");
    expect(serialized).not.toContain("COLOR003");
    expect(serialized).not.toContain("DYN005");
    evidence("unit-allowlist.json", { counts: manifest.counts, hidden: ["FLOWER009", "COLOR003", "DYN005"], status: "passed" });
  });

  it("rejects incomplete registration and any early full_p0 enablement", () => {
    const incomplete = fullComplexManifest();
    incomplete.items.splice(incomplete.items.findIndex((item) => item.canonical_id === "DYN035"), 1);
    expect(() => createP0aPublicManifest({ complexManifest: incomplete, staticCatalog: staticCatalog() })).toThrow(/interactive_sticker count/i);

    const early = fullComplexManifest();
    early.items.find((item) => item.canonical_id === "FLOWER009")!.release_status = "enabled";
    expect(() => createP0aPublicManifest({ complexManifest: early, staticCatalog: staticCatalog() })).toThrow(/full_p0.*enabled/i);
  });
});

describe("TDD-WP5-COL-001 shared five-color renderer input", () => {
  it("binds the four enabled layouts to one immutable palette snapshot", () => {
    const palette = ["#102030", "#405060", "#708090", "#A0B0C0", "#D0E0F0"] as const;
    const plans = createP0aColorCardRenderPlans(palette);
    expect(P0A_COLOR_CARD_DEFINITIONS.map((item) => [item.cardId, item.styleId])).toEqual([
      ["COLOR001", "style_01"], ["COLOR002", "style_02"], ["COLOR008", "style_08"], ["COLOR016", "style_16"],
    ]);
    expect(plans.map((plan) => plan.cardId)).toEqual(P0A_COLOR_CARD_IDS);
    expect(plans.every((plan) => plan.palette === plans[0]!.palette)).toBe(true);
    expect(Object.isFrozen(plans[0]!.palette)).toBe(true);
    expect(plans.every((plan) => JSON.stringify(plan.palette) === JSON.stringify(palette))).toBe(true);
    expect(() => createP0aColorCardRenderPlans(["#000000"])).toThrow(/five colors/i);
  });
});
