import { createHash } from "node:crypto";

export const WP4_07_SOURCE_HASHES = Object.freeze({
  "DevelopmentPlan.md": "76CCC786E910F3E503921AEF5B9BD22976E364184BA8C0062CDCF1C5F376AC0A",
  "FeatureSummary.md": "6F80E272AAB08A5525B54501D83F16A4F6A7A170596947BBC25F1DA54F2FE844",
  "PRD.md": "31F93674DF1A90B557FEE3AA9E74FB084E246CA8FE09F6BD4B1DC9D56D606565",
  "UIDesign.md": "40A9EA29B921989877A01253A686F12A0EDE93454F8A23ADD5C0511616FCC35C",
});

export const WP4_07_ENVIRONMENT = Object.freeze({
  browser_channels: ["chrome", "msedge"],
  device_scale_factor: 1,
  locale: "zh-CN",
  timezone_id: "Asia/Shanghai",
  viewport: { height: 1080, width: 1920 },
  zoom_percent: 100,
});

export const WP4_07_VISUAL_THRESHOLDS = Object.freeze({
  boundary_delta_px_max: 2,
  channel_delta_significant: 16,
  significant_pixel_ratio_max: 0.01,
});

export const WP4_07_PERFORMANCE_BUDGETS = Object.freeze({
  autosave_serialization_p95_ms_max: 50,
  canvas_frame_p95_ms_max: 33,
  continuous_unresponsive_ms_max_exclusive: 500,
  editor_reopen_ms_max: 3_000,
  export_1080x1920_ms_max: 10_000,
  export_peak_additional_bytes_max: 1_073_741_824,
  interaction_duration_ms: 10_000,
  long_task_ms_max: 200,
  measured_runs: 5,
  pointer_to_frame_p95_ms_max: 50,
  warmup_runs: 1,
});

export const WP4_07_DYNAMIC_VALUES = Object.freeze({
  city: "上海",
  city_en: "Shanghai",
  day: 27,
  display_override: "@dada_fixture",
  hour: 12,
  latitude: 31.2304,
  longitude: 121.4737,
  minute: 0,
  month: 7,
  nickname: "@dada_fixture",
  title: "上海市",
  year: 2026,
});

const timestamp = "2026-07-27T04:00:00.000Z";
const redResourceVersion = "wp4-07-red-contract-v1";
export const WP4_07_REAL_RESOURCE_VERSIONS = Object.freeze({
  complex: "p0a-complex-v1",
  static: "p0a-static-v1",
});
const palette = ["#111111", "#F2F400", "#1769AA", "#C92A24", "#FFFFFF"];
const textTemplateIds = [
  "FLOWER001", "FLOWER003", "FLOWER005", "FLOWER008", "H003", "H004",
  "H006", "TAG001", "TAG002", "TAG003", "TAG005", "TAG051",
];
const textFontIds = [
  "FONT011", "FONT008", "FONT008", "FONT005", "FONT039", "FONT046",
  "FONT052", "FONT027", "FONT043", "FONT043", "FONT008", "FONT022",
];
const dynamicIds = [
  "DYN001", "DYN002", "DYN003", "DYN004", "DYN007",
  "DYN008", "DYN011", "DYN012", "DYN015", "DYN016",
];
const colorCards = [
  ["COLOR001", "style_01"],
  ["COLOR002", "style_02"],
  ["COLOR008", "style_08"],
  ["COLOR016", "style_16"],
];

function identity(index) {
  return `00000000-0000-4000-8000-${String(4_070_000 + index).padStart(12, "0")}`;
}

function position(index, columns, rowOffset) {
  return {
    x: Number((0.1 + (index % columns) * (0.8 / Math.max(1, columns - 1))).toFixed(4)),
    y: Number((rowOffset + Math.floor(index / columns) * 0.105).toFixed(4)),
  };
}

function common(index, type, templateOrAssetId, resourceVersion) {
  return {
    created_at: timestamp,
    element_id: identity(index),
    opacity: 1,
    position: { x: 0.5, y: 0.5 },
    resource_version: resourceVersion,
    rotation: 0,
    scale: { x: 1, y: 1 },
    style_parameters: {},
    template_or_asset_id: templateOrAssetId,
    type,
    z_index: index - 1,
  };
}

function releaseVersions(input = redResourceVersion) {
  return typeof input === "string" ? { complex: input, static: input } : input;
}

export function createWp407CanvasFixture(resourceVersions = redResourceVersion) {
  const versions = releaseVersions(resourceVersions);
  const text = textTemplateIds.map((templateId, offset) => ({
    ...common(offset + 1, "text_template", templateId, versions.complex),
    content: offset === 0 ? "DADA\n视觉预算" : `固定文字 ${String(offset + 1).padStart(2, "0")}`,
    font_size: 48,
    position: offset === 0 ? { x: 0.5, y: 0.5 } : position(offset, 4, 0.09),
    rotation: (offset % 3 - 1) * 4,
    scale: { x: 0.72, y: 0.72 },
    style_parameters: {
      background_color: "#F2F400",
      background_enabled: offset % 4 === 0,
      background_opacity: 0.9,
      default_font_id: textFontIds[offset],
      fill_color: offset % 2 === 0 ? "#111111" : "#1769AA",
      letter_spacing: 1,
      line_height: 1.2,
      stroke_color: "#FFFFFF",
      stroke_enabled: offset % 5 === 0,
      stroke_width: offset % 5 === 0 ? 2 : 0,
      text_align: "center",
    },
  }));
  const stickers = Array.from({ length: 24 }, (_, offset) => ({
    ...common(offset + 13, "static_sticker", `STK${String(offset + 1).padStart(3, "0")}`, versions.static),
    opacity: 0.84 + (offset % 4) * 0.04,
    position: position(offset, 6, 0.39),
    rotation: (offset % 5 - 2) * 6,
    scale: { x: 0.58 + (offset % 3) * 0.06, y: 0.58 + (offset % 3) * 0.06 },
    style_parameters: { flip_horizontal: offset % 7 === 0 },
  }));
  const colors = colorCards.map(([cardId, styleId], offset) => ({
    ...common(offset + 37, "color_card", cardId, versions.complex),
    colors: [...palette],
    position: { x: 0.16 + offset * 0.22, y: 0.83 },
    scale: { x: 1.25, y: 1.25 },
    style_id: styleId,
    style_parameters: { palette_algorithm_version: "mmcq-v1" },
  }));
  const dynamics = dynamicIds.map((dynamicId, offset) => ({
    ...common(offset + 41, "dynamic_sticker", dynamicId, versions.complex),
    dynamic_fields: { ...WP4_07_DYNAMIC_VALUES },
    formatted_value: dynamicId === "DYN012" ? "12:00 PM" : "@dada_fixture",
    position: { x: 0.09 + (offset % 5) * 0.205, y: 0.9 + Math.floor(offset / 5) * 0.06 },
    scale: { x: 0.55, y: 0.55 },
    style_parameters: dynamicId === "DYN012" ? { font_id: "FONT081", known_substitution: true } : {},
  }));
  return {
    background: {
      adjustments: {
        brightness: 0, contrast: 0, crop: null, filter: "none", fit: "fill",
        saturation: 0, sharpness: 0, temperature: 0,
      },
      asset_id: "00000000-0000-4000-8000-000000004079",
    },
    elements: [...text, ...stickers, ...colors, ...dynamics],
    pixel_height: 1920,
    pixel_width: 1080,
    ratio: "9:16",
    schema_version: 1,
  };
}

export function wp407FixtureContract(resourceVersions = redResourceVersion) {
  const canvas = createWp407CanvasFixture(resourceVersions);
  return {
    canvas,
    dynamic_values: WP4_07_DYNAMIC_VALUES,
    environment: WP4_07_ENVIRONMENT,
    performance_budgets: WP4_07_PERFORMANCE_BUDGETS,
    schema_version: "wp4-07-fixed-fixture/v1",
    visual_thresholds: WP4_07_VISUAL_THRESHOLDS,
  };
}

export function wp407FixtureSha256(resourceVersions = redResourceVersion) {
  return createHash("sha256").update(JSON.stringify(wp407FixtureContract(resourceVersions))).digest("hex").toUpperCase();
}

export function assertWp407Fixture(resourceVersions = redResourceVersion) {
  const fixture = wp407FixtureContract(resourceVersions);
  const counts = Object.fromEntries(["text_template", "static_sticker", "color_card", "dynamic_sticker"].map((type) => [
    type,
    fixture.canvas.elements.filter((element) => element.type === type).length,
  ]));
  if (fixture.canvas.elements.length !== 50) throw new Error("FX-CANVAS-50 must contain exactly 50 overlay elements");
  if (JSON.stringify(counts) !== JSON.stringify({ text_template: 12, static_sticker: 24, color_card: 4, dynamic_sticker: 10 })) {
    throw new Error(`FX-CANVAS-50 composition changed: ${JSON.stringify(counts)}`);
  }
  if (fixture.canvas.pixel_width !== 1080 || fixture.canvas.pixel_height !== 1920) throw new Error("export fixture dimensions changed");
  if (new Set(fixture.canvas.elements.map((element) => element.element_id)).size !== 50) throw new Error("fixture element IDs are not unique");
  if (fixture.performance_budgets.warmup_runs !== 1 || fixture.performance_budgets.measured_runs !== 5) throw new Error("measurement count changed");
  if (fixture.performance_budgets.interaction_duration_ms !== 10_000) throw new Error("interaction duration changed");
  if (fixture.environment.viewport.width !== 1920 || fixture.environment.viewport.height !== 1080 || fixture.environment.device_scale_factor !== 1) {
    throw new Error("candidate viewport or DPR changed");
  }
  return { counts, fixture_sha256: wp407FixtureSha256(resourceVersions) };
}

export const WP4_07_RED_RESOURCE_VERSION = redResourceVersion;
export const WP4_07_REQUIRED_FONT_IDS = Object.freeze([
  "FONT005", "FONT008", "FONT011", "FONT021", "FONT022", "FONT027", "FONT039", "FONT043", "FONT046", "FONT052", "FONT081",
  "15974853bc3294ef68e7e6d58fe74fd7", "46f8336813e4c48d06a1aef294fdccf6",
  "53ca6b704728520da50c145eabb2e635", "cca5efc0e02fb1bf62349bd68ef30fc1",
  "dd25b35dcb7ba4476cbaa9a9592e39e2", "e4210c9872f0c279b35273f230809821",
  "f4bfd4132df2d6be97ceabadf3853505",
]);
