import { useEffect, useRef } from "react";
import lottieMod from "lottie-web";
import archive from "react-useanimations/lib/archive";
import arrowDownCircle from "react-useanimations/lib/arrowDownCircle";
import bookmark from "react-useanimations/lib/bookmark";
import calendar from "react-useanimations/lib/calendar";
import checkmark from "react-useanimations/lib/checkmark";
import copy from "react-useanimations/lib/copy";
import edit from "react-useanimations/lib/edit";
import explore from "react-useanimations/lib/explore";
import folder from "react-useanimations/lib/folder";
import help from "react-useanimations/lib/help";
import lock from "react-useanimations/lib/lock";
import mail from "react-useanimations/lib/mail";
import menu2 from "react-useanimations/lib/menu2";
import notification2 from "react-useanimations/lib/notification2";
import plusToX from "react-useanimations/lib/plusToX";
import searchToX from "react-useanimations/lib/searchToX";
import share from "react-useanimations/lib/share";
import skipForward from "react-useanimations/lib/skipForward";
import star from "react-useanimations/lib/star";
import thumbUp from "react-useanimations/lib/thumbUp";
import userPlus from "react-useanimations/lib/userPlus";
import visibility from "react-useanimations/lib/visibility";
import type { NavKey } from "../../lib/nav";

type LottieItem = {
  play: () => void;
  destroy: () => void;
  setDirection: (direction: number) => void;
  goToAndStop: (value: number, isFrame?: boolean) => void;
  totalFrames: number;
};

type LottiePlayer = {
  loadAnimation: (opts: {
    container: Element;
    renderer: "svg";
    loop: boolean;
    autoplay: boolean;
    animationData: unknown;
  }) => LottieItem;
};

type Glyph = { animationData: unknown; animationKey: string };

/** CJS 套件在 Vite 下 default 可能包一層 `{ default: x }`。 */
function unwrapDefault<T>(mod: T | { default: T }): T {
  if (typeof mod === "function") return mod;
  if (mod && typeof mod === "object" && "default" in mod) {
    return (mod as { default: T }).default;
  }
  return mod as T;
}

function asGlyph(mod: unknown): Glyph {
  const inner = unwrapDefault(mod) as Glyph;
  return {
    animationKey: inner.animationKey,
    animationData: unwrapDefault(inner.animationData),
  };
}

const lottie = unwrapDefault(lottieMod) as LottiePlayer;

export type AppIconName =
  | NavKey
  | "more"
  | "spark"
  | "send"
  | "bell"
  | "visibility"
  | "chevron"
  | "help"
  | "close"
  | "check";

type Props = {
  name: AppIconName;
  size?: number;
  className?: string;
  /** 密碼眼睛等：點一下才播，不要 hover 就劃掉 */
  play?: "hover" | "click";
  /** 一開始停在最後一格（例如 close 顯示 X） */
  reverse?: boolean;
};

const glyphs: Record<AppIconName, Glyph> = {
  today: asGlyph(calendar),
  crew: asGlyph(userPlus),
  studio: asGlyph(edit),
  scout: asGlyph(searchToX),
  radar: asGlyph(explore),
  crm: asGlyph(archive),
  outbox: asGlyph(mail),
  jobs: asGlyph(folder),
  brands: asGlyph(bookmark),
  policy: asGlyph(lock),
  playbooks: asGlyph(copy),
  insights: asGlyph(thumbUp),
  benchmark: asGlyph(star),
  utm: asGlyph(share),
  more: asGlyph(menu2),
  spark: asGlyph(star),
  send: asGlyph(skipForward),
  bell: asGlyph(notification2),
  visibility: asGlyph(visibility),
  chevron: asGlyph(arrowDownCircle),
  help: asGlyph(help),
  close: asGlyph(plusToX),
  check: asGlyph(checkmark),
};

/**
 * 用 react-useanimations 的 Lottie 檔，但自己播。
 * 原套件事件只綁在 18px 方塊上，hover 側欄整列不會動；cleanup 也抓不到 instance。
 */
export function AppIcon({
  name,
  size = 22,
  className = "",
  play = "hover",
  reverse = false,
}: Props) {
  const hostRef = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const host = hostRef.current;
    const glyph = glyphs[name];
    if (!host || !glyph?.animationData || typeof lottie?.loadAnimation !== "function") {
      return;
    }

    host.replaceChildren();
    const anim = lottie.loadAnimation({
      container: host,
      renderer: "svg",
      loop: false,
      autoplay: false,
      animationData: glyph.animationData,
    });

    if (reverse && anim.totalFrames > 0) {
      anim.goToAndStop(anim.totalFrames - 1, true);
    }

    const target = host.closest("a, button, [data-icon-host]") ?? host;
    let direction = reverse ? -1 : 1;

    const playForward = () => {
      if (reverse) {
        anim.goToAndStop(0, true);
      }
      anim.setDirection(1);
      anim.play();
    };
    const playBack = () => {
      if (reverse) {
        anim.goToAndStop(Math.max(0, anim.totalFrames - 1), true);
        return;
      }
      anim.setDirection(-1);
      anim.play();
    };
    const playToggle = () => {
      anim.setDirection(direction);
      anim.play();
      direction *= -1;
    };

    if (play === "click") {
      target.addEventListener("click", playToggle);
    } else {
      target.addEventListener("pointerenter", playForward);
      target.addEventListener("pointerleave", playBack);
    }

    return () => {
      if (play === "click") {
        target.removeEventListener("click", playToggle);
      } else {
        target.removeEventListener("pointerenter", playForward);
        target.removeEventListener("pointerleave", playBack);
      }
      anim.destroy();
    };
  }, [name, play, reverse]);

  return (
    <span
      ref={hostRef}
      className={`hb-app-icon ${className}`.trim()}
      style={{ width: size, height: size }}
      aria-hidden
    />
  );
}
