/**
 * @file Upgrade panel component for purchasing game upgrades.
 * @copyright nhcarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */
/* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to the panel */
/* eslint-disable max-lines-per-function -- Complex component with many render paths */
/* eslint-disable complexity -- UpgradeCard has many conditional render paths for states */
import { type JSX, useState } from "react";
import { useGame } from "../../context/gameContext.js";
import { cdnImage } from "../../utils/cdn.js";
import { LockToggle } from "../ui/lockToggle.js";
import type { Adventurer, Upgrade } from "@elysium/types";

interface UpgradeCardProperties {
  readonly upgrade:         Upgrade;
  readonly currentGold:     number;
  readonly currentEssence:  number;
  readonly currentCrystals: number;
  readonly unlockHint:      string | undefined;
  readonly formatNumber:    (n: number)=> string;
  readonly adventurers:     ReadonlyArray<Adventurer>;
}

/**
 * Renders a single upgrade card.
 * @param props - The upgrade card properties.
 * @param props.upgrade - The upgrade data.
 * @param props.currentGold - The current gold amount.
 * @param props.currentEssence - The current essence amount.
 * @param props.currentCrystals - The current crystals amount.
 * @param props.unlockHint - Optional hint for how to unlock this upgrade.
 * @param props.formatNumber - The number formatting utility function.
 * @param props.adventurers - The list of adventurers, used to resolve the affected adventurer name.
 * @returns The JSX element.
 */
const UpgradeCard = ({
  upgrade,
  currentGold,
  currentEssence,
  currentCrystals,
  unlockHint,
  formatNumber,
  adventurers,
}: UpgradeCardProperties): JSX.Element => {
  const { buyUpgrade } = useGame();
  const adventurerName = upgrade.adventurerId === undefined
    ? undefined
    : adventurers.find((adventurer) => {
      return adventurer.id === upgrade.adventurerId;
    })?.name;
  const canAfford
    = currentGold >= upgrade.costGold
    && currentEssence >= upgrade.costEssence
    && currentCrystals >= upgrade.costCrystals;

  function handleBuy(): void {
    buyUpgrade(upgrade.id);
  }

  if (upgrade.unlocked && upgrade.purchased) {
    return (
      <div className="upgrade-card purchased">
        <img
          alt={upgrade.name}
          className="card-thumbnail"
          src={cdnImage("upgrades", upgrade.id)}
        />
        <span className="upgrade-name">
          {"✅ "}
          {upgrade.name}
        </span>
        <span className="upgrade-desc">{upgrade.description}</span>
        {adventurerName === undefined
          ? null
          : <span className="upgrade-target">
            {"🗡️ Affects: "}
            {adventurerName}
          </span>
        }
      </div>
    );
  }

  if (upgrade.unlocked) {
    return (
      <div className="upgrade-card">
        <img
          alt={upgrade.name}
          className="card-thumbnail"
          src={cdnImage("upgrades", upgrade.id)}
        />
        <div className="upgrade-info">
          <h3>{upgrade.name}</h3>
          <p>{upgrade.description}</p>
          {adventurerName === undefined
            ? null
            : <p className="upgrade-target">
              {"🗡️ Affects: "}
              {adventurerName}
            </p>
          }
          <p className="upgrade-multiplier">
            {"×"}
            {upgrade.multiplier}
            {" multiplier"}
          </p>
        </div>
        <div className="upgrade-cost">
          {upgrade.costGold > 0
            && <span>
              {"🪙 "}
              {formatNumber(upgrade.costGold)}
            </span>
          }
          {upgrade.costEssence > 0
            && <span>
              {"✨ "}
              {formatNumber(upgrade.costEssence)}
            </span>
          }
          {upgrade.costCrystals > 0
            && <span>
              {"💎 "}
              {formatNumber(upgrade.costCrystals)}
            </span>
          }
        </div>
        <button
          className="buy-button"
          disabled={!canAfford}
          onClick={handleBuy}
          type="button"
        >
          {"Buy"}
        </button>
      </div>
    );
  }

  return (
    <div className="upgrade-card locked">
      <img
        alt={upgrade.name}
        className="card-thumbnail"
        src={cdnImage("upgrades", upgrade.id)}
      />
      <div className="upgrade-info">
        <h3>
          {"🔒 "}
          {upgrade.name}
        </h3>
        <p>{upgrade.description}</p>
        {adventurerName === undefined
          ? null
          : <p className="upgrade-target">
            {"🗡️ Affects: "}
            {adventurerName}
          </p>
        }
        <p className="upgrade-multiplier">
          {"×"}
          {upgrade.multiplier}
          {" multiplier"}
        </p>
      </div>
      <div className="upgrade-cost">
        {upgrade.costGold > 0
          && <span>
            {"🪙 "}
            {formatNumber(upgrade.costGold)}
          </span>
        }
        {upgrade.costEssence > 0
          && <span>
            {"✨ "}
            {formatNumber(upgrade.costEssence)}
          </span>
        }
        {upgrade.costCrystals > 0
          && <span>
            {"💎 "}
            {formatNumber(upgrade.costCrystals)}
          </span>
        }
      </div>
      <span className="upgrade-locked-label">{"Locked"}</span>
      {unlockHint === undefined
        ? null
        : <p className="unlock-hint">{unlockHint}</p>
      }
    </div>
  );
};

/**
 * Renders the upgrade panel with all available, locked, and purchased upgrades.
 * @returns The JSX element.
 */
const UpgradePanel = (): JSX.Element => {
  const { state, formatNumber } = useGame();
  const [ showLocked, setShowLocked ] = useState(true);

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

  const { adventurers, bosses, quests, upgrades, resources } = state;
  const purchased = upgrades.filter((upgrade) => {
    return upgrade.purchased;
  });
  const available = upgrades.filter((upgrade) => {
    return upgrade.unlocked && !upgrade.purchased;
  });
  const locked = upgrades.filter((upgrade) => {
    return !upgrade.unlocked;
  });

  const upgradeUnlockHints = new Map<string, string>();
  for (const { upgradeRewards, name: bossName } of bosses) {
    for (const upgradeId of upgradeRewards) {
      upgradeUnlockHints.set(upgradeId, `⚔️ Defeat: ${bossName}`);
    }
  }
  for (const { rewards, name: questName } of quests) {
    for (const reward of rewards) {
      if (
        reward.type === "upgrade"
        && reward.targetId !== undefined
        && !upgradeUnlockHints.has(reward.targetId)
      ) {
        upgradeUnlockHints.set(reward.targetId, `📜 Complete: ${questName}`);
      }
    }
  }

  function handleToggle(): void {
    setShowLocked((current) => {
      return !current;
    });
  }

  return (
    <section className="panel upgrade-panel">
      <div className="panel-header">
        <h2>{"Upgrades"}</h2>
        <LockToggle
          lockedCount={locked.length}
          onToggle={handleToggle}
          showLocked={showLocked}
        />
      </div>
      <p className="upgrade-progress">
        {purchased.length}
        {" / "}
        {upgrades.length}
        {" purchased"}
      </p>
      <p className="upgrade-stacking-note">
        {"💡 Upgrade multipliers stack multiplicatively — two ×2 upgrades"
          + " combine to give ×4, not ×3."}
      </p>
      {upgrades.length === 0
        ? <p className="empty-state">
          {"No upgrades available yet — keep adventuring!"}
        </p>
        : <div className="upgrade-list">
          {available.map((upgrade) => {
            return (
              <UpgradeCard
                adventurers={adventurers}
                currentCrystals={resources.crystals}
                currentEssence={resources.essence}
                currentGold={resources.gold}
                formatNumber={formatNumber}
                key={upgrade.id}
                unlockHint={undefined}
                upgrade={upgrade}
              />
            );
          })}
          {purchased.map((upgrade) => {
            return (
              <UpgradeCard
                adventurers={adventurers}
                currentCrystals={resources.crystals}
                currentEssence={resources.essence}
                currentGold={resources.gold}
                formatNumber={formatNumber}
                key={upgrade.id}
                unlockHint={undefined}
                upgrade={upgrade}
              />
            );
          })}
          {showLocked
            ? locked.map((upgrade) => {
              return (
                <UpgradeCard
                  adventurers={adventurers}
                  currentCrystals={resources.crystals}
                  currentEssence={resources.essence}
                  currentGold={resources.gold}
                  formatNumber={formatNumber}
                  key={upgrade.id}
                  unlockHint={upgradeUnlockHints.get(upgrade.id)}
                  upgrade={upgrade}
                />
              );
            })
            : null}
        </div>
      }
    </section>
  );
};

export { UpgradePanel };
