import { ABILITY_ORDER } from "../game/data";
import { HEALER_CLASSES } from "../game/healers";
import { BOSS_DEFINITIONS } from "../game/bossCatalog";
import { GLOBAL_COOLDOWN_SECONDS, abilityRemaining, barrierProtects, upcomingEncounterMechanic, useGameStore } from "../game/store";
import { runAbilityCastTime, runAbilityCooldown, runAbilityManaCost } from "../game/roguelike";
import { PARTY_ABILITY_NAMES, tankAuraProtects } from "../game/partyCombat";
import type { BottomTab, PartyMember } from "../game/types";
import { useFrontendStore } from "../frontend/store";
import { DEFAULT_CONTROLLER_GLYPHS } from "../input/controllerGlyphs";

function RewardSummary() {
  const rewards = useFrontendStore((state) => state.recentRewards);
  if (!rewards.length) return null;
  return <div className="reward-summary" aria-label="Boss rewards">{rewards.map((reward, index) => <span key={`${reward.drop.id}-${index}`}><b>{reward.drop.glyph}</b>{reward.drop.name} ×{reward.quantity}{reward.pet ? <i> + {reward.pet.name}</i> : null}</span>)}</div>;
}

function HealthBar({ member }: { member: PartyMember }) {
  const health = Math.max(0, (member.hp / member.maxHp) * 100);
  const shield = Math.min(38, (member.absorb / member.maxHp) * 100);
  const shieldLeft = Math.min(health, 100 - shield);
  return (
    <span className="health-bar">
      <i className={health < 35 ? "is-low" : ""} style={{ width: `${health}%` }} />
      {shield > 0 && <b style={{ left: `${shieldLeft}%`, width: `${shield}%` }} />}
    </span>
  );
}

function PartyFrame({ member }: { member: PartyMember }) {
  const selected = useGameStore((state) => state.selectedMemberId === member.id);
  const selectMember = useGameStore((state) => state.selectMember);
  const time = useGameStore((state) => state.time);
  const renewRemaining = Math.max(0, member.renewExpiresAt - time);
  const knockedRemaining = Math.max(0, member.knockedUntil - time);
  const barrier = useGameStore((state) => state.barrier);
  const tankAura = useGameStore((state) => state.partyCombat.tankAura);
  const tankPosition = useGameStore((state) => state.partyPositions.brann);
  const combatant = useGameStore((state) => member.id === "aelia" ? undefined : state.partyCombat.combatants[member.id]);
  const position = useGameStore((state) => state.partyPositions[member.id]);
  const protectedByBarrier = barrierProtects(position, barrier, time);
  const protectedByTank = tankAuraProtects(position, tankPosition, tankAura, time);
  const currentAction = combatant?.visualAction && combatant.visualAction.endsAt > time
    ? PARTY_ABILITY_NAMES[combatant.visualAction.abilityId]
    : null;
  return (
    <button
      className={`party-frame ${selected ? "is-selected" : ""} ${member.hp <= 0 ? "is-down" : ""}`}
      onClick={() => selectMember(member.id)}
      aria-pressed={selected}
    >
      <span className="party-avatar" style={{ "--member-color": member.color } as React.CSSProperties}>{member.name[0]}</span>
      <span className="party-data">
        <span className="party-name"><strong>{member.name}</strong><em>{Math.ceil(member.hp)} / {member.maxHp}</em></span>
        <HealthBar member={member} />
        <small>{currentAction ?? member.className}</small>
      </span>
      <span className="effect-stack">
        {member.absorb > 0 && <i className="effect shield-effect" title={`${Math.ceil(member.absorb)} absorption`}>◇</i>}
        {renewRemaining > 0 && <i className="effect renew-effect" title={`Renew: ${renewRemaining.toFixed(1)} seconds`}>{Math.ceil(renewRemaining)}</i>}
        {member.debuffs.length > 0 && <i className="effect debuff-effect" title={`${member.debuffs[0].name} — Purify`}>!</i>}
        {protectedByBarrier && <i className="effect barrier-effect" title="Barrier: 30% reduced damage">B</i>}
        {protectedByTank && <i className="effect tank-aura-effect" title="Bulwark March: 30% reduced damage">T</i>}
        {knockedRemaining > 0 && <i className="effect knock-effect" title={`Knocked down: ${knockedRemaining.toFixed(1)} seconds`}>KD</i>}
      </span>
    </button>
  );
}

function PartyList() {
  const party = useGameStore((state) => state.party);
  return (
    <div className="party-list">
      <div className="section-label"><span>Formation</span><small>Q / E target</small></div>
      {party.map((member) => <PartyFrame key={member.id} member={member} />)}
    </div>
  );
}

function AbilityButton({ abilityId }: { abilityId: (typeof ABILITY_ORDER)[number] }) {
  const healerClassId = useGameStore((state) => state.healerClassId);
  const ability = HEALER_CLASSES[healerClassId].abilities[abilityId];
  const time = useGameStore((state) => state.time);
  const cooldowns = useGameStore((state) => state.cooldowns);
  const globalCooldownUntil = useGameStore((state) => state.globalCooldownUntil);
  const mana = useGameStore((state) => state.mana);
  const phase = useGameStore((state) => state.phase);
  const healerAlive = useGameStore((state) => state.party.some((member) => member.id === "aelia" && member.hp > 0));
  const selected = useGameStore((state) => state.party.find((member) => member.id === state.selectedMemberId)!);
  const activeCast = useGameStore((state) => state.activeCast);
  const castAbility = useGameStore((state) => state.castAbility);
  const runModifiers = useGameStore((state) => state.runModifiers);
  const remaining = abilityRemaining(abilityId, time, cooldowns);
  const manaCost = runAbilityManaCost(abilityId, ability.mana, runModifiers);
  const castTime = ability.castTime ? runAbilityCastTime(abilityId, ability.castTime, runModifiers) : 0;
  const cooldownDuration = runAbilityCooldown(abilityId, ability.cooldown, runModifiers);
  const globalRemaining = Math.max(0, globalCooldownUntil - time);
  const noDispel = abilityId === "purify" && selected.debuffs.length === 0;
  const invalidTarget = ability.targeting === "ally" && selected.hp <= 0;
  const disabled = phase !== "combat" || !healerAlive || activeCast !== null || remaining > 0 || globalRemaining > 0 || mana < manaCost || noDispel || invalidTarget;
  const resourceCopy = `${manaCost ? `${manaCost} mana` : "free"}${castTime ? ` · ${castTime.toFixed(1)}s` : ""}`;

  return (
    <button
      className={`ability ability-${abilityId} ${remaining > 0 || globalRemaining > 0 ? "on-cooldown" : ""}`}
      style={{ "--ability-color": ability.color } as React.CSSProperties}
      onClick={() => castAbility(abilityId)}
      disabled={disabled}
      title={ability.description}
      aria-label={`${ability.name}. ${ability.description}`}
    >
      <span className="ability-key">{ability.key}</span>
      <span className="ability-icon">{ability.icon}</span>
      <span className="ability-copy"><strong>{ability.shortName}</strong><small>{resourceCopy}</small></span>
      <span className="ability-pad">{ability.gamepad}</span>
      {remaining > 0 && (
        <span className="cooldown-mask" style={{ "--cooldown-progress": Math.min(1, remaining / cooldownDuration) } as React.CSSProperties}>
          <b>{remaining < 1 ? remaining.toFixed(1) : Math.ceil(remaining)}</b>
        </span>
      )}
      {remaining <= 0 && globalRemaining > 0 && (
        <span className="cooldown-mask global-cooldown" style={{ "--cooldown-progress": Math.min(1, globalRemaining / GLOBAL_COOLDOWN_SECONDS) } as React.CSSProperties}>
          <b>{globalRemaining.toFixed(1)}</b>
        </span>
      )}
    </button>
  );
}

function AbilityTray() {
  const healerClassId = useGameStore((state) => state.healerClassId);
  const healer = HEALER_CLASSES[healerClassId];
  const mana = useGameStore((state) => state.mana);
  const maxMana = useGameStore((state) => state.maxMana);
  const selected = useGameStore((state) => state.party.find((member) => member.id === state.selectedMemberId)!);
  const time = useGameStore((state) => state.time);
  const boss = useGameStore((state) => state.boss);
  const bossMotion = useGameStore((state) => state.bossMotion);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  const mechanic = upcomingEncounterMechanic({ boss, bossMotion, additionalBosses, time });
  return (
    <div className="ability-column">
      <div className="ability-meta">
        <div className="target-chip"><span>Target</span><strong>{selected.name}</strong></div>
        <div className="mana-wrap"><span>{healer.resourceName}</span><b>{Math.ceil(mana)}</b><i><em style={{ width: `${(mana / maxMana) * 100}%` }} /></i></div>
      </div>
      <div className="ability-grid">
        {ABILITY_ORDER.map((abilityId) => <AbilityButton key={abilityId} abilityId={abilityId} />)}
      </div>
      <div className={`incoming-strip ${mechanic.urgent ? "is-urgent" : ""}`}>
        <span className="incoming-icon">⌁</span>
        <span><small>Incoming</small><strong>{mechanic.name}</strong></span>
        <b>{mechanic.remaining.toFixed(1)}s</b>
        <i><em style={{ width: `${Math.min(100, (mechanic.remaining / mechanic.cycle) * 100)}%` }} /></i>
      </div>
    </div>
  );
}

function BriefingPanel() {
  const healerClassId = useGameStore((state) => state.healerClassId);
  const healer = HEALER_CLASSES[healerClassId];
  const startEncounter = useGameStore((state) => state.startEncounter);
  const primaryBoss = useGameStore((state) => state.boss);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  const bosses = [primaryBoss, ...additionalBosses.map((entry) => entry.boss)];
  const definitions = bosses.map((boss) => BOSS_DEFINITIONS[boss.id]);
  const bossNames = bosses.map((boss) => boss.name).join(" & ");
  return (
    <div className="briefing-panel">
      <div className="briefing-class">
        <div className="class-crest" style={{ color: healer.color }}>{healer.icon}</div>
        <span>Chosen discipline</span>
        <h2>{healer.specialization}</h2>
        <p>{healer.description} {definitions.map((boss) => boss.briefing).join(" ")}</p>
        <button className="start-button" onClick={startEncounter}><span>Face {bossNames}</span><small>{DEFAULT_CONTROLLER_GLYPHS.start} / ENTER</small></button>
      </div>
      <div className="briefing-kit">
        <div className="section-label"><span>Prepared skills</span><small>6 equipped</small></div>
        <div className="kit-grid">
          {ABILITY_ORDER.map((abilityId) => {
            const ability = healer.abilities[abilityId];
            return (
              <div className="kit-skill" key={abilityId} style={{ "--ability-color": ability.color } as React.CSSProperties}>
                <b>{ability.icon}</b><span><strong>{ability.shortName}</strong><small>{ability.description}</small></span>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function EndPanel({ onExit }: { onExit?: () => void }) {
  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 endlessChoiceSelection = useGameStore((state) => state.endlessChoiceSelection);
  const setEndlessChoiceSelection = useGameStore((state) => state.setEndlessChoiceSelection);
  const startRogueTrialsEndless = useGameStore((state) => state.startRogueTrialsEndless);
  const time = useGameStore((state) => state.time);
  const party = useGameStore((state) => state.party);
  const restart = useGameStore((state) => state.restart);
  const startEncounter = useGameStore((state) => state.startEncounter);
  const totalHp = party.reduce((sum, member) => sum + member.hp, 0);
  const totalMax = party.reduce((sum, member) => sum + member.maxHp, 0);
  const showEndlessChoice = phase === "victory" && runMode === "rogue-trials" && round === 5 && !endlessMode;
  const endlessDefeat = phase === "defeat" && endlessMode;
  return (
    <div className={`end-panel end-${phase}`}>
      <span className="end-mark">{phase === "victory" ? "✦" : "×"}</span>
      <small>{showEndlessChoice ? "ROGUE TRIALS CLEARED" : endlessDefeat ? "ENDLESS RUN COMPLETE" : phase === "victory" ? "TRIAL COMPLETE" : "FORMATION LOST"}</small>
      <h2>{showEndlessChoice ? "The trial can continue" : endlessDefeat ? `${endlessBossKills} bosses defeated` : phase === "victory" ? "Five souls endure" : "The vault claims its due"}</h2>
      <div className="result-stats">
        <span><small>Duration</small><strong>{Math.floor(time / 60)}:{String(Math.floor(time % 60)).padStart(2, "0")}</strong></span>
        <span><small>Party vitality</small><strong>{Math.round((totalHp / totalMax) * 100)}%</strong></span>
        <span><small>{endlessDefeat ? "Endless kills" : "Boss"}</small><strong>{endlessDefeat ? endlessBossKills : phase === "victory" ? "Defeated" : "Standing"}</strong></span>
      </div>
      {phase === "victory" && <RewardSummary />}
      {showEndlessChoice ? <div className="end-actions endless-choice-actions">
        <button
          className={endlessChoiceSelection === "continue" ? "is-controller-focused" : ""}
          onFocus={() => setEndlessChoiceSelection("continue")}
          onPointerEnter={() => setEndlessChoiceSelection("continue")}
          onClick={startRogueTrialsEndless}
        >Continue Endless</button>
        <button
          className={`secondary ${endlessChoiceSelection === "quit" ? "is-controller-focused" : ""}`}
          onFocus={() => setEndlessChoiceSelection("quit")}
          onPointerEnter={() => setEndlessChoiceSelection("quit")}
          onClick={onExit}
        >Quit to Main Menu</button>
      </div> : <div className="end-actions">
        <button onClick={() => { restart(); startEncounter(); }}>Run again</button>
        <button className="secondary" onClick={endlessDefeat ? onExit : restart}>{endlessDefeat ? "Return to main menu" : "Return to briefing"}</button>
      </div>}
    </div>
  );
}

function IntermissionStatusPanel() {
  const round = useGameStore((state) => state.round);
  return (
    <div className="intermission-status" aria-label={`Round ${round} cleared. Choose a blessing on the top display.`}>
      <i>✦</i>
      <span>Round {round} cleared</span>
      <h2>Choose on top display</h2>
      <p>Next encounter stays locked until one blessing is claimed.</p>
      <RewardSummary />
      <small>Use D-pad to choose · {DEFAULT_CONTROLLER_GLYPHS.confirm} to claim</small>
    </div>
  );
}

function CombatPanel({ onExit }: { onExit?: () => void }) {
  const phase = useGameStore((state) => state.phase);
  if (phase === "briefing") return <BriefingPanel />;
  if (phase === "intermission") return <IntermissionStatusPanel />;
  if (phase === "victory" || phase === "defeat") return <EndPanel onExit={onExit} />;
  return <div className="combat-panel"><PartyList /><AbilityTray /></div>;
}

function MapPanel() {
  const playerPosition = useGameStore((state) => state.playerPosition);
  const partyPositions = useGameStore((state) => state.partyPositions);
  const bossMotion = useGameStore((state) => state.bossMotion);
  const additionalBosses = useGameStore((state) => state.additionalBosses);
  const barrier = useGameStore((state) => state.barrier);
  const time = useGameStore((state) => state.time);
  const phase = useGameStore((state) => state.phase);
  const bossId = useGameStore((state) => state.bossId);
  const bossDefinition = BOSS_DEFINITIONS[bossId];
  const playerX = 120 + playerPosition[0] * 7;
  const playerY = 143 + playerPosition[1] * 5.3;
  const bossMotions = [bossMotion, ...additionalBosses.map((entry) => entry.motion)];
  return (
    <div className="map-panel">
      <div className="map-copy">
        <span>Ember Vault</span>
        <h2>{bossDefinition.mapTitle}</h2>
        <p>Single chamber trial. {bossDefinition.mapCopy}</p>
        <div className="map-legend"><i className="legend-party" /> Party <i className="legend-boss" /> Boss <i className="legend-exit" /> Entry</div>
      </div>
      <div className="map-canvas">
        <svg viewBox="0 0 240 280" role="img" aria-label="Ember Vault encounter map">
          <defs>
            <radialGradient id="room" cx="50%" cy="45%" r="60%"><stop offset="0" stopColor="#1b302b" /><stop offset="1" stopColor="#0a1715" /></radialGradient>
          </defs>
          <path className="map-room" d="M120 18 C181 18 218 62 218 128 C218 190 184 231 149 242 L149 271 L91 271 L91 242 C53 229 22 190 22 128 C22 62 59 18 120 18Z" fill="url(#room)" />
          <path className="map-ring" d="M120 39 C169 39 195 75 195 128 C195 181 168 219 120 219 C72 219 45 181 45 128 C45 75 71 39 120 39Z" />
          <path className="map-glyph" d="M120 74 L145 119 L120 164 L95 119 Z M76 175 L120 196 L164 175" />
          {Array.from({ length: 8 }, (_, index) => {
            const angle = (index / 8) * Math.PI * 2;
            return <circle key={index} className="map-pillar" cx={120 + Math.sin(angle) * 77} cy={128 + Math.cos(angle) * 76} r="4" />;
          })}
          {bossMotions.map((motion, index) => {
            const bossX = 120 + motion.position[0] * 7;
            const bossY = 143 + motion.position[1] * 5.3;
            return <g key={`${motion.bossId}-${index}`}>
              <circle className="map-boss" cx={bossX} cy={bossY} r="9" />
              <path className="map-boss-arrow" d={`M${bossX} ${bossY - 15} L${bossX + 6} ${bossY - 5} L${bossX - 6} ${bossY - 5} Z`} />
            </g>;
          })}
          <circle className="map-player-pulse" cx={playerX} cy={playerY} r="12" />
          <circle className="map-player" cx={playerX} cy={playerY} r="6" />
          {barrier.expiresAt > time && (
            <ellipse
              className="map-barrier"
              cx={120 + barrier.center[0] * 7}
              cy={143 + barrier.center[1] * 5.3}
              rx="21"
              ry="15.9"
            />
          )}
          {(["brann", "nia", "orin", "vale"] as const).map((memberId) => (
            <circle
              key={memberId}
              className={`map-ally map-ally-${memberId}`}
              data-member-id={memberId}
              cx={120 + partyPositions[memberId][0] * 7}
              cy={143 + partyPositions[memberId][1] * 5.3}
              r="4"
            />
          ))}
          <path className="map-entry" d="M103 258 L120 245 L137 258" />
        </svg>
        <span className="map-state">{phase === "combat" ? "LIVE TACTICAL FEED" : "STATIC ROUTE"}</span>
      </div>
    </div>
  );
}

function PackPanel() {
  const inventory = useGameStore((state) => state.inventory);
  const selectedItemId = useGameStore((state) => state.selectedItemId);
  const selectItem = useGameStore((state) => state.selectItem);
  const item = inventory.find((entry) => entry.id === selectedItemId) ?? inventory[0];
  return (
    <div className="pack-panel">
      <div className="item-list">
        <div className="section-label"><span>Field pack</span><small>{inventory.length} / 12</small></div>
        {inventory.map((entry) => (
          <button key={entry.id} onClick={() => selectItem(entry.id)} className={entry.id === item.id ? "is-selected" : ""}>
            <b>{entry.icon}</b><span><strong>{entry.name}</strong><small>{entry.slot}{entry.equipped ? " · Equipped" : ""}</small></span><i>{entry.rarity[0]}</i>
          </button>
        ))}
      </div>
      <article className={`item-tooltip rarity-${item.rarity.toLowerCase()}`}>
        <span className="tooltip-label">Item detail · lower display</span>
        <div className="tooltip-title"><b>{item.icon}</b><span><h2>{item.name}</h2><small>{item.rarity} {item.slot}</small></span></div>
        <div className="tooltip-stats">{item.stats.map((stat) => <strong key={stat}>{stat}</strong>)}</div>
        <p>{item.effect}</p>
        <footer><span>{item.equipped ? "✓ Equipped" : "Not equipped"}</span><small>Compare: hold Y</small></footer>
      </article>
    </div>
  );
}

const tabs: { id: BottomTab; label: string; icon: string; key: string }[] = [
  { id: "combat", label: "Heal", icon: "✦", key: "" },
  { id: "map", label: "Map", icon: "⌁", key: "M" },
  { id: "pack", label: "Pack", icon: "▧", key: "I" },
];

export function BottomScreen({ onExit }: { onExit?: () => void } = {}) {
  const activeTab = useGameStore((state) => state.activeTab);
  const setActiveTab = useGameStore((state) => state.setActiveTab);
  const phase = useGameStore((state) => state.phase);
  const paused = useGameStore((state) => state.paused);
  return (
    <section className="display bottom-display" aria-label="Tactical touch display">
      <header className="lower-header">
        <div className="lower-brand"><span>IH</span><strong>I Want To Heal</strong><small>{phase === "combat" ? "Encounter live" : "Field console"}</small></div>
        <nav aria-label="Lower display sections">
          {tabs.map((tab) => (
            <button key={tab.id} className={activeTab === tab.id ? "is-active" : ""} onClick={() => setActiveTab(tab.id)}>
              <i>{tab.icon}</i><span>{tab.label}</span>{tab.key && <small>{tab.key}</small>}
            </button>
          ))}
        </nav>
      </header>
      <main className="lower-content">
        {activeTab === "combat" && <CombatPanel onExit={onExit} />}
        {activeTab === "map" && <MapPanel />}
        {activeTab === "pack" && <PackPanel />}
      </main>
      {paused && (
        <div className="lower-pause-overlay" aria-hidden="true">
          <span>PAUSED</span><strong>Encounter suspended</strong><small>{DEFAULT_CONTROLLER_GLYPHS.start} / ESC resumes · ↑↓ selects menu action</small>
        </div>
      )}
    </section>
  );
}
