import type { Boss } from "@elysium/types";
import { useState } from "react";
import { useGame } from "../../context/GameContext.js";
import { formatNumber } from "../../utils/format.js";
import { LockToggle } from "../ui/LockToggle.js";
import { ZoneSelector } from "./ZoneSelector.js";

interface BossCardProps {
  boss: Boss;
  prestigeCount: number;
  onChallenge: (bossId: string) => void;
  isChallenging: boolean;
  unlockHint?: string | undefined;
}

const BossCard = ({
  boss,
  prestigeCount,
  onChallenge,
  isChallenging,
  unlockHint,
}: BossCardProps): React.JSX.Element => {
  const hpPercent = (boss.currentHp / boss.maxHp) * 100;
  const isPrestigeLocked = boss.prestigeRequirement > prestigeCount;
  const canChallenge =
    (boss.status === "available" || boss.status === "in_progress") && !isChallenging;

  return (
    <div className={`boss-card boss-${boss.status}`}>
      <div className="boss-info">
        <h3>{boss.name}</h3>
        <p>{boss.description}</p>
        {isPrestigeLocked && boss.status === "locked" && (
          <p className="prestige-lock">
            🔒 Requires Prestige {boss.prestigeRequirement}
          </p>
        )}
        {!isPrestigeLocked && boss.status === "locked" && unlockHint && (
          <p className="unlock-hint">{unlockHint}</p>
        )}
      </div>

      {boss.status !== "locked" && boss.status !== "defeated" && (
        <div className="boss-hp">
          <div className="hp-bar">
            <div
              className="hp-fill"
              style={{ width: `${hpPercent.toFixed(1)}%` }}
            />
          </div>
          <span className="hp-text">
            {formatNumber(boss.currentHp)} / {formatNumber(boss.maxHp)} HP
          </span>
        </div>
      )}

      <div className="boss-meta">
        <span className="boss-dps">💢 Boss DPS: {formatNumber(boss.damagePerSecond)}</span>
      </div>

      <div className="boss-rewards">
        <span>🪙 {formatNumber(boss.goldReward)}</span>
        {boss.essenceReward > 0 && (
          <span>✨ {formatNumber(boss.essenceReward)}</span>
        )}
        {boss.crystalReward > 0 && (
          <span>💎 {formatNumber(boss.crystalReward)}</span>
        )}
        {(boss.equipmentRewards ?? []).length > 0 && (
          <span>🗡️ {boss.equipmentRewards.length} Equipment</span>
        )}
      </div>

      {(boss.status === "available" || boss.status === "in_progress") && (
        <button
          className="attack-button"
          disabled={!canChallenge}
          onClick={() => {
            onChallenge(boss.id);
          }}
          type="button"
        >
          {isChallenging ? "⚔️ Battling…" : "⚔️ Challenge"}
        </button>
      )}

      {boss.status === "defeated" && (
        <span className="boss-badge defeated">☠️ Defeated</span>
      )}
    </div>
  );
};

export const BossPanel = (): React.JSX.Element => {
  const { state, challengeBoss } = useGame();
  const [challengingBossId, setChallengingBossId] = useState<string | null>(null);
  const [activeZoneId, setActiveZoneId] = useState("verdant_vale");
  const [showLocked, setShowLocked] = useState(true);

  if (!state) return <section className="panel"><p>Loading...</p></section>;

  // Calculate party combat stats including equipment multiplier
  let globalMultiplier = 1;
  for (const upgrade of state.upgrades) {
    if (upgrade.purchased && upgrade.target === "global") {
      globalMultiplier *= upgrade.multiplier;
    }
  }
  const prestigeMultiplier = 1 + state.prestige.count * 0.1;
  const equipmentCombatMultiplier = (state.equipment ?? [])
    .filter((e) => e.equipped && e.bonus.combatMultiplier != null)
    .reduce((mult, e) => mult * (e.bonus.combatMultiplier ?? 1), 1);

  let partyDPS = 0;
  let partyHP = 0;
  for (const adventurer of state.adventurers) {
    if (adventurer.count === 0) continue;
    let adventurerMultiplier = 1;
    for (const upgrade of state.upgrades) {
      if (
        upgrade.purchased &&
        upgrade.target === "adventurer" &&
        upgrade.adventurerId === adventurer.id
      ) {
        adventurerMultiplier *= upgrade.multiplier;
      }
    }
    partyDPS +=
      adventurer.combatPower *
      adventurer.count *
      adventurerMultiplier *
      globalMultiplier *
      prestigeMultiplier;
    partyHP += adventurer.level * 50 * adventurer.count;
  }
  partyDPS *= equipmentCombatMultiplier;

  const handleChallenge = async (bossId: string): Promise<void> => {
    setChallengingBossId(bossId);
    try {
      await challengeBoss(bossId);
    } finally {
      setChallengingBossId(null);
    }
  };

  const zones = state.zones ?? [];
  const zoneBosses = state.bosses.filter((b) => b.zoneId === activeZoneId);
  const lockedCount = zoneBosses.filter((b) => b.status === "locked").length;
  const visibleBosses = showLocked
    ? zoneBosses
    : zoneBosses.filter((b) => b.status !== "locked");

  const bossUnlockHints = new Map<string, string>();
  for (const zone of zones) {
    const allZoneBosses = state.bosses.filter((b) => b.zoneId === zone.id);
    for (let i = 0; i < allZoneBosses.length; i++) {
      const boss = allZoneBosses[i];
      if (!boss || boss.status !== "locked") continue;
      if (i === 0) {
        const parts: string[] = [];
        if (zone.unlockBossId) {
          const gateBoss = state.bosses.find((b) => b.id === zone.unlockBossId);
          if (gateBoss) parts.push(`⚔️ Defeat: ${gateBoss.name}`);
        }
        if (zone.unlockQuestId) {
          const gateQuest = state.quests.find((q) => q.id === zone.unlockQuestId);
          if (gateQuest) parts.push(`📜 Complete: ${gateQuest.name}`);
        }
        if (parts.length > 0) {
          bossUnlockHints.set(boss.id, parts.join(" & "));
        }
      } else {
        const prevBoss = allZoneBosses[i - 1];
        if (prevBoss) {
          bossUnlockHints.set(boss.id, `⚔️ Defeat: ${prevBoss.name} first`);
        }
      }
    }
  }

  return (
    <section className="panel boss-panel">
      <div className="panel-header">
        <h2>Boss Encounters</h2>
        <LockToggle
          lockedCount={lockedCount}
          showLocked={showLocked}
          onToggle={() => { setShowLocked((v) => !v); }}
        />
      </div>

      <ZoneSelector
        activeZoneId={activeZoneId}
        zones={zones}
        onSelectZone={setActiveZoneId}
      />

      <div className="party-combat-stats">
        <div className="combat-stat">
          <span className="stat-label">⚔️ Party DPS</span>
          <span className="stat-value">{formatNumber(partyDPS)}</span>
        </div>
        <div className="combat-stat">
          <span className="stat-label">❤️ Party HP</span>
          <span className="stat-value">{formatNumber(partyHP)}</span>
        </div>
      </div>

      <div className="boss-list">
        {visibleBosses.map((boss) => (
          <BossCard
            key={boss.id}
            boss={boss}
            isChallenging={challengingBossId === boss.id}
            prestigeCount={state.prestige.count}
            unlockHint={bossUnlockHints.get(boss.id)}
            onChallenge={(id) => {
              void handleChallenge(id);
            }}
          />
        ))}
        {visibleBosses.length === 0 && (
          <p className="empty-zone">No bosses to show in this zone.</p>
        )}
      </div>
    </section>
  );
};
