/**
 * @file Story panel component displaying the main questline narrative.
 * @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 -- Complex component with many conditional render paths */
import { STORY_CHAPTERS } from "@elysium/types";
import { type JSX, useState } from "react";
import { useGame } from "../../context/gameContext.js";
import { cdnImage } from "../../utils/cdn.js";

/**
 * Substitutes the character name placeholder in story text.
 * @param text - The story text with placeholders.
 * @param characterName - The player's character name.
 * @returns The text with placeholders replaced.
 */
const substituteCharacterName = (
  text: string,
  characterName: string,
): string => {
  const fallback = characterName === ""
    ? "the guild leader"
    : characterName;
  return text.replaceAll("{characterName}", fallback);
};

/**
 * Renders the story panel with chapter navigation and content.
 * @returns The JSX element.
 */
const StoryPanel = (): JSX.Element => {
  const { state, completeChapter } = useGame();
  const [ activeChapterIndex, setActiveChapterIndex ] = useState(0);

  if (state === null) {
    return (
      <div className="story-panel">
        <p>{"Loading…"}</p>
      </div>
    );
  }

  const unlockedIds = state.story?.unlockedChapterIds ?? [];
  const completedChapters = state.story?.completedChapters ?? [];
  const { characterName } = state.player;

  const activeChapter = STORY_CHAPTERS[activeChapterIndex];
  const isUnlocked = unlockedIds.includes(activeChapter?.id ?? "");
  const completion
    = activeChapter === undefined
      ? null
      : completedChapters.find((completedChapter) => {
        return completedChapter.chapterId === activeChapter.id;
      }) ?? null;
  const isUnread = isUnlocked && completion === null;

  return (
    <div className="story-panel">
      <div className="story-chapter-tabs">
        {STORY_CHAPTERS.map((chapter, index) => {
          const unlocked = unlockedIds.includes(chapter.id);
          const completed = completedChapters.some((completedChapter) => {
            return completedChapter.chapterId === chapter.id;
          });
          const unread = unlocked && !completed;
          function handleChapterSelect(): void {
            setActiveChapterIndex(index);
          }
          return (
            <button
              aria-label={
                unlocked
                  ? chapter.title
                  : `Chapter ${String(index + 1)} (locked)`
              }
              className={[
                "story-tab-btn",
                activeChapterIndex === index
                  ? "active"
                  : "",
                unlocked
                  ? ""
                  : "locked",
              ].join(" ")}
              key={chapter.id}
              onClick={handleChapterSelect}
              type="button"
            >
              {index + 1}
              {unread
                ? <span className="story-unread-dot" />
                : null}
            </button>
          );
        })}
      </div>

      {activeChapter === undefined
        ? null
        : <div className="story-chapter-view">
          {isUnlocked
            ? <>
              <img
                alt={activeChapter.title}
                className="story-chapter-banner"
                src={cdnImage("story-chapters", activeChapter.id)}
              />
              <h2 className="story-chapter-title">
                {"Chapter "}
                {activeChapterIndex + 1}
                {": "}
                {activeChapter.title}
              </h2>
              <div className="story-chapter-content">
                {substituteCharacterName(activeChapter.content, characterName).
                  split("\n\n").
                  map((paragraph, paraIndex) => {
                    // eslint-disable-next-line react/no-array-index-key -- Static content paragraphs have no stable id
                    return <p key={paraIndex}>{paragraph}</p>;
                  })}
              </div>

              {completion === null && isUnread
                ? <div className="story-choices">
                  <p className="story-choices-prompt">{"What do you do?"}</p>
                  {activeChapter.choices.map((storyChoice) => {
                    const chapterForClosure = activeChapter;
                    function handleChoice(): void {
                      completeChapter(chapterForClosure.id, storyChoice.id);
                    }
                    return (
                      <button
                        className="story-choice-btn"
                        key={storyChoice.id}
                        onClick={handleChoice}
                        type="button"
                      >
                        {storyChoice.label}
                      </button>
                    );
                  })}
                </div>
                : null}
              {completion === null
                ? null
                : <div className="story-choice-result">
                  <p className="story-choice-label">
                    <strong>{"Your choice:"}</strong>{" "}
                    {
                      activeChapter.choices.find((storyChoice) => {
                        return storyChoice.id === completion.choiceId;
                      })?.label
                    }
                  </p>
                  <p className="story-choice-outcome">
                    {substituteCharacterName(
                      activeChapter.choices.find((storyChoice) => {
                        return storyChoice.id === completion.choiceId;
                      })?.outcome ?? "",
                      characterName,
                    )}
                  </p>
                </div>
              }
            </>
            : <div className="story-locked">
              <p className="story-locked-title">
                {"Chapter "}
                {activeChapterIndex + 1}
              </p>
              <p className="story-locked-hint">
                {"🔒 This chapter has not yet been unlocked."}
              </p>
            </div>
          }
        </div>
      }
    </div>
  );
};

export { StoryPanel };
