import { lazy, Suspense } from "react";
import { barrierProtects, upcomingEncounterMechanic, useGameStore } from "../game/store";
import { HEALER_CLASSES } from "../game/healers";
import { BOSS_DEFINITIONS } from "../game/bossCatalog";
import { bossRoomFor } from "../game/bossRooms";
import { tankAuraProtects } from "../game/partyCombat";
import { BuffDraftPanel } from "./BuffDraftPanel";
import { DEFAULT_CONTROLLER_GLYPHS } from "../input/controllerGlyphs";

const GameScene = lazy(() => import("./GameScene").then((module) => ({ default: module.GameScene })));

function CompactParty() {
  const party = useGameStore((state) => state.party);
  const time = useGameStore((state) => state.time);
  const selected = useGameStore((state) => state.selectedMemberId);
  const barrier = useGameStore((state) => state.barrier);
  const tankAura = useGameStore((state) => state.partyCombat.tankAura);
  const partyPositions = useGameStore((state) => state.partyPositions);
  const selectMember = useGameStore((state) => state.selectMember);
  const mana = useGameStore((state) => state.mana);
  const maxMana = useGameStore((state) => state.maxMana);
  return (
    <div className="top-party" aria-label="Party health">
      {party.map((member) => {
        const health = (member.hp / member.maxHp) * 100;
        const shield = (member.absorb / member.maxHp) * 100;
        return (
          <button
            className={`top-party-member ${selected === member.id ? "is-selected" : ""}`}
            key={member.id}
            onClick={() => selectMember(member.id)}
            aria-label={`Target ${member.name}, ${Math.ceil(member.hp)} health`}
          >
            <span className="portrait-dot" style={{ background: member.color }}>{member.name[0]}</span>
            <span className="top-party-copy"><strong>{member.name}</strong><small>{member.role}</small></span>
            <span className={`microbar ${member.id === "aelia" ? "player-health-bar" : ""}`}>
              <i style={{ width: `${health}%` }} />
              {shield > 0 && <b style={{ width: `${Math.max(8, shield)}%` }} />}
            </span>
            {member.id === "aelia" && (
              <span className="player-mana-bar" aria-label={`${Math.ceil(mana)} of ${maxMana} mana`}>
                <i style={{ width: `${(mana / maxMana) * 100}%` }} />
              </span>
            )}
            <span className="top-effects">
              {member.renewExpiresAt > 0 && <em className="renew-pip">R</em>}
              {member.debuffs.length > 0 && <em className="debuff-pip">!</em>}
              {barrierProtects(partyPositions[member.id], barrier, time) && <em className="barrier-pip">B</em>}
              {tankAuraProtects(partyPositions[member.id], partyPositions.brann, tankAura, time) && <em className="tank-aura-pip">T</em>}
              {member.knockedUntil > time && <em className="knockdown-pip">KD</em>}
            </span>
          </button>
        );
      })}
    </div>
  );
}

function CastingBar() {
  const healerClassId = useGameStore((state) => state.healerClassId);
  const abilityName = HEALER_CLASSES[healerClassId].abilities.mend.name;
  const activeCast = useGameStore((state) => state.activeCast);
  const time = useGameStore((state) => state.time);
  const party = useGameStore((state) => state.party);
  if (!activeCast) return null;
  const duration = activeCast.completesAt - activeCast.startedAt;
  const progress = Math.min(1, Math.max(0, (time - activeCast.startedAt) / duration));
  const target = party.find((member) => member.id === activeCast.targetId);
  return (
    <div className="casting-bar" aria-label={`Casting ${abilityName} on ${target?.name ?? "ally"}`}>
      <span><strong>{abilityName}</strong><small>{target?.name}</small></span>
      <b>{Math.max(0, activeCast.completesAt - time).toFixed(1)}s</b>
      <i><em style={{ width: `${progress * 100}%` }} /></i>
    </div>
  );
}

function BossBar() {
  const boss = useGameStore((state) => state.boss);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  const phase = useGameStore((state) => state.phase);
  if (phase === "briefing") return null;
  const bosses = [boss, ...additionalBosses.map((entry) => entry.boss)];
  return (
    <div className={`boss-bar-wrap ${bosses.length > 1 ? "is-multi" : ""} ${bosses.length === 3 ? "is-trio" : ""}`}>
      {bosses.map((entry) => <div className="boss-bar-entry" key={entry.id}>
        <div className="boss-name"><span>Vault Beast</span><strong>{entry.name}</strong><span>{Math.ceil((entry.hp / entry.maxHp) * 100)}%</span></div>
        <div className="boss-bar"><i style={{ width: `${(entry.hp / entry.maxHp) * 100}%` }} /></div>
      </div>)}
    </div>
  );
}

function EncounterCallout() {
  const phase = useGameStore((state) => state.phase);
  const time = useGameStore((state) => state.time);
  const boss = useGameStore((state) => state.boss);
  const bossMotion = useGameStore((state) => state.bossMotion);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  if (phase !== "combat") return null;
  const mechanic = upcomingEncounterMechanic({ boss, bossMotion, additionalBosses, time });
  return (
    <div className={`encounter-callout ${mechanic.urgent ? "is-urgent" : ""}`}>
      <span>{mechanic.name}</span>
      <strong>{mechanic.remaining.toFixed(1)}s</strong>
    </div>
  );
}

function PhaseOverlay() {
  const phase = useGameStore((state) => state.phase);
  const runMode = useGameStore((state) => state.runMode);
  const round = useGameStore((state) => state.round);
  const endlessMode = useGameStore((state) => state.endlessMode);
  const endlessBossKills = useGameStore((state) => state.endlessBossKills);
  const primaryBoss = useGameStore((state) => state.boss);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  if (phase === "intermission") return <BuffDraftPanel className="top-buff-draft" />;
  const bosses = [primaryBoss, ...additionalBosses.map((entry) => entry.boss)];
  const definitions = bosses.map((boss) => BOSS_DEFINITIONS[boss.id]);
  const room = bossRoomFor(primaryBoss.id);
  const bossNames = bosses.map((boss) => boss.name).join(" & ");
  const showEndlessChoice = phase === "victory" && runMode === "rogue-trials" && round === 5 && !endlessMode;
  const endlessDefeat = phase === "defeat" && endlessMode;
  const briefingMode = runMode === "rogue-trials"
    ? bosses.length === 3 ? "Rogue Trials · Trio Finale" : "Rogue Trials · Dual Round"
    : bosses.length > 1 ? "Roguelike PVE · Dual Encounter" : definitions[0].trial;
  if (phase === "combat") return null;
  const title = phase === "briefing"
    ? room.name
    : phase === "victory"
        ? showEndlessChoice ? "Rogue Trials Cleared" : `${bossNames} Broken`
        : endlessDefeat ? "Endless Run Ended" : "Party Broken";
  const eyebrow = phase === "briefing"
    ? `${briefingMode} · ${room.biome}`
    : phase === "victory"
        ? showEndlessChoice ? "Endless Path Unlocked" : "Encounter Complete"
        : endlessDefeat ? `${endlessBossKills} Endless Bosses Defeated` : "Encounter Failed";
  const copy = phase === "briefing"
    ? definitions.map((boss) => boss.briefing).join(" ")
    : phase === "victory"
      ? showEndlessChoice ? "Leave with the clear, or continue against an unbroken chain of replacement bosses." : "Five entered. Five endured."
      : endlessDefeat ? `Run record: ${endlessBossKills} bosses defeated after the trio finale.` : definitions.map((boss) => boss.failure).join(" ");
  return (
    <div className={`phase-overlay phase-${phase}`}>
      <div className="phase-sigil">✦</div>
      <span>{eyebrow}</span>
      <h1>{title}</h1>
      <p>{copy}</p>
      <small>{phase === "briefing" ? "Begin from lower display" : showEndlessChoice ? "Choose Continue or Quit on lower display" : "Restart from lower display"}</small>
    </div>
  );
}

function PauseOverlay({ onExit }: { onExit?: () => void }) {
  const paused = useGameStore((state) => state.paused);
  const selection = useGameStore((state) => state.pauseSelection);
  const setPaused = useGameStore((state) => state.setPaused);
  const setPauseSelection = useGameStore((state) => state.setPauseSelection);
  if (!paused) return null;
  const exit = () => {
    setPaused(false);
    onExit?.();
  };
  return (
    <div className="pause-overlay" role="dialog" aria-modal="true" aria-label="Game paused">
      <div className="pause-panel">
        <span>Encounter suspended</span>
        <h1>Paused</h1>
        <p>Simulation, damage, and movement are stopped.</p>
        <div className="pause-actions">
          <button
            className={selection === "resume" ? "is-controller-focused" : ""}
            onFocus={() => setPauseSelection("resume")}
            onPointerEnter={() => setPauseSelection("resume")}
            onClick={() => setPaused(false)}
          >Resume <small>{DEFAULT_CONTROLLER_GLYPHS.start} / ESC</small></button>
          <button
            className={`secondary ${selection === "exit" ? "is-controller-focused" : ""}`}
            onFocus={() => setPauseSelection("exit")}
            onPointerEnter={() => setPauseSelection("exit")}
            onClick={exit}
          >Return to main menu <small>{DEFAULT_CONTROLLER_GLYPHS.confirm}</small></button>
        </div>
        <footer><b>↑ / ↓</b> Choose <i /> <b>{DEFAULT_CONTROLLER_GLYPHS.confirm} / ENTER</b> Confirm</footer>
      </div>
    </div>
  );
}

export function TopScreen({ onExit }: { onExit?: () => void }) {
  const phase = useGameStore((state) => state.phase);
  const bossCount = useGameStore((state) => state.additionalBosses.length + 1);
  const round = useGameStore((state) => state.round);
  const runMode = useGameStore((state) => state.runMode);
  const endlessMode = useGameStore((state) => state.endlessMode);
  const endlessBossKills = useGameStore((state) => state.endlessBossKills);
  const setPaused = useGameStore((state) => state.setPaused);
  return (
    <section className="display top-display" aria-label="Main game viewport">
      <Suspense fallback={<div className="scene-loading" aria-label="Loading 3D scene" />}>
        <GameScene />
      </Suspense>
      <div className="top-vignette" />
      <div className="top-hud">
        <CompactParty />
        <BossBar />
        <div className="objective-chip"><span>{endlessMode ? `Endless · ${endlessBossKills} kills` : runMode !== "encounter" ? `Round ${round}` : "Objective"}</span><strong>{endlessMode ? "Defeat bosses · replacements incoming" : bossCount === 3 ? "Defeat trio · keep five alive" : bossCount === 2 ? "Defeat both · keep five alive" : "Keep all five alive"}</strong></div>
        <EncounterCallout />
        <CastingBar />
        <div className="control-hint"><b>WASD</b> Move <i /> <b>Q / E</b> Target <i /> <b>1–6</b> Cast</div>
        {onExit && <button className="game-menu-button" onClick={() => phase === "combat" ? setPaused(true) : onExit()}><b>☰</b> Menu <small>{DEFAULT_CONTROLLER_GLYPHS.start} / ESC</small></button>}
      </div>
      <PhaseOverlay />
      <PauseOverlay onExit={onExit} />
    </section>
  );
}
