"use client";

import { useId, useSyncExternalStore } from "react";
import { Box, Cloud, Flame, Ghost, Link2, Shield, Skull, Snowflake, Star, Swords, VolumeX, type LucideIcon } from "lucide-react";
import { portraits } from "@/game/portraits";
import type { ResourceKind } from "@/game/data";
import type { AuraView } from "@/game/Game";
import "./unitframe.css";

const num = new Intl.NumberFormat("en-US");

const AURA_ICON: Record<string, LucideIcon> = {
  slow: Snowflake,
  root: Link2,
  poly: Cloud,
  stun: Star,
  fear: Ghost,
  silence: VolumeX,
  absorb: Shield,
  immune: Box,
  dot: Skull,
  enrage: Flame,
  wall: Shield,
};

/** Name colour by class, like WoW (the hero is a mage, the Fire Mage too, the warrior brown, the priest white). */
export const CLASS_COLOUR: Record<string, string> = {
  player: "#69ccf0",
  warrior: "#c79c6e",
  pyromancer: "#ff9a4a",
  priestess: "#d9c4ff",
  gladiator: "#f2c14e",
};
const RES_LABEL: Record<ResourceKind, string> = { mana: "Mana", rage: "Rage", energy: "Energy" };

/** Round portrait in an ornate ring: gold outer bevel, steel inner ring, studs; the elite ring grows spikes and a skull. */
export function Orb({ kind, level, elite, dead, mirror }: { kind: string; level: string; elite?: boolean; dead?: boolean; mirror?: boolean }) {
  const uid = useId().replace(/:/g, "");
  useSyncExternalStore(portraits.subscribe, portraits.version, portraits.version);
  const src = portraits.get(kind);
  const tint = CLASS_COLOUR[kind] ?? "#fff";
  return (
    <span className={`uf-orb ${dead ? "dead" : ""} ${elite ? "elite" : ""} ${mirror ? "mirror" : ""}`} style={{ ["--cc" as string]: tint }}>
      <span className="uf-face">
        {src ? <img src={src} alt="" width={64} height={64} draggable={false} /> : <span className="uf-ph" />}
      </span>
      <svg className="uf-ring" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
        <defs>
          <linearGradient id={`${uid}g`} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="#fff2b0" />
            <stop offset="0.35" stopColor="#e3a93a" />
            <stop offset="0.7" stopColor="#8a5a14" />
            <stop offset="1" stopColor="#f6d77a" />
          </linearGradient>
          <linearGradient id={`${uid}s`} x1="1" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="#e9eef7" />
            <stop offset="0.5" stopColor="#6c7890" />
            <stop offset="1" stopColor="#2a3144" />
          </linearGradient>
        </defs>
        {elite && (
          <g fill={`url(#${uid}g)`} stroke="#3b2608" strokeWidth="0.8">
            <path d="M50 0 L56 9 L44 9 Z" />
            <path d="M82 12 L83 22 L74 17 Z" />
            <path d="M18 12 L26 17 L17 22 Z" />
            <path d="M100 46 L91 52 L91 40 Z" />
            <path d="M0 46 L9 40 L9 52 Z" />
          </g>
        )}
        <circle cx="50" cy="50" r="45" fill="none" stroke={`url(#${uid}g)`} strokeWidth="7" />
        <circle cx="50" cy="50" r="41" fill="none" stroke="#2b1a05" strokeWidth="1.2" />
        <circle cx="50" cy="50" r="48.6" fill="none" stroke="#2b1a05" strokeWidth="1" />
        <circle cx="50" cy="50" r="38.5" fill="none" stroke={`url(#${uid}s)`} strokeWidth="3" />
        {[0, 60, 120, 180, 240, 300].map((a) => (
          <circle key={a} cx={50 + 45 * Math.cos((a * Math.PI) / 180)} cy={50 + 45 * Math.sin((a * Math.PI) / 180)} r="1.5" fill="#fff6c8" stroke="#3b2608" strokeWidth="0.5" />
        ))}
        <path d="M30 8 Q50 -2 70 8" fill="none" stroke="#fff6c8" strokeOpacity="0.55" strokeWidth="1.2" />
      </svg>
      <span className="uf-lvl" title="Level">
        {elite ? <Skull aria-label="Boss" /> : level}
      </span>
    </span>
  );
}

/** One bevelled bar: texture, gloss line, a pale chip that drains after a hit, numbers on the bar, percent on hover. */
export function StatBar({ kind, value, max, label, absorb }: { kind: "hp" | ResourceKind; value: number; max: number; label: string; absorb?: number }) {
  const pct = Math.max(0, Math.min(100, (value / Math.max(1, max)) * 100));
  const v = Math.ceil(value), m = Math.round(max);
  return (
    <div className={`uf-bar uf-${kind}`} role="progressbar" aria-label={label} aria-valuemin={0} aria-valuemax={m} aria-valuenow={v}>
      <b style={{ width: `${pct}%` }} />
      <i style={{ width: `${pct}%` }} />
      {!!absorb && absorb > 0 && <u style={{ width: `${Math.min(100 - pct + 4, (absorb / Math.max(1, max)) * 100)}%`, left: `${pct}%` }} />}
      <span className="uf-num">
        <span className="n-abs">
          {num.format(v)} / {num.format(m)}
        </span>
        <span className="n-pct">{Math.round(pct)}%</span>
      </span>
    </div>
  );
}

/** Buff / debuff row: square icons, green or red rim, clock sweep, seconds, and a stack count for duplicates. */
export function Buffs({ list, mirror }: { list: AuraView[]; mirror?: boolean }) {
  if (!list.length) return <div className="uf-buffs empty" aria-hidden="true" />;
  const groups: { a: AuraView; n: number }[] = [];
  for (const a of list) {
    const g = groups.find((x) => x.a.name === a.name && x.a.kind === a.kind);
    if (g) {
      g.n++;
      if (a.left > g.a.left) g.a = a;
    } else groups.push({ a, n: 1 });
  }
  return (
    <div className={`uf-buffs ${mirror ? "mirror" : ""}`}>
      {groups.slice(0, 8).map(({ a, n }) => {
        const I = AURA_ICON[a.kind] ?? Snowflake;
        const timed = a.left < 100;
        return (
          <span key={a.id} className={`uf-aura ${a.harmful ? "bad" : "good"}`} title={`${a.name}${timed ? `, ${a.left.toFixed(1)} s` : ""}`}>
            <I aria-hidden="true" />
            {timed && <span className="uf-sweep" style={{ ["--p" as string]: Math.max(0, Math.min(1, 1 - a.left / Math.max(0.1, a.total))) }} />}
            {n > 1 && <b className="uf-stack">{n}</b>}
            {timed && <small>{a.left >= 10 ? Math.ceil(a.left) : a.left.toFixed(1)}</small>}
          </span>
        );
      })}
    </div>
  );
}

interface FrameProps {
  kind: string;
  name: string;
  level: string;
  hp: number;
  maxHp: number;
  res: { kind: ResourceKind; v: number; max: number } | null;
  absorb?: number;
  auras: AuraView[];
  elite?: boolean;
  mirror?: boolean;
  state?: "combat" | "rest" | "";
  hostile?: boolean;
  label: string;
}

/** A WoW-style unit frame: portrait orb, name plate, health bar, resource bar, state badge, buffs underneath. */
export function UnitFrame({ kind, name, level, hp, maxHp, res, absorb, auras, elite, mirror, state, hostile, label }: FrameProps) {
  const dead = hp <= 0;
  return (
    <div className={`uf ${mirror ? "mirror" : ""} ${elite ? "elite" : ""} ${hostile ? "hostile" : ""} ${dead ? "dead" : ""}`} aria-label={label}>
      <div className="uf-main">
        <Orb kind={kind} level={level} elite={elite} dead={dead} mirror={mirror} />
        <div className="uf-plate">
          <div className="uf-name" style={{ color: CLASS_COLOUR[kind] ?? "#fff" }}>
            <span className="truncate">{name}</span>
            {state === "combat" && <Swords className="uf-state combat" aria-label="In combat" />}
            {state === "rest" && <span className="uf-state rest" aria-label="Resting">Zz</span>}
          </div>
          <StatBar kind="hp" value={hp} max={maxHp} label={`${name} health`} absorb={absorb} />
          {res ? <StatBar kind={res.kind} value={res.v} max={res.max} label={`${name} ${RES_LABEL[res.kind]}`} /> : <div className="uf-bar uf-none" aria-hidden="true" />}
        </div>
      </div>
      <Buffs list={auras} mirror={mirror} />
    </div>
  );
}
