"use client";

import { useEffect, useRef, useState } from "react";
import { ABILITY_BY_ID, SCHOOL_NAME, type Ability } from "@/game/data";
import type { AbilityView } from "@/game/Game";
import { SCHOOL_COLOUR, SpellIcon } from "./SpellIcon";
import "./spellui.css";

const secs = (v: number) => `${v % 1 === 0 ? v : v.toFixed(1)} s`;

/** Holding Alt while the card is open reveals the advice line. */
function useAlt(on: boolean) {
  const [alt, setAlt] = useState(false);
  useEffect(() => {
    if (!on) {
      setAlt(false);
      return;
    }
    const h = (e: KeyboardEvent) => setAlt(e.altKey);
    window.addEventListener("keydown", h);
    window.addEventListener("keyup", h);
    return () => {
      window.removeEventListener("keydown", h);
      window.removeEventListener("keyup", h);
    };
  }, [on]);
  return alt;
}

/** The compact card (about 260 px wide). Every number comes from data.ts, the same table the combat sim reads. */
export function SpellCard({ ab, alt = false }: { ab: Ability; alt?: boolean }) {
  const c = SCHOOL_COLOUR[ab.school];
  const rows: [string, string][] = [
    ["Cast", ab.cast > 0 ? secs(ab.cast) : "Instant"],
    ["Mana", ab.mana > 0 ? String(ab.mana) : "Free"],
    ["Cooldown", ab.cd > 0 ? secs(ab.cd) : "None"],
    ["Range", ab.range > 0 ? `${ab.range} m` : ab.id === "dash" || ab.id === "blink" ? "Self" : "Around you"],
  ];
  return (
    <div className="spell-card" style={{ ["--school" as string]: c.main }}>
      <div className="spell-card-head">
        <SpellIcon id={ab.id} school={ab.school} size={28} />
        <div className="min-w-0 flex-1">
          <div className="spell-card-name">{ab.name}</div>
          <div className="spell-card-sub">
            <span style={{ color: c.main }}>{ab.school === "physical" ? "Movement" : SCHOOL_NAME[ab.school]}</span>
            <span>Rank {ab.rank}</span>
          </div>
        </div>
        <kbd>{ab.key}</kbd>
      </div>
      <dl className="spell-card-rows">
        {rows.map(([k, v]) => (
          <div key={k}>
            <dt>{k}</dt>
            <dd>{v}</dd>
          </div>
        ))}
      </dl>
      <p className="spell-card-what">{ab.what}</p>
      {ab.dmg != null && (
        <div className="spell-card-dmg">
          <span>
            Damage <b>{ab.dmg}</b>
          </span>
          {ab.dmgFrozen != null && (
            <span className="shatter">
              Frozen <b>{ab.dmgFrozen}</b>
            </span>
          )}
        </div>
      )}
      {alt && <p className="spell-card-tip">{ab.tip}</p>}
    </div>
  );
}

interface SlotProps {
  a: AbilityView;
  code: string;
  onCast(code: string): void;
  size?: "bar" | "big";
  touch: boolean;
}

/**
 * One action-bar slot: drawn icon, school-coloured frame, cooldown sweep, out-of-mana dim, key label, and a tooltip on
 * hover or keyboard focus (desktop) or a long press (phone: a quick tap casts, a hold shows the card).
 */
export function ActionSlot({ a, code, onCast, size = "bar", touch }: SlotProps) {
  const ab = ABILITY_BY_ID[a.id];
  const ref = useRef<HTMLButtonElement>(null);
  const [tip, setTip] = useState<{ left: number; bottom: number } | null>(null);
  const press = useRef({ timer: 0, long: false, id: -1 });
  const hide = useRef(0);
  const alt = useAlt(!!tip);

  useEffect(
    () => () => {
      window.clearTimeout(press.current.timer);
      window.clearTimeout(hide.current);
    },
    [],
  );

  const show = () => {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    const w = Math.min(260, window.innerWidth - 16);
    const left = Math.max(8, Math.min(window.innerWidth - w - 8, r.left + r.width / 2 - w / 2));
    setTip({ left, bottom: window.innerHeight - r.top + 8 });
  };

  const useCd = a.cdLeft > 0;
  const p = useCd ? a.cdLeft / Math.max(0.01, a.cdTotal) : a.gcdLeft > 0 ? a.gcdLeft / a.gcdTotal : 0;
  const colour = SCHOOL_COLOUR[ab.school];

  return (
    <>
      <button
        ref={ref}
        type="button"
        data-coach={`slot-${a.key.toLowerCase()}`}
        aria-label={`${a.name}, key ${a.key}${a.mana ? `, ${a.mana} mana` : ""}. ${ab.what}`}
        className={`aslot ${size === "big" ? "aslot-big" : ""} ${a.noMana ? "nomana" : ""} ${a.usable === "range" || a.usable === "sight" ? `u-${a.usable}` : ""} ${a.locked ? "silenced" : ""} ${a.active ? "active" : ""} ${useCd ? "oncd" : ""}`}
        style={{ ["--school" as string]: colour.main, ["--glow" as string]: colour.glow }}
        onPointerEnter={(e) => {
          if (e.pointerType === "mouse") show();
        }}
        onPointerLeave={(e) => {
          if (e.pointerType === "mouse") setTip(null);
        }}
        onFocus={(e) => {
          if (e.currentTarget.matches(":focus-visible")) show();
        }}
        onBlur={() => setTip(null)}
        onPointerDown={(e) => {
          e.preventDefault();
          if (e.pointerType === "touch") {
            const s = press.current;
            s.long = false;
            s.id = e.pointerId;
            window.clearTimeout(s.timer);
            s.timer = window.setTimeout(() => {
              s.long = true;
              show();
            }, 340);
            return;
          }
          onCast(code);
        }}
        onPointerUp={(e) => {
          if (e.pointerType !== "touch") return;
          const s = press.current;
          window.clearTimeout(s.timer);
          if (s.long) {
            window.clearTimeout(hide.current);
            hide.current = window.setTimeout(() => setTip(null), 2600);
          } else if (s.id === e.pointerId) onCast(code);
          s.id = -1;
        }}
        onPointerCancel={() => {
          window.clearTimeout(press.current.timer);
          press.current.id = -1;
          setTip(null);
        }}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") {
            e.preventDefault();
            onCast(code);
          }
        }}
      >
        <SpellIcon id={a.id} school={ab.school} size={size === "big" ? 56 : 52} />
        <span className="aslot-shade" />
        <span className="sweep" style={{ ["--p" as string]: p }} />
        {useCd && <span className="cdnum">{a.cdLeft >= 10 ? Math.ceil(a.cdLeft) : a.cdLeft.toFixed(1)}</span>}
        {!useCd && a.mana > 0 && <span className="cost">{a.mana}</span>}
        <span className="key">{a.key === "Space" ? (touch ? "" : "Spc") : a.key === "Shift" ? (touch ? "" : "Shft") : a.key}</span>
      </button>
      {tip && (
        <div className="spell-tip" style={{ left: tip.left, bottom: tip.bottom }} role="tooltip">
          <SpellCard ab={ab} alt={alt} />
        </div>
      )}
    </>
  );
}
