/**
 * @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 */
/* eslint-disable complexity -- Companion card has many conditional render paths */
import { COMPANIONS, type Companion } from "@elysium/types";
import { useGame } from "../../context/gameContext.js";
import { cdnImage } from "../../utils/cdn.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)",
};

interface CompanionCardProperties {
  readonly companion:       Companion;
  readonly isUnlocked:      boolean;
  readonly isActive:        boolean;
  readonly onSelect:        ()=> void;
  readonly formatNumber:    (n: number)=> string;
  readonly currentProgress: number;
}

/**
 * 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.
 * @param props.formatNumber - The number formatting utility function.
 * @param props.currentProgress - The player's current progress toward the unlock threshold.
 * @returns The JSX element.
 */
const CompanionCard = ({
  companion,
  isUnlocked,
  isActive,
  onSelect,
  formatNumber,
  currentProgress,
}: 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">
        <img
          alt={companion.name}
          className="card-thumbnail"
          src={cdnImage("companions", companion.id)}
        />
        <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">
          <p>
            {"🔒 Unlock: "}
            {companion.unlock.type === "lifetimeGold"
              ? formatNumber(companion.unlock.threshold)
              : String(companion.unlock.threshold)}{" "}
            {unlockLabels[companion.unlock.type] ?? companion.unlock.type}
          </p>
          <div className="companion-progress">
            <progress
              max={companion.unlock.threshold}
              value={Math.min(currentProgress, companion.unlock.threshold)}
            />
            <span className="companion-progress-label">
              {companion.unlock.type === "lifetimeGold"
                ? formatNumber(currentProgress)
                : String(currentProgress)}
              {" / "}
              {companion.unlock.type === "lifetimeGold"
                ? formatNumber(companion.unlock.threshold)
                : String(companion.unlock.threshold)}
            </span>
          </div>
        </div>
      }
    </div>
  );
};

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

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

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

  const progressByUnlockType: Record<string, number> = {
    apotheosis:     state.apotheosis?.count ?? 0,
    lifetimeBosses: state.player.lifetimeBossesDefeated,
    // eslint-disable-next-line stylistic/max-len -- Long expression; splitting would reduce readability
    lifetimeGold:   state.player.lifetimeGoldEarned + state.player.totalGoldEarned,
    lifetimeQuests: state.player.lifetimeQuestsCompleted,
    prestige:       state.prestige.count,
    transcendence:  state.transcendence?.count ?? 0,
  };

  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}
              currentProgress={
                progressByUnlockType[companion.unlock.type] ?? 0
              }
              formatNumber={formatNumber}
              isActive={activeId === companion.id}
              isUnlocked={unlockedIds.includes(companion.id)}
              key={companion.id}
              onSelect={handleCompanionSelect}
            />
          );
        })}
      </div>
    </div>
  );
};

export { CompanionPanel };
