/**
 * @file Prestige panel component for ascending and purchasing runestone upgrades.
 * @copyright nhcarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */
/* eslint-disable max-lines-per-function -- Complex component with many render paths */
/* eslint-disable complexity -- Many conditional render paths */
/* eslint-disable max-lines -- Large panel with prestige and shop tabs */
/* eslint-disable max-statements -- Prestige panel manages many local state variables */
import { useState, type JSX } from "react";
import { prestige } from "../../api/client.js";
import { useGame } from "../../context/gameContext.js";
import {
  PRESTIGE_UPGRADES,
  PRESTIGE_UPGRADE_CATEGORY_LABELS,
} from "../../data/prestigeUpgrades.js";
import { cdnImage } from "../../utils/cdn.js";
import { sendNotification } from "../../utils/notification.js";
import { playSound } from "../../utils/sound.js";
import type { PrestigeUpgradeCategory } from "@elysium/types";

const baseThreshold = 1_000_000;
const thresholdScale = 5;
const runestonesPerLevel = 10;

/**
 * Calculates the prestige threshold for a given prestige count.
 * @param prestigeCount - The current prestige count.
 * @returns The required gold to prestige.
 */
const calculateThreshold = (prestigeCount: number): number => {
  return baseThreshold * Math.pow(thresholdScale, prestigeCount);
};

/**
 * Calculates the production multiplier for a given prestige count.
 * @param prestigeCount - The number of times the player has prestiged.
 * @returns The compounding multiplier applied to all income sources.
 */
const calculateProductionMultiplier = (prestigeCount: number): number => {
  return Math.pow(1.15, prestigeCount);
};

/**
 * Calculates the runestone preview for a prestige.
 * @param totalGoldEarned - Total gold earned this run.
 * @param prestigeCount - The current prestige count.
 * @param purchasedUpgradeIds - IDs of purchased prestige upgrades.
 * @returns The predicted runestone reward.
 */
const calculateRunestonePreview = (
  totalGoldEarned: number,
  prestigeCount: number,
  purchasedUpgradeIds: Array<string>,
): number => {
  const threshold = calculateThreshold(prestigeCount);
  const base
    = Math.floor(Math.sqrt(totalGoldEarned / threshold)) * runestonesPerLevel;
  const runestoneMult = PRESTIGE_UPGRADES.filter((upgrade) => {
    return (
      upgrade.category === "runestones"
      && purchasedUpgradeIds.includes(upgrade.id)
    );
  }).reduce((mult, upgrade) => {
    return mult * upgrade.multiplier;
  }, 1);
  return Math.floor(base * runestoneMult);
};

const categoryOrder: Array<PrestigeUpgradeCategory> = [
  "income",
  "click",
  "essence",
  "crystals",
  "runestones",
  "utility",
];

/**
 * Renders the prestige panel with ascension and runestone shop tabs.
 * @returns The JSX element.
 */
const PrestigePanel = (): JSX.Element => {
  const {
    state,
    reload,
    formatNumber,
    buyPrestigeUpgrade,
    enableNotifications,
    enableSounds,
    toggleAutoAdventurer,
    toggleAutoPrestige,
    triggerPrestigeToast,
  } = useGame();
  const [ isPending, setIsPending ] = useState(false);
  const [ result, setResult ] = useState<{
    runestones:          number;
    count:               number;
    milestoneRunestones: number;
  } | null>(null);
  const [ prestigeError, setPrestigeError ] = useState<string | null>(null);
  const [ buyingId, setBuyingId ] = useState<string | null>(null);
  const [ activeTab, setActiveTab ] = useState<"prestige" | "shop">("prestige");

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

  const { autoAdventurer, prestige: prestigeData, player } = state;
  const threshold = calculateThreshold(prestigeData.count);
  const isEligible = player.totalGoldEarned >= threshold;
  const runestonePreview = calculateRunestonePreview(
    player.totalGoldEarned,
    prestigeData.count,
    prestigeData.purchasedUpgradeIds,
  );
  const nextMultiplier = calculateProductionMultiplier(prestigeData.count + 1);

  async function handlePrestige(): Promise<void> {
    setIsPending(true);
    setPrestigeError(null);
    try {
      const data = await prestige({});
      setResult({
        count:               data.newPrestigeCount,
        milestoneRunestones: data.milestoneRunestones,
        runestones:          data.runestones,
      });
      triggerPrestigeToast();
      if (enableSounds) {
        playSound("prestige");
      }
      if (enableNotifications) {
        sendNotification(
          "⭐ Prestige!",
          `You've reached prestige level ${data.newPrestigeCount.toString()}!`,
        );
      }
      await reload();
    } catch (error_: unknown) {
      setPrestigeError(
        error_ instanceof Error
          ? error_.message
          : "Prestige failed",
      );
    } finally {
      setIsPending(false);
    }
  }

  async function handleBuyUpgrade(upgradeId: string): Promise<void> {
    setBuyingId(upgradeId);
    try {
      await buyPrestigeUpgrade(upgradeId);
    } finally {
      setBuyingId(null);
    }
  }

  const upgradesByCategory = categoryOrder.map((categoryId) => {
    const label = PRESTIGE_UPGRADE_CATEGORY_LABELS[categoryId] ?? categoryId;
    const upgrades = PRESTIGE_UPGRADES.filter((upgrade) => {
      return upgrade.category === categoryId;
    });
    return { categoryId, label, upgrades };
  });

  function handlePrestigeClick(): void {
    void handlePrestige();
  }

  function handleAutoAdventurerToggle(): void {
    toggleAutoAdventurer();
  }

  function handleAutoPrestigeToggle(): void {
    toggleAutoPrestige();
  }

  function handlePrestigeTabClick(): void {
    setActiveTab("prestige");
  }

  function handleShopTabClick(): void {
    setActiveTab("shop");
  }

  const progressRatio = player.totalGoldEarned / threshold;
  const progressPct = (progressRatio * 100).toFixed(1);

  return (
    <section className="panel prestige-panel">
      <h2>{"⭐ Prestige"}</h2>

      <div className="prestige-tabs">
        <button
          className={`prestige-tab ${activeTab === "prestige"
            ? "active"
            : ""}`}
          onClick={handlePrestigeTabClick}
          type="button"
        >
          {"Ascend"}
        </button>
        <button
          className={`prestige-tab ${activeTab === "shop"
            ? "active"
            : ""}`}
          onClick={handleShopTabClick}
          type="button"
        >
          {"🔮 Runestone Shop ("}
          {formatNumber(prestigeData.runestones)}
          {" stones)"}
        </button>
      </div>

      {activeTab === "prestige"
        && <>
          <p>
            {"Prestige resets your progress but grants "}
            <strong>{"Runestones"}</strong>
            {"— permanent currency used for powerful upgrades."}
            {" Each prestige multiplies your global production by ×1.15"}
            {" (compounding each run)."}
          </p>

          <div className="prestige-status">
            <p>
              {"Total gold this run: "}
              <strong>{formatNumber(player.totalGoldEarned)}</strong>
            </p>
            <p>
              {"Required to prestige: "}
              <strong>{formatNumber(threshold)}</strong>
            </p>
            <p>
              {"Prestige count: "}
              <strong>{prestigeData.count}</strong>
            </p>
            <p>
              {"Current production multiplier: "}
              <strong>
                {"×"}
                {prestigeData.productionMultiplier.toFixed(2)}
              </strong>
            </p>
            <p>
              {"After next prestige: "}
              <strong>
                {"×"}
                {nextMultiplier.toFixed(2)}
              </strong>
            </p>
            <p>
              {"Runestones: "}
              <strong>{formatNumber(prestigeData.runestones)}</strong>
            </p>
            {isEligible
              ? <p className="runestone-preview">
                {"Runestones on prestige: "}
                <strong>
                  {"+"}
                  {formatNumber(runestonePreview)}
                </strong>
              </p>
              : null}
            {isEligible
              ? null
              : <p className="prestige-progress">
                {"Progress: "}
                {formatNumber(player.totalGoldEarned)}
                {" / "}
                {formatNumber(threshold)}
                {" ("}
                {progressPct}
                {"%"}
                {")"}
              </p>
            }
          </div>

          {isEligible
            ? <div className="prestige-form">
              <p>{"You are ready to prestige!"}</p>
              <button
                className="prestige-button"
                disabled={isPending}
                onClick={handlePrestigeClick}
                type="button"
              >
                {isPending
                  ? "Ascending..."
                  : `✨ Ascend (+${formatNumber(runestonePreview)} Runestones)`}
              </button>
              {prestigeError === null
                ? null
                : <p className="error">{prestigeError}</p>
              }
              {result === null
                ? null
                : <p className="success">
                  {"Ascended to Prestige "}
                  {result.count}
                  {"! Earned "}
                  {formatNumber(result.runestones)}
                  {" Runestones."}
                  {result.milestoneRunestones > 0
                    && <>
                      {" 🎉 Milestone bonus: +"}
                      {formatNumber(result.milestoneRunestones)}
                      {" Runestones!"}
                    </>
                  }
                </p>
              }
            </div>
            : <p className="prestige-locked">
              {"Earn "}
              {formatNumber(threshold - player.totalGoldEarned)}
              {" more gold to unlock prestige."}
            </p>
          }
        </>
      }

      {activeTab === "shop"
        && <div className="runestone-shop">
          <p className="shop-balance">
            {"Balance: "}
            <strong>
              {formatNumber(prestigeData.runestones)}
              {" Runestones"}
            </strong>
          </p>

          {upgradesByCategory.map(({ categoryId, label, upgrades }) => {
            return (
              <div className="shop-category" key={categoryId}>
                <h3>{label}</h3>
                <div className="shop-upgrades">
                  {upgrades.map((upgrade) => {
                    const purchased = prestigeData.purchasedUpgradeIds.includes(
                      upgrade.id,
                    );
                    const canAfford
                      = prestigeData.runestones >= upgrade.runestonesCost;
                    const isLoading = buyingId === upgrade.id;

                    const isAutoAdventurerToggle
                      = upgrade.id === "auto_adventurer" && purchased;
                    const autoAdventurerEnabled = autoAdventurer ?? false;
                    const isAutoPrestigeToggle
                      = upgrade.id === "auto_prestige" && purchased;
                    const autoPrestigeEnabled
                      = prestigeData.autoPrestigeEnabled ?? false;

                    function handleBuyClick(): void {
                      void handleBuyUpgrade(upgrade.id);
                    }

                    return (
                      <div
                        className={`shop-upgrade-card ${
                          purchased
                            ? "purchased"
                            : ""
                        } ${!canAfford && !purchased
                          ? "unaffordable"
                          : ""}`}
                        key={upgrade.id}
                      >
                        <img
                          alt={upgrade.name}
                          className="card-thumbnail"
                          src={cdnImage("prestige-upgrades", upgrade.id)}
                        />
                        <div className="shop-upgrade-info">
                          <h4>{upgrade.name}</h4>
                          <p>{upgrade.description}</p>
                          <p className="upgrade-cost">
                            {purchased
                              ? "✅ Purchased"
                              : `🔮 ${formatNumber(upgrade.runestonesCost)} Runestones`}
                          </p>
                        </div>
                        {isAutoAdventurerToggle
                          ? <button
                            className={`auto-prestige-toggle ${
                              autoAdventurerEnabled
                                ? "enabled"
                                : "disabled"
                            }`}
                            onClick={handleAutoAdventurerToggle}
                            type="button"
                          >
                            {autoAdventurerEnabled
                              ? "⚡ Auto ON"
                              : "⏸ Auto OFF"}
                          </button>
                          : null}
                        {isAutoPrestigeToggle
                          ? <button
                            className={`auto-prestige-toggle ${
                              autoPrestigeEnabled
                                ? "enabled"
                                : "disabled"
                            }`}
                            onClick={handleAutoPrestigeToggle}
                            type="button"
                          >
                            {autoPrestigeEnabled
                              ? "⚡ Auto ON"
                              : "⏸ Auto OFF"}
                          </button>
                          : null}
                        {purchased
                          ? null
                          : <button
                            className="buy-upgrade-button"
                            disabled={
                              !canAfford || isLoading || buyingId !== null
                            }
                            onClick={handleBuyClick}
                            type="button"
                          >
                            {isLoading
                              ? "Buying..."
                              : "Buy"}
                          </button>
                        }
                      </div>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      }
    </section>
  );
};

export { PrestigePanel };
