/**
 * @file Vampire achievements panel component displaying all vampire expansion achievements.
 * @copyright nhcarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */
/* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to this panel */
/* eslint-disable max-lines-per-function -- Achievement panel renders many achievement states */
import { type JSX, useState } from "react";
import { useGame } from "../../context/gameContext.js";
import { LockToggle } from "../ui/lockToggle.js";
import type { VampireAchievement, VampireState } from "@elysium/types";

/**
 * Returns the plural form of a word based on a count.
 * @param count - The count to check.
 * @param word - The base word to pluralise.
 * @returns The pluralised word string.
 */
const pluralise = (count: number, word: string): string => {
  return count > 1
    ? `${word}s`
    : word;
};

/**
 * Generates a human-readable condition description for a vampire achievement.
 * @param achievement - The vampire achievement to describe.
 * @param formatNumber - The number formatting utility function.
 * @returns A string describing the achievement condition.
 */
const conditionDescription = (
  achievement: VampireAchievement,
  formatNumber: (n: number)=> string,
): string => {
  const { condition } = achievement;
  switch (condition.type) {
    case "totalBloodEarned":
      return `Earn ${formatNumber(condition.amount)} total blood`;
    case "vampireBossesDefeated":
      return `Defeat ${String(condition.amount)} vampire ${pluralise(condition.amount, "boss")}`;
    case "vampireQuestsCompleted":
      return `Complete ${String(condition.amount)} vampire ${pluralise(condition.amount, "quest")}`;
    case "thrallTotal":
      return `Recruit ${formatNumber(condition.amount)} total ${pluralise(condition.amount, "thrall")}`;
    case "siringCount":
      return `Sire ${String(condition.amount)} ${pluralise(condition.amount, "time")}`;
    case "vampireEquipmentOwned":
      return `Own ${String(condition.amount)} vampire equipment ${pluralise(condition.amount, "item")}`;
    default:
      return "Unknown condition";
  }
};

/**
 * Returns the player's current progress value toward a vampire achievement's unlock condition.
 * @param achievement - The achievement to evaluate progress for.
 * @param vampire - The current vampire state.
 * @returns The current numeric progress toward the achievement condition.
 */
const getCurrentProgress = (
  achievement: VampireAchievement,
  vampire: VampireState,
): number => {
  const { condition } = achievement;
  switch (condition.type) {
    case "totalBloodEarned":
      return vampire.lifetimeBloodEarned;
    case "vampireBossesDefeated":
      return vampire.lifetimeBossesDefeated;
    case "vampireQuestsCompleted":
      return vampire.lifetimeQuestsCompleted;
    case "thrallTotal":
      return vampire.thralls.reduce((sum, thrall) => {
        return sum + thrall.count;
      }, 0);
    case "siringCount":
      return vampire.siring.count;
    case "vampireEquipmentOwned":
      return vampire.equipment.filter((item) => {
        return item.owned;
      }).length;
    default:
      return 0;
  }
};

interface VampireAchievementCardProperties {
  readonly achievement:   VampireAchievement;
  readonly formatNumber:  (n: number)=> string;
  readonly progressValue: number;
}

/**
 * Renders a single vampire achievement card.
 * @param props - The achievement card properties.
 * @param props.achievement - The achievement to display.
 * @param props.formatNumber - The number formatting utility function.
 * @param props.progressValue - The player's current progress toward the unlock condition.
 * @returns The JSX element.
 */
const VampireAchievementCard = ({
  achievement,
  formatNumber,
  progressValue,
}: VampireAchievementCardProperties): JSX.Element => {
  const isUnlocked = achievement.unlockedAt !== null;
  const cappedProgress = Math.min(progressValue, achievement.condition.amount);

  return (
    <div className={`achievement-card ${isUnlocked
      ? "unlocked"
      : "locked"}`}>
      <div className="achievement-icon">
        <span className="achievement-emoji">{achievement.icon}</span>
      </div>
      <div className="achievement-info">
        <h3>{achievement.name}</h3>
        <p>{achievement.description}</p>
        <p className="achievement-condition">
          {conditionDescription(achievement, formatNumber)}
        </p>
        {!isUnlocked
          && <div className="achievement-progress">
            <progress
              max={achievement.condition.amount}
              value={cappedProgress}
            />
            <span className="achievement-progress-label">
              {formatNumber(progressValue)}
              {" / "}
              {formatNumber(achievement.condition.amount)}
            </span>
          </div>
        }
        {achievement.reward !== undefined
          && <div className="achievement-reward">
            {achievement.reward.ichor !== undefined
              && <p>
                {"💧 +"}
                {achievement.reward.ichor}
                {" Ichor"}
              </p>
            }
            {achievement.reward.soulShards !== undefined
              && <p>
                {"💠 +"}
                {achievement.reward.soulShards}
                {" Soul Shards"}
              </p>
            }
          </div>
        }
      </div>
      <div className="achievement-status">
        {isUnlocked
          ? <>
            <span className="achievement-unlocked-badge">{"✓ Unlocked"}</span>
            {achievement.unlockedAt !== null
              && <span className="achievement-unlocked-at">
                {new Date(achievement.unlockedAt).toLocaleDateString("en-GB", {
                  day:   "numeric",
                  month: "short",
                  year:  "numeric",
                })}
              </span>
            }
          </>
          : <span className="achievement-locked-badge">{"🔒"}</span>
        }
      </div>
    </div>
  );
};

/**
 * Renders the vampire achievements panel with all vampire expansion achievements.
 * @returns The JSX element.
 */
const VampireAchievementsPanel = (): JSX.Element => {
  const { state, formatNumber } = useGame();
  const [ showLocked, setShowLocked ] = useState(true);

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

  const { vampire } = state;

  if (vampire === undefined) {
    return (
      <section className="panel">
        <p>{"The Vampire expansion is not yet unlocked."}</p>
      </section>
    );
  }

  const achievementList = vampire.achievements;
  const unlocked = achievementList.filter((achievement) => {
    return achievement.unlockedAt !== null;
  });
  const locked = achievementList.filter((achievement) => {
    return achievement.unlockedAt === null;
  });
  const visible = showLocked
    ? achievementList
    : unlocked;

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

  return (
    <section className="panel achievement-panel vampire-achievements-panel">
      <div className="panel-header">
        <h2>{"🩸 Vampire Achievements"}</h2>
        <LockToggle
          lockedCount={locked.length}
          onToggle={handleToggle}
          showLocked={showLocked}
        />
      </div>
      <p className="achievement-progress">
        {unlocked.length}
        {" / "}
        {achievementList.length}
        {" unlocked"}
      </p>
      <div className="achievement-list">
        {visible.map((achievement) => {
          return (
            <VampireAchievementCard
              achievement={achievement}
              formatNumber={formatNumber}
              key={achievement.id}
              progressValue={getCurrentProgress(achievement, vampire)}
            />
          );
        })}
      </div>
    </section>
  );
};

export { VampireAchievementsPanel };
