"use client";

import Link from "next/link";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { Game } from "@/lib/types";
import { playUi } from "@/lib/consoleUiAudio";
import { WaveBg } from "./WaveBg";
import { MuteChip } from "./MuteChip";

const CATEGORIES = [
  { id: "users", label: "Users", icon: "◎" },
  { id: "settings", label: "Settings", icon: "⚙" },
  { id: "photo", label: "Photo", icon: "▣" },
  { id: "music", label: "Music", icon: "♪" },
  { id: "video", label: "Video", icon: "▶" },
  { id: "game", label: "Game", icon: "◆" },
  { id: "network", label: "Network", icon: "◌" },
] as const;

export function XmbShell({
  games,
  variant,
  title,
}: {
  games: Game[];
  variant: "ps3" | "psp";
  title: string;
}) {
  const kind = variant === "psp" ? "psp-xmb" : "ps3-xmb";
  const gameCat = 5;
  const [cat, setCat] = useState(gameCat);
  const [row, setRow] = useState(0);
  const [clock, setClock] = useState("");
  const firstMove = useRef(true);

  const items = useMemo(() => {
    if (cat === 0) {
      return [
        {
          slug: "_profiles",
          title: "Profiles",
          cover: undefined as string | undefined,
          href: "/profiles",
          subtitle: "Switch local memory cards",
        },
        {
          slug: "_account",
          title: "Account",
          cover: undefined,
          href: "/account",
          subtitle: "Sign in or create",
        },
      ];
    }
    if (cat === 1) {
      return [
        {
          slug: "_settings",
          title: "System settings",
          cover: undefined as string | undefined,
          href: "/settings",
          subtitle: "Identity, competitive, gameplay",
        },
        {
          slug: "_ui",
          title: "Change cabinet UI",
          cover: undefined,
          href: "/setup/ui",
          subtitle: "XMB, shelves, arcade…",
        },
      ];
    }
    if (cat !== gameCat) {
      const titles: Record<number, string> = {
        2: "Photo album",
        3: "Music player",
        4: "Video player",
        6: "Network status",
      };
      return [
        {
          slug: "_noop",
          title: titles[cat] ?? "Unavailable",
          cover: undefined as string | undefined,
          href: undefined as string | undefined,
          subtitle: "Coming later",
        },
      ];
    }
    if (games.length === 0) {
      return [
        {
          slug: "_empty",
          title: "No games installed",
          cover: undefined,
          href: "/load",
          subtitle: "Open a ROM file",
        },
      ];
    }
    return games.map((g) => ({
      slug: g.slug,
      title: g.title,
      cover: g.cover,
      href: `/play/${g.slug}`,
      subtitle: g.legal ? "Free title" : "Game data",
    }));
  }, [cat, games]);

  useEffect(() => {
    setRow(0);
  }, [cat]);

  useEffect(() => {
    const tick = () =>
      setClock(
        new Date().toLocaleTimeString([], {
          hour: "2-digit",
          minute: "2-digit",
        }),
      );
    tick();
    const id = window.setInterval(tick, 30_000);
    return () => window.clearInterval(id);
  }, []);

  const move = useCallback(
    (dx: number, dy: number) => {
      playUi(kind, "move");
      if (dx !== 0) {
        setCat((c) => {
          let next = c + dx;
          if (next < 0) next = CATEGORIES.length - 1;
          if (next >= CATEGORIES.length) next = 0;
          return next;
        });
      }
      if (dy !== 0) {
        setRow((r) => {
          let next = r + dy;
          if (next < 0) next = Math.max(0, items.length - 1);
          if (next >= items.length) next = 0;
          return next;
        });
      }
    },
    [items.length, kind],
  );

  const selectAt = useCallback(
    (index: number) => {
      const item = items[index];
      if (!item?.href) {
        playUi(kind, "error");
        return;
      }
      playUi(kind, "confirm");
      window.setTimeout(() => {
        window.location.href = item.href!;
      }, 120);
    },
    [items, kind],
  );

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "ArrowLeft") {
        e.preventDefault();
        move(-1, 0);
      } else if (e.key === "ArrowRight") {
        e.preventDefault();
        move(1, 0);
      } else if (e.key === "ArrowUp") {
        e.preventDefault();
        move(0, -1);
      } else if (e.key === "ArrowDown") {
        e.preventDefault();
        move(0, 1);
      } else if (e.key === "Enter" || e.key === " ") {
        e.preventDefault();
        selectAt(row);
      } else if (e.key === "Escape" || e.key === "Backspace") {
        e.preventDefault();
        playUi(kind, "back");
        window.location.href = "/setup/ui";
      }
    };
    const onWheel = (e: WheelEvent) => {
      if (Math.abs(e.deltaY) < 2) return;
      e.preventDefault();
      move(0, e.deltaY > 0 ? 1 : -1);
    };
    window.addEventListener("keydown", onKey);
    window.addEventListener("wheel", onWheel, { passive: false });
    return () => {
      window.removeEventListener("keydown", onKey);
      window.removeEventListener("wheel", onWheel);
    };
  }, [kind, move, row, selectAt]);

  const shell = (
    <div className={`xmb-shell xmb-shell--${variant} is-live`}>
      <WaveBg variant={variant} />
      <div className="xmb-vignette" aria-hidden />
      <header className="xmb-top">
        <div className="xmb-top-links">
          <Link
            href="/setup/ui"
            className="xmb-back"
            onClick={() => playUi(kind, "back")}
          >
            ← UI
          </Link>
          <Link
            href="/profiles"
            className="xmb-back"
            onClick={() => playUi(kind, "confirm")}
          >
            Profiles
          </Link>
          <Link
            href="/settings"
            className="xmb-back"
            onClick={() => playUi(kind, "confirm")}
          >
            Settings
          </Link>
        </div>
        <div className="xmb-brand">
          <span className="xmb-brand-mark">
            {variant === "psp" ? "PSP" : "PS"}
          </span>
          <span className="xmb-brand-title">{title}</span>
        </div>
        <div className="xmb-top-right">
          <MuteChip />
          <time className="xmb-clock">{clock}</time>
        </div>
      </header>

      <div className="xmb-cross">
        <nav className="xmb-cats" aria-label="Categories">
          {CATEGORIES.map((c, i) => (
            <button
              key={c.id}
              type="button"
              className={`xmb-cat${i === cat ? " is-active" : ""}`}
              onClick={() => {
                if (i !== cat) {
                  playUi(kind, "move");
                  setCat(i);
                }
              }}
            >
              <span className="xmb-cat-icon" aria-hidden>
                {c.icon}
              </span>
              <span className="xmb-cat-label">{c.label}</span>
            </button>
          ))}
        </nav>

        <div className="xmb-col">
          {items.map((item, i) => {
            const active = i === row;
            const offset = i - row;
            const far = Math.abs(offset) > 4;
            return (
              <button
                key={item.slug}
                type="button"
                tabIndex={far ? -1 : 0}
                className={`xmb-item${active ? " is-active" : ""}`}
                style={{
                  transform: `translateY(calc(${offset} * var(--xmb-row))) scale(${active ? 1 : 0.9})`,
                  opacity: far ? 0 : 1 - Math.abs(offset) * 0.18,
                  pointerEvents: far ? "none" : "auto",
                  zIndex: 20 - Math.abs(offset),
                }}
                onMouseEnter={() => {
                  if (i !== row && !far) {
                    if (!firstMove.current) playUi(kind, "move");
                    firstMove.current = false;
                    setRow(i);
                  }
                }}
                onClick={() => {
                  setRow(i);
                  selectAt(i);
                }}
              >
                <div className="xmb-item-art">
                  {item.cover ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={item.cover} alt="" />
                  ) : (
                    <span className="xmb-item-fallback">◆</span>
                  )}
                </div>
                <div className="xmb-item-meta">
                  <p className="xmb-item-title">{item.title}</p>
                  {active && (
                    <p className="xmb-item-hint">{item.subtitle}</p>
                  )}
                </div>
              </button>
            );
          })}
        </div>
      </div>

      <footer className="xmb-hint">
        <span>× Back</span>
        <span>○ Select</span>
        <span>↑↓←→ / scroll</span>
        <span>
          {cat === gameCat ? `${row + 1}/${items.length}` : ""}
        </span>
      </footer>
    </div>
  );

  if (variant === "psp") {
    return (
      <div className="psp-device">
        <div className="psp-shoulder" aria-hidden />
        <div className="psp-device-frame">{shell}</div>
        <div className="psp-controls" aria-hidden>
          <div className="psp-analog" />
          <div className="psp-face">
            <i /><i /><i /><i />
          </div>
        </div>
        <p className="psp-device-label">PSP System Software</p>
      </div>
    );
  }

  return shell;
}
