/**
 * @file Companion panel component for managing active companions.
 * @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 companion card with conditional renders */
import { COMPANIONS, type Companion } from "@elysium/types";
import { useGame } from "../../context/gameContext.js";
import type { JSX } from "react";

const bonusLabels: Record<string, string> = {
  bossDamage:    "Boss Damage",
  clickGold:     "Click Gold",
  essenceIncome: "Essence Income",
  passiveGold:   "Passive Gold",
  questTime:     "Quest Time",
};

const unlockLabels: Record<string, string> = {
  apotheosis:     "apotheosis",
  lifetimeBosses: "lifetime bosses defeated",
  lifetimeGold:   "lifetime gold earned",
  lifetimeQuests: "lifetime quests completed",
  prestige:       "prestige(s)",
  transcendence:  "transcendence(s)",
};

/**
 * Formats a companion unlock threshold for display.
 * @param type - The unlock condition type.
 * @param threshold - The threshold value.
 * @returns The formatted threshold string.
 */
const formatThreshold = (type: string, threshold: number): string => {
  if (type === "lifetimeGold") {
    if (threshold >= 1e18) {
      return `${(threshold / 1e18).toFixed(0)}Qt`;
    }
    if (threshold >= 1e15) {
      return `${(threshold / 1e15).toFixed(0)}Q`;
    }
    if (threshold >= 1e12) {
      return `${(threshold / 1e12).toFixed(0)}T`;
    }
    if (threshold >= 1e9) {
      return `${(threshold / 1e9).toFixed(0)}B`;
    }
    if (threshold >= 1e6) {
      return `${(threshold / 1e6).toFixed(0)}M`;
    }
    if (threshold >= 1e3) {
      return `${(threshold / 1e3).toFixed(0)}K`;
    }
  }
  return threshold.toString();
};

interface CompanionCardProperties {
  readonly companion:  Companion;
  readonly isUnlocked: boolean;
  readonly isActive:   boolean;
  readonly onSelect:   ()=> void;
}

/**
 * Renders a single companion card.
 * @param props - The companion card properties.
 * @param props.companion - The companion data.
 * @param props.isUnlocked - Whether this companion is unlocked.
 * @param props.isActive - Whether this companion is currently active.
 * @param props.onSelect - Callback when the companion is selected/deselected.
 * @returns The JSX element.
 */
const CompanionCard = ({
  companion,
  isUnlocked,
  isActive,
  onSelect,
}: CompanionCardProperties): JSX.Element => {
  const bonusSign = companion.bonus.type === "questTime"
    ? "-"
    : "+";
  const bonusPercent = Math.round(companion.bonus.value * 100);
  const bonusLabel = bonusLabels[companion.bonus.type] ?? companion.bonus.type;

  return (
    <div
      className={`companion-card ${
        isUnlocked
          ? "companion-unlocked"
          : "companion-locked"
      } ${isActive
        ? "companion-active"
        : ""}`}
    >
      <div className="companion-header">
        <div className="companion-name-block">
          <span className="companion-name">{companion.name}</span>
          <span className="companion-title">{companion.title}</span>
        </div>
        {isActive
          ? <span className="companion-active-badge">{"Active"}</span>
          : null}
      </div>

      <p className="companion-description">{companion.description}</p>

      <div className="companion-bonus">
        <span className="companion-bonus-label">{bonusLabel}</span>
        <span className="companion-bonus-value">
          {bonusSign}
          {bonusPercent}
          {"%"}
        </span>
      </div>

      {isUnlocked
        ? <button
          className={`companion-select-btn ${
            isActive
              ? "companion-select-active"
              : ""
          }`}
          onClick={onSelect}
          type="button"
        >
          {isActive
            ? "Deactivate"
            : "Activate"}
        </button>
        : <div className="companion-unlock-requirement">
          {"🔒 Unlock: "}
          {formatThreshold(
            companion.unlock.type,
            companion.unlock.threshold,
          )}{" "}
          {unlockLabels[companion.unlock.type] ?? companion.unlock.type}
        </div>
      }
    </div>
  );
};

/**
 * Renders the companion panel with all companions.
 * @returns The JSX element.
 */
const CompanionPanel = (): JSX.Element => {
  const { state, setActiveCompanion } = useGame();

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

  const unlockedIds = state.companions?.unlockedCompanionIds ?? [];
  const activeId = state.companions?.activeCompanionId ?? null;

  function handleSelect(companionId: string): void {
    setActiveCompanion(activeId === companionId
      ? null
      : companionId);
  }

  const activeCompanion
    = activeId === null
      ? undefined
      : COMPANIONS.find((companion) => {
        return companion.id === activeId;
      });

  return (
    <div className="companion-panel">
      <h2>{"👥 Companions"}</h2>
      <p className="companion-intro">
        {"Companions provide powerful bonuses while active."
          + " You can only have one companion active at a time."}
        {activeId === null
          ? null
          : <>
            {" Currently active: "}
            <strong>{activeCompanion?.name ?? activeId}</strong>
            {"."}
          </>
        }
      </p>

      <div className="companion-grid">
        {COMPANIONS.map((companion) => {
          function handleCompanionSelect(): void {
            handleSelect(companion.id);
          }
          return (
            <CompanionCard
              companion={companion}
              isActive={activeId === companion.id}
              isUnlocked={unlockedIds.includes(companion.id)}
              key={companion.id}
              onSelect={handleCompanionSelect}
            />
          );
        })}
      </div>
    </div>
  );
};

export { CompanionPanel };
