/**
 * @file Battle modal component displaying animated battle results.
 * @copyright nhcarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */
/* eslint-disable max-lines-per-function -- Complex battle animation and result display */
/* eslint-disable complexity -- Battle result display requires many conditional paths */
import { type JSX, useEffect, useState } from "react";
import { type BattleResult, useGame } from "../../context/gameContext.js";
import { sendNotification } from "../../utils/notification.js";
import { playSound } from "../../utils/sound.js";

/**
 * Converts HP values to a percentage for display.
 * @param current - The current HP value.
 * @param maximum - The maximum HP value.
 * @returns The percentage as a number between 0 and 100.
 */
const toHpPercent = (current: number, maximum: number): number => {
  if (maximum === 0) {
    return 0;
  }
  const scaled = current * 100;
  return scaled / maximum;
};

/**
 * Returns a colour hex string based on the HP percentage.
 * Green above 50%, yellow 25–50%, red below 25%.
 * @param percent - Current HP as a percentage (0–100).
 * @returns A hex colour string.
 */
const getHpColour = (percent: number): string => {
  if (percent > 50) {
    return "#27ae60";
  }
  if (percent > 25) {
    return "#f39c12";
  }
  return "#e74c3c";
};

interface BattleModalProperties {
  readonly battle:    BattleResult;
  readonly onDismiss: ()=> void;
}

/**
 * Renders the battle modal with HP bars and animated battle results.
 * @param props - The battle modal properties.
 * @param props.battle - The battle result data to display.
 * @param props.onDismiss - Callback to dismiss the modal.
 * @returns The JSX element.
 */
const BattleModal = ({
  battle,
  onDismiss,
}: BattleModalProperties): JSX.Element => {
  const { result, bossName } = battle;
  const {
    enableNotifications,
    enableSounds,
    flushBossLoreToasts,
    formatInteger,
    formatNumber,
  } = useGame();

  const [ phase, setPhase ] = useState<"animating" | "result">("animating");

  const bossStartPercent = toHpPercent(result.bossHpBefore, result.bossMaxHp);

  const bossEndPercent = toHpPercent(
    result.bossHpAtBattleEnd,
    result.bossMaxHp,
  );
  const partyEndPercent = toHpPercent(
    result.partyHpRemaining,
    result.partyMaxHp,
  );

  const [ bossHpPercent, setBossHpPercent ] = useState(bossStartPercent);
  const [ partyHpPercent, setPartyHpPercent ] = useState(100);

  useEffect(() => {
    const animationDurationMs = 5000;
    const intervalMs = 50;
    const totalSteps = animationDurationMs / intervalMs;

    const bossHpRange = bossEndPercent - bossStartPercent;
    const bossDelta = bossHpRange / totalSteps;

    const partyHpRange = partyEndPercent - 100;
    const partyDelta = partyHpRange / totalSteps;

    let currentStep = 0;
    // eslint-disable-next-line @typescript-eslint/init-declarations -- assigned inside timeout
    let intervalId: ReturnType<typeof setInterval> | undefined;

    const tick = (): void => {
      currentStep = currentStep + 1;
      if (currentStep >= totalSteps) {
        setBossHpPercent(bossEndPercent);
        setPartyHpPercent(partyEndPercent);
        clearInterval(intervalId);
      } else {
        const bossStep = bossDelta * currentStep;
        setBossHpPercent(bossStartPercent + bossStep);
        const partyStep = partyDelta * currentStep;
        setPartyHpPercent(100 + partyStep);
      }
    };

    const startTimeout = setTimeout(() => {
      intervalId = setInterval(tick, intervalMs);
    }, 200);

    const revealTimeout = setTimeout(() => {
      setPhase("result");
      flushBossLoreToasts();
      if (result.won) {
        if (enableSounds) {
          playSound("bossVictory");
        }
        if (enableNotifications) {
          sendNotification("⚔️ Boss Defeated!", `You defeated ${bossName}!`);
        }
      }
    }, 5200);

    return (): void => {
      clearTimeout(startTimeout);
      clearTimeout(revealTimeout);
      clearInterval(intervalId);
    };
  }, [
    bossEndPercent,
    bossName,
    bossStartPercent,
    enableNotifications,
    enableSounds,
    flushBossLoreToasts,
    partyEndPercent,
    result.won,
  ]);

  const bossHpBarColour = getHpColour(bossHpPercent);
  const partyHpBarColour = getHpColour(partyHpPercent);

  return (
    <div className="modal-overlay">
      <div className="modal battle-modal">
        <h2>
          {"⚔️ Battle: "}
          {bossName}
        </h2>

        <div className="battle-stats">
          <div className="battle-stat">
            <span className="stat-label">{"Your Party DPS"}</span>
            <span className="stat-value">{formatNumber(result.partyDPS)}</span>
          </div>
          <div className="battle-stat-divider">{"vs"}</div>
          <div className="battle-stat">
            <span className="stat-label">{"Boss DPS"}</span>
            <span className="stat-value">{formatNumber(result.bossDPS)}</span>
          </div>
        </div>

        <div className="battle-bars">
          <div className="battle-bar-row">
            <span className="bar-label">
              {"👹 "}
              {bossName}
            </span>
            <div className="hp-bar-container">
              <div
                className="hp-bar-fill"
                style={{
                  backgroundColor: bossHpBarColour,
                  width:           `${bossHpPercent.toFixed(1)}%`,
                }}
              />
            </div>
            <span className="bar-hp">
              {formatNumber(result.bossHpAtBattleEnd)}
              {" / "}
              {formatNumber(result.bossMaxHp)}
            </span>
          </div>

          <div className="vs-divider">{"⚔️ VS ⚔️"}</div>

          <div className="battle-bar-row">
            <span className="bar-label">{"🛡️ Your Party"}</span>
            <div className="hp-bar-container">
              <div
                className="hp-bar-fill party-hp"
                style={{
                  backgroundColor: partyHpBarColour,
                  width:           `${partyHpPercent.toFixed(1)}%`,
                }}
              />
            </div>
            <span className="bar-hp">
              {formatNumber(result.partyHpRemaining)}
              {" / "}
              {formatNumber(result.partyMaxHp)}
            </span>
          </div>
        </div>

        {phase === "animating"
          && <p className="battle-in-progress">{"Battling…"}</p>
        }

        {phase === "result"
          && <div
            className={`battle-outcome ${result.won
              ? "victory"
              : "defeat"}`}
          >
            {result.won
              ? <>
                <h3>{"🏆 Victory!"}</h3>
                {result.rewards === undefined
                  ? null
                  : <div className="battle-rewards">
                    <p>{"Rewards:"}</p>
                    <span>
                      {"🪙 "}
                      {formatNumber(result.rewards.gold)}
                      {" gold"}
                    </span>
                    {result.rewards.essence > 0
                      && <span>
                        {"✨ "}
                        {formatNumber(result.rewards.essence)}
                        {" essence"}
                      </span>
                    }
                    {result.rewards.crystals > 0
                      && <span>
                        {"💎 "}
                        {formatInteger(result.rewards.crystals)}
                        {" crystals"}
                      </span>
                    }
                    {result.rewards.bountyRunestones > 0
                      && <span className="battle-bounty">
                        {"🔮 "}
                        {formatInteger(result.rewards.bountyRunestones)}
                        {" runestones (first kill!)"}
                      </span>
                    }
                  </div>
                }
              </>
              : <>
                <h3>{"💀 Defeat"}</h3>
                <p>{"Your party was defeated. The boss has reset."}</p>
                {result.casualties !== undefined
                && result.casualties.length > 0
                  ? <div className="battle-casualties">
                    <p>{"Casualties:"}</p>
                    {result.casualties.map((casualty) => {
                      return (
                        <span key={casualty.adventurerId}>
                          {"☠️ "}
                          {casualty.killed} {casualty.adventurerId}
                          {" lost"}
                        </span>
                      );
                    })}
                  </div>
                  : null}
              </>
            }
            <button
              className="dismiss-button"
              onClick={onDismiss}
              type="button"
            >
              {"Continue"}
            </button>
          </div>
        }
      </div>
    </div>
  );
};

export { BattleModal };
