import type { CanvasState } from "@dada/shared-contracts";
import { P0A_COMPLEX_RELEASE_VERSION } from "@dada/template-registry";

import { fontOption, type FontOption } from "./text-assets.js";
import type { DynamicTemplateId } from "./dynamic-provider.js";

type CanvasElement = CanvasState["elements"][number];

export type DynamicTextValue =
  | "city"
  | "city_en"
  | "day"
  | "hour"
  | "latitude_dms"
  | "longitude_dms"
  | "meridiem"
  | "minute"
  | "month"
  | "month_en"
  | "nickname"
  | "time"
  | "title"
  | "year_short";

export interface DynamicImageLayer {
  assetId: string;
  height: number;
  width: number;
  x: number;
  y: number;
}

export interface DynamicTextLayer {
  align: "center" | "left";
  color: string;
  fontId: string;
  fontSize: number;
  value: DynamicTextValue;
  x: number;
  y: number;
}

export interface DynamicRenderModel {
  halfSize: { height: number; width: number };
  imageLayers: readonly DynamicImageLayer[];
  sourceCandidateId: string;
  textLayers: readonly DynamicTextLayer[];
}

export const DYNAMIC_RESOURCE_VERSION = P0A_COMPLEX_RELEASE_VERSION;

const dynamicFont = (fontId: string): FontOption => ({
  displayName: fontId,
  fontId,
  url: `/api/v1/assets/public/${DYNAMIC_RESOURCE_VERSION}/${fontId}`,
});

export const DYNAMIC_FONT_OPTIONS: readonly FontOption[] = [
  dynamicFont("15974853bc3294ef68e7e6d58fe74fd7"),
  dynamicFont("46f8336813e4c48d06a1aef294fdccf6"),
  dynamicFont("53ca6b704728520da50c145eabb2e635"),
  dynamicFont("cca5efc0e02fb1bf62349bd68ef30fc1"),
  dynamicFont("dd25b35dcb7ba4476cbaa9a9592e39e2"),
  dynamicFont("e4210c9872f0c279b35273f230809821"),
  dynamicFont("f4bfd4132df2d6be97ceabadf3853505"),
] as const;

export const DYNAMIC_RENDER_MODELS: Readonly<Record<DynamicTemplateId, DynamicRenderModel>> = {
  DYN001: {
    halfSize: { height: 42, width: 130 },
    imageLayers: [{ assetId: "DYN001-image28", height: 67, width: 219, x: -17.562, y: 2.203 }],
    sourceCandidateId: "l_POI01",
    textLayers: [{ align: "center", color: "#FFFFFF", fontId: "dd25b35dcb7ba4476cbaa9a9592e39e2", fontSize: 21, value: "title", x: 0, y: 0 }],
  },
  DYN002: {
    halfSize: { height: 48, width: 215 },
    imageLayers: [{ assetId: "DYN002-image29", height: 77, width: 232, x: 94.5, y: 0.5 }],
    sourceCandidateId: "l_POI02",
    textLayers: [
      { align: "left", color: "#FFFFFF", fontId: "15974853bc3294ef68e7e6d58fe74fd7", fontSize: 19, value: "title", x: -94.5, y: 10.5 },
      { align: "left", color: "#FFFFFF", fontId: "15974853bc3294ef68e7e6d58fe74fd7", fontSize: 10, value: "city_en", x: 0, y: 36 },
    ],
  },
  DYN003: {
    halfSize: { height: 54, width: 215 },
    imageLayers: [{ assetId: "DYN003-image30", height: 85, width: 235, x: -93.857, y: -23.635 }],
    sourceCandidateId: "l_POI03",
    textLayers: [
      { align: "left", color: "#FFFFFF", fontId: "dd25b35dcb7ba4476cbaa9a9592e39e2", fontSize: 18, value: "title", x: -54, y: 9 },
      { align: "left", color: "#FFFFFF", fontId: "dd25b35dcb7ba4476cbaa9a9592e39e2", fontSize: 24, value: "city", x: -53, y: -16 },
    ],
  },
  DYN004: {
    halfSize: { height: 48, width: 180 },
    imageLayers: [{ assetId: "DYN004-image32", height: 76, width: 39, x: -21.067, y: -1 }],
    sourceCandidateId: "l_POI04",
    textLayers: [
      { align: "left", color: "#FFFFFF", fontId: "dd25b35dcb7ba4476cbaa9a9592e39e2", fontSize: 26, value: "city", x: -28, y: 0 },
      { align: "left", color: "#FFFFFF", fontId: "15974853bc3294ef68e7e6d58fe74fd7", fontSize: 14, value: "latitude_dms", x: -29.844, y: 36 },
      { align: "left", color: "#FFFFFF", fontId: "15974853bc3294ef68e7e6d58fe74fd7", fontSize: 14, value: "longitude_dms", x: 71.523, y: 36 },
    ],
  },
  DYN007: {
    halfSize: { height: 34, width: 190 },
    imageLayers: [],
    sourceCandidateId: "diaoyu",
    textLayers: [{ align: "center", color: "#295E8B", fontId: "53ca6b704728520da50c145eabb2e635", fontSize: 50, value: "nickname", x: 0, y: 0 }],
  },
  DYN008: {
    halfSize: { height: 180, width: 140 },
    imageLayers: [{ assetId: "DYN008-backendui0", height: 185, width: 5, x: -125, y: 0 }],
    sourceCandidateId: "l_shijian2",
    textLayers: [
      { align: "left", color: "#FFFFFF", fontId: "f4bfd4132df2d6be97ceabadf3853505", fontSize: 70, value: "month_en", x: -112, y: -32 },
      { align: "left", color: "#FFFFFF", fontId: "f4bfd4132df2d6be97ceabadf3853505", fontSize: 130, value: "time", x: -114.024, y: 97 },
    ],
  },
  DYN011: {
    halfSize: { height: 40, width: 130 },
    imageLayers: [{ assetId: "DYN011-backendui0", height: 12, width: 8, x: -120, y: -19 }],
    sourceCandidateId: "l_shijian6",
    textLayers: [
      { align: "center", color: "#FF6D2F", fontId: "e4210c9872f0c279b35273f230809821", fontSize: 64, value: "year_short", x: -85, y: 0 },
      { align: "center", color: "#FF6D2F", fontId: "e4210c9872f0c279b35273f230809821", fontSize: 64, value: "month", x: 0, y: 0 },
      { align: "center", color: "#FF6D2F", fontId: "e4210c9872f0c279b35273f230809821", fontSize: 64, value: "day", x: 85, y: 0 },
    ],
  },
  DYN012: {
    halfSize: { height: 78, width: 118 },
    imageLayers: [],
    sourceCandidateId: "l_shijian7",
    textLayers: [],
  },
  DYN015: {
    halfSize: { height: 42, width: 300 },
    imageLayers: [{ assetId: "DYN015-imager2", height: 60, width: 60, x: -140, y: 0 }],
    sourceCandidateId: "0721userna",
    textLayers: [{ align: "left", color: "#666666", fontId: "cca5efc0e02fb1bf62349bd68ef30fc1", fontSize: 40, value: "nickname", x: -100, y: 0 }],
  },
  DYN016: {
    halfSize: { height: 48, width: 160 },
    imageLayers: [{ assetId: "DYN016-image21", height: 59, width: 186, x: -61.842, y: 16.483 }],
    sourceCandidateId: "l_username00",
    textLayers: [{ align: "left", color: "#FFFFFF", fontId: "46f8336813e4c48d06a1aef294fdccf6", fontSize: 27, value: "nickname", x: 0, y: 0 }],
  },
};

export function dynamicFontOptionsFor(templateId: string) {
  if (templateId === "DYN012") {
    const replacement = fontOption("FONT081");
    return replacement ? [replacement] : [];
  }
  const model = DYNAMIC_RENDER_MODELS[templateId as DynamicTemplateId];
  if (!model) return [];
  const ids = new Set(model.textLayers.map((layer) => layer.fontId));
  return DYNAMIC_FONT_OPTIONS.filter((option) => ids.has(option.fontId));
}

export function dynamicImageUrl(resourceVersion: string, assetId: string) {
  return `/api/v1/assets/public/${encodeURIComponent(resourceVersion)}/${encodeURIComponent(assetId)}`;
}

function numericField(element: CanvasElement, key: string) {
  const value = element.dynamic_fields?.[key];
  return typeof value === "number" ? value : Number(value);
}

function coordinate(value: number, positive: string, negative: string) {
  if (!Number.isFinite(value)) return "";
  const absolute = Math.abs(value);
  const degrees = Math.floor(absolute);
  const minutesFloat = (absolute - degrees) * 60;
  const minutes = Math.floor(minutesFloat);
  const seconds = (minutesFloat - minutes) * 60;
  return `${degrees}°${String(minutes).padStart(2, "0")}'${seconds.toFixed(2).padStart(5, "0")}\"${value >= 0 ? positive : negative}`;
}

export function dynamicTextValue(element: CanvasElement, value: DynamicTextValue) {
  const fields = element.dynamic_fields ?? {};
  const text = (key: string) => String(fields[key] ?? "");
  const override = fields.display_override;
  if (typeof override === "string" && (value === "nickname" || value === "title")) return element.formatted_value ?? override;
  if (value === "time") return `${text("hour")}:${text("minute")}`;
  if (value === "month_en") {
    const month = Math.max(1, Math.min(12, numericField(element, "month")));
    return `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][month - 1]}.`;
  }
  if (value === "year_short") return text("year").slice(-2);
  if (value === "latitude_dms") return coordinate(numericField(element, "latitude"), "N", "S");
  if (value === "longitude_dms") return coordinate(numericField(element, "longitude"), "E", "W");
  if (value === "meridiem") {
    const hour = numericField(element, "hour");
    const minute = numericField(element, "minute");
    return hour > 12 || (hour === 12 && minute > 0) ? "PM" : "AM";
  }
  return text(value);
}
