import type { StaticStickerCatalog, StaticStickerCatalogItem } from "@dada/static-sticker-catalog";

export const P0A_COMPLEX_RELEASE_VERSION = "p0a-complex-v1";
export const P0A_STATIC_STICKER_RELEASE_VERSION = "p0a-static-v1";

export const P0A_TEXT_TEMPLATE_IDS = [
  "FLOWER001", "FLOWER002", "FLOWER003", "FLOWER004", "FLOWER005", "FLOWER006", "FLOWER007", "FLOWER008",
  "H001", "H002", "H003", "H004", "H005", "H006", "H007", "H008",
  "TAG001", "TAG002", "TAG003", "TAG004", "TAG005", "TAG006", "TAG007", "TAG051",
  "SIMPLE001", "SIMPLE002", "SIMPLE003", "SIMPLE004", "SIMPLE005", "SIMPLE006", "SIMPLE007", "SIMPLE008",
] as const;

// Derived from exact package-hash matches between the 32 frozen templates and the 86-item font panel.
export const P0A_REQUIRED_FONT_PANEL_IDS = [
  "FONT005", "FONT008", "FONT011", "FONT021", "FONT022", "FONT027",
  "FONT039", "FONT043", "FONT046", "FONT052", "FONT081",
] as const;

export const P0A_COLOR_CARD_IDS = ["COLOR001", "COLOR002", "COLOR008", "COLOR016"] as const;

export const P0A_DYNAMIC_STICKER_IDS = [
  "DYN001", "DYN002", "DYN003", "DYN004", "DYN007",
  "DYN008", "DYN011", "DYN012", "DYN015", "DYN016",
] as const;

export const P0A_DYNAMIC_RUNTIME_FONT_SOURCES = [
  { assetId: "15974853bc3294ef68e7e6d58fe74fd7", sourceReference: "fonts/15974853bc3294ef68e7e6d58fe74fd7", templateId: "DYN002" },
  { assetId: "46f8336813e4c48d06a1aef294fdccf6", sourceReference: "fonts/46f8336813e4c48d06a1aef294fdccf6", templateId: "DYN016" },
  { assetId: "53ca6b704728520da50c145eabb2e635", sourceReference: "fonts/53ca6b704728520da50c145eabb2e635", templateId: "DYN007" },
  { assetId: "cca5efc0e02fb1bf62349bd68ef30fc1", sourceReference: "fonts/cca5efc0e02fb1bf62349bd68ef30fc1", templateId: "DYN015" },
  { assetId: "dd25b35dcb7ba4476cbaa9a9592e39e2", sourceReference: "fonts/dd25b35dcb7ba4476cbaa9a9592e39e2", templateId: "DYN001" },
  { assetId: "e4210c9872f0c279b35273f230809821", sourceReference: "fonts/e4210c9872f0c279b35273f230809821", templateId: "DYN011" },
  { assetId: "f4bfd4132df2d6be97ceabadf3853505", sourceReference: "fonts/f4bfd4132df2d6be97ceabadf3853505", templateId: "DYN008" },
] as const;

export const P0A_DYNAMIC_RUNTIME_IMAGE_SOURCES = [
  { assetId: "DYN001-image28", sourceReference: "resource/image28.png", templateId: "DYN001" },
  { assetId: "DYN002-image29", sourceReference: "resource/image29.png", templateId: "DYN002" },
  { assetId: "DYN003-image30", sourceReference: "resource/image30.png", templateId: "DYN003" },
  { assetId: "DYN004-image32", sourceReference: "resource/image32.png", templateId: "DYN004" },
  { assetId: "DYN008-backendui0", sourceReference: "resource/backendui0.png", templateId: "DYN008" },
  { assetId: "DYN011-backendui0", sourceReference: "resource/backendui0.png", templateId: "DYN011" },
  { assetId: "DYN015-imager2", sourceReference: "resource/imager2_2.png", templateId: "DYN015" },
  { assetId: "DYN016-image21", sourceReference: "resource/image21.png", templateId: "DYN016" },
] as const;

export type RegisteredComplexFamily = "color_card" | "font_panel" | "interactive_sticker" | "text_template";

export interface RegisteredComplexAsset extends Record<string, unknown> {
  canonical_id: string;
  family: RegisteredComplexFamily;
  font_panel_references?: string[];
  release_status: string;
  release_tier: string;
  validation_status: string;
}

export interface ComplexRegistryManifest {
  items: RegisteredComplexAsset[];
  release_version: string;
  schema_version: string;
}

export interface PublicComplexAsset extends RegisteredComplexAsset {
  release_status: "enabled";
  release_tier: "alpha_whitelist";
  validation_status: "passed";
}

export interface P0aPublicManifest {
  assets: {
    color_cards: PublicComplexAsset[];
    dynamic_stickers: PublicComplexAsset[];
    font_panel_items: PublicComplexAsset[];
    static_stickers: StaticStickerCatalogItem[];
    text_templates: PublicComplexAsset[];
  };
  counts: {
    color_cards: 4;
    dynamic_stickers: 10;
    font_panel_items: 11;
    static_parts: 25;
    static_stickers: 1407;
    text_templates: 32;
  };
  release_tier: "alpha_whitelist";
  release_version: string;
  schema_version: "P0AAssetManifest/v1";
  source_versions: {
    complex: string;
    static_stickers: string;
  };
  static_part_counts: Record<string, number>;
}

const expectedFamilyCounts: Readonly<Record<RegisteredComplexFamily, number>> = {
  color_card: 16,
  font_panel: 86,
  interactive_sticker: 35,
  text_template: 332,
};

function orderedItems(items: readonly RegisteredComplexAsset[], ids: readonly string[], family: RegisteredComplexFamily) {
  const byId = new Map(items.filter((item) => item.family === family).map((item) => [item.canonical_id, item]));
  return ids.map((id) => {
    const item = byId.get(id);
    if (!item) throw new Error(`P0-A allowlist item is not registered: ${id}`);
    return item;
  });
}

function publicItem(item: RegisteredComplexAsset): PublicComplexAsset {
  return {
    ...item,
    release_status: "enabled",
    release_tier: "alpha_whitelist",
    validation_status: "passed",
  };
}

function validateFullRegistry(manifest: ComplexRegistryManifest) {
  if (manifest.schema_version !== "asset-release-compiler/v1") throw new Error("complex registry schema version is unsupported");
  const ids = new Set<string>();
  for (const item of manifest.items) {
    if (ids.has(item.canonical_id)) throw new Error(`duplicate registered asset ${item.canonical_id}`);
    ids.add(item.canonical_id);
    if (item.release_tier !== "full_p0") throw new Error(`${item.canonical_id} must remain in full_p0 before public projection`);
    if (item.release_status === "enabled") throw new Error(`full_p0 item is enabled before atomic full release: ${item.canonical_id}`);
  }
  for (const [family, expected] of Object.entries(expectedFamilyCounts) as Array<[RegisteredComplexFamily, number]>) {
    const actual = manifest.items.filter((item) => item.family === family).length;
    if (actual !== expected) throw new Error(`${family} count mismatch: expected ${expected}, received ${actual}`);
  }
}

function validateStaticCatalog(catalog: StaticStickerCatalog) {
  if (catalog.count !== 1_407 || catalog.items.length !== 1_407) throw new Error("static sticker count mismatch: expected 1407");
  const parts = new Set(catalog.items.map((item) => item.part));
  if (parts.size !== 25 || [...parts].some((part) => part < 1 || part > 25)) throw new Error("static sticker parts must be exactly part1-part25");
  if (Object.keys(catalog.part_counts).length !== 25) throw new Error("static sticker part counts must contain 25 parts");
}

function fontIdsForTemplates(templates: readonly RegisteredComplexAsset[]) {
  const referenced = new Set<string>();
  for (const template of templates) {
    for (const fontId of template.font_panel_references ?? []) referenced.add(fontId);
  }
  referenced.add("FONT081");
  return [...referenced].sort((left, right) => Number(left.slice(4)) - Number(right.slice(4)));
}

export function createP0aPublicManifest(input: {
  complexManifest: ComplexRegistryManifest;
  staticCatalog: StaticStickerCatalog;
}): P0aPublicManifest {
  validateFullRegistry(input.complexManifest);
  validateStaticCatalog(input.staticCatalog);

  const textTemplates = orderedItems(input.complexManifest.items, P0A_TEXT_TEMPLATE_IDS, "text_template");
  const derivedFontIds = fontIdsForTemplates(textTemplates);
  if (JSON.stringify(derivedFontIds) !== JSON.stringify(P0A_REQUIRED_FONT_PANEL_IDS)) {
    throw new Error(`P0-A referenced font panel mismatch: received ${derivedFontIds.join(",")}`);
  }
  const fontPanelItems = orderedItems(input.complexManifest.items, derivedFontIds, "font_panel");
  const colorCards = orderedItems(input.complexManifest.items, P0A_COLOR_CARD_IDS, "color_card");
  const dynamicStickers = orderedItems(input.complexManifest.items, P0A_DYNAMIC_STICKER_IDS, "interactive_sticker");

  return {
    assets: {
      color_cards: colorCards.map(publicItem),
      dynamic_stickers: dynamicStickers.map(publicItem),
      font_panel_items: fontPanelItems.map(publicItem),
      static_stickers: input.staticCatalog.items.map((item) => ({ ...item })),
      text_templates: textTemplates.map(publicItem),
    },
    counts: {
      color_cards: 4,
      dynamic_stickers: 10,
      font_panel_items: 11,
      static_parts: 25,
      static_stickers: 1_407,
      text_templates: 32,
    },
    release_tier: "alpha_whitelist",
    release_version: input.complexManifest.release_version,
    schema_version: "P0AAssetManifest/v1",
    source_versions: {
      complex: input.complexManifest.release_version,
      static_stickers: input.staticCatalog.release_version,
    },
    static_part_counts: { ...input.staticCatalog.part_counts },
  };
}
