"use client";

import { useEffect, useRef, useState } from "react";
import {
  isSequenceCorrect,
  isTerminalAnswer,
  shuffleItems,
  shuffleSequenceTokens
} from "../lib/game";

const AUTO_ADVANCE_MS = 3_500;
// Beim dritten Fehler bleibt mehr Zeit: die Lösung soll noch gelesen werden,
// bevor das Kapitel neu startet.
const STRIKE_ADVANCE_MS = 5_500;

export default function Puzzle({
  mission,
  solution,
  strikeLimit,
  completed,
  hintUsed,
  onUseHint,
  onWrong,
  onStrikeReset,
  onSuccess,
  onNext,
  nextLabel,
  positionLabel
}) {
  const [terminalValue, setTerminalValue] = useState("");
  const [sequence, setSequence] = useState([]);
  const [feedback, setFeedback] = useState(null);
  const [tokenPool, setTokenPool] = useState([]);
  const [choicePool, setChoicePool] = useState([]);
  const [reducedMotion, setReducedMotion] = useState(false);
  const advanceRef = useRef(onNext);
  const strikeResetRef = useRef(onStrikeReset);

  useEffect(() => {
    advanceRef.current = onNext;
    strikeResetRef.current = onStrikeReset;
  }, [onNext, onStrikeReset]);

  useEffect(() => {
    const query = window.matchMedia("(prefers-reduced-motion: reduce)");
    setReducedMotion(query.matches);
    const listener = (event) => setReducedMotion(event.matches);
    query.addEventListener("change", listener);
    return () => query.removeEventListener("change", listener);
  }, []);

  useEffect(() => {
    setTerminalValue("");
    setSequence([]);
    setFeedback(null);
    setChoicePool(
      mission.type === "choice" ? shuffleItems(mission.choices) : []
    );
    setTokenPool(
      mission.type === "sequence"
        ? shuffleSequenceTokens(mission.tokens, mission.answer).map(
            (value, index) => ({
              key: `${mission.id}-${index}`,
              value
            })
          )
        : []
    );
  }, [mission]);

  useEffect(() => {
    if (feedback?.type !== "wrong") return undefined;
    const { limitReached } = feedback;
    const timer = window.setTimeout(
      () => (limitReached ? strikeResetRef.current() : advanceRef.current()),
      limitReached ? STRIKE_ADVANCE_MS : AUTO_ADVANCE_MS
    );
    return () => window.clearTimeout(timer);
  }, [feedback]);

  function wrong(message) {
    const outcome = onWrong();
    setFeedback({
      type: "wrong",
      message,
      penalty: outcome?.penalty ?? { xp: 0, integrity: 0 },
      strikes: outcome?.strikes ?? 0,
      limitReached: Boolean(outcome?.limitReached)
    });
  }

  function success() {
    setFeedback({ type: "success", message: mission.decision });
    onSuccess();
  }

  function answerChoice(choice) {
    if (completed || feedback) return;
    if (choice.correct) success();
    else wrong(choice.feedback);
  }

  function submitTerminal(event) {
    event.preventDefault();
    if (completed || feedback) return;
    if (!terminalValue.trim()) return;
    if (isTerminalAnswer(terminalValue, mission.acceptedAnswers)) success();
    else
      wrong(
        "Der Simulator akzeptiert diesen Befehl hier nicht. Lies Signal und Auftrag noch einmal genau."
      );
  }

  function addToken(token) {
    if (completed || feedback) return;
    setSequence((current) => [...current, token]);
    setFeedback(null);
  }

  function removeToken(index) {
    setSequence((current) => current.filter((_, itemIndex) => itemIndex !== index));
    setFeedback(null);
  }

  function submitSequence() {
    if (completed || feedback) return;
    const values = sequence.map((token) => token.value);
    if (isSequenceCorrect(values, mission.answer)) success();
    else
      wrong(
        "Die Bausteine sind noch nicht in der ausführbaren Reihenfolge. Du kannst sie einzeln zurücknehmen."
      );
  }

  const selectedKeys = new Set(sequence.map((token) => token.key));
  // Nach jeder Antwort gesperrt, nicht erst nach einer richtigen: bei einer
  // falschen schaltet der Auto-Advance ohnehin weiter.
  const solved = completed || Boolean(feedback);

  return (
    <section
      className="puzzle-panel"
      aria-labelledby="puzzle-title"
      data-question-id={mission.id}
    >
      <div className="mission-meta">
        <span>{mission.exam}</span>
        <span>Objective {mission.objective}</span>
        <span>{positionLabel}</span>
        <span>{mission.xp} XP</span>
      </div>

      <div className="mission-title-row">
        <span className="huge-number">{mission.number}</span>
        <div>
          <p className="eyebrow">{mission.topic}</p>
          <h1 id="puzzle-title">{mission.title}</h1>
          <p className="mission-subtitle">{mission.subtitle}</p>
        </div>
      </div>

      <p className="briefing">{mission.briefing}</p>

      {mission.output.length > 0 && (
        <div className="terminal-output" aria-label="Terminalausgabe">
          <div className="terminal-bar">
            <span />
            <span />
            <span />
            <strong>andre@rescue:~</strong>
          </div>
          <pre>
            {mission.output.map((line, index) => (
              <span key={`${mission.id}-out-${index}`}>
                {line}
                {"\n"}
              </span>
            ))}
          </pre>
        </div>
      )}

      <div className="challenge">
        <p className="challenge-label">DEIN AUFTRAG</p>
        <h2>{mission.prompt}</h2>

        {mission.type === "choice" && (
          <div className="choice-list">
            {choicePool.map((choice) => (
              <button
                type="button"
                key={choice.label}
                onClick={() => answerChoice(choice)}
                disabled={solved}
              >
                <span className="prompt-glyph">$</span>
                <code>{choice.label}</code>
              </button>
            ))}
          </div>
        )}

        {mission.type === "terminal" && (
          <form className="terminal-form" onSubmit={submitTerminal}>
            <label htmlFor={`terminal-${mission.id}`}>Simuliertes Terminal</label>
            <div className="terminal-input-row">
              <span aria-hidden="true">$</span>
              <input
                id={`terminal-${mission.id}`}
                value={terminalValue}
                onChange={(event) => {
                  setTerminalValue(event.target.value.slice(0, 120));
                  setFeedback(null);
                }}
                placeholder={mission.placeholder}
                autoComplete="off"
                spellCheck="false"
                disabled={solved}
              />
              <button type="submit" disabled={solved || !terminalValue.trim()}>
                Ausführen
              </button>
            </div>
            <small>Simulation – es wird kein echter Befehl ausgeführt.</small>
          </form>
        )}

        {mission.type === "sequence" && (
          <div className="sequence-builder">
            <div
              className="sequence-target"
              aria-label="Zusammengesetzter Befehl"
            >
              {sequence.length === 0 && (
                <span className="sequence-placeholder">
                  Bausteine hier zusammensetzen …
                </span>
              )}
              {sequence.map((token, index) => (
                <button
                  type="button"
                  key={`${token.key}-selected`}
                  onClick={() => removeToken(index)}
                  title="Baustein zurücknehmen"
                >
                  {token.value}
                </button>
              ))}
            </div>
            <div className="token-pool">
              {tokenPool.map((token) => (
                <button
                  type="button"
                  key={token.key}
                  disabled={selectedKeys.has(token.key) || solved}
                  onClick={() => addToken(token)}
                >
                  {token.value}
                </button>
              ))}
            </div>
            <button
              className="verify-button"
              type="button"
              disabled={sequence.length === 0 || solved}
              onClick={submitSequence}
            >
              Reihenfolge prüfen
            </button>
          </div>
        )}

        <div className="puzzle-actions">
          <button
            type="button"
            className="hint-button"
            onClick={onUseHint}
            disabled={hintUsed || solved}
          >
            {hintUsed ? "Hinweis geöffnet" : "Hinweis (−15 XP)"}
          </button>
          {hintUsed && <p className="hint-copy">{mission.hint}</p>}
        </div>

        <div className="feedback" aria-live="polite">
          {feedback && (
            <div
              className={`feedback-box ${feedback.type}`}
              data-testid={
                feedback.type === "wrong" ? "wrong-feedback" : undefined
              }
            >
              <strong>
                {feedback.type === "success"
                  ? "FRAGE GELÖST"
                  : "FEHLER IM SYSTEM"}
              </strong>
              <p>{feedback.message}</p>

              {feedback.type === "wrong" && (
                <>
                  {feedback.penalty.xp > 0 && (
                    <p className="penalty-line">
                      −{feedback.penalty.xp} XP · −{feedback.penalty.integrity} %
                      INTEGRITÄT
                    </p>
                  )}
                  <p className="solution-line">
                    Richtig wäre gewesen: <code>{solution}</code>
                  </p>
                  <p className="strike-line">
                    Fehler {feedback.strikes} von {strikeLimit} in diesem Kapitel
                    {feedback.limitReached
                      ? " — Kapitel wird neu gestartet."
                      : ""}
                  </p>
                  {reducedMotion ? (
                    // Ohne Balken braucht der automatische Wechsel eine
                    // Ankündigung, sonst springt die Frage unvermittelt weg.
                    <p className="advance-note">
                      {feedback.limitReached
                        ? "Das Kapitel startet gleich neu."
                        : "Es geht gleich automatisch weiter."}
                    </p>
                  ) : (
                    <span
                      className="auto-advance-bar"
                      style={{
                        animationDuration: feedback.limitReached
                          ? `${STRIKE_ADVANCE_MS}ms`
                          : `${AUTO_ADVANCE_MS}ms`
                      }}
                      aria-hidden="true"
                    />
                  )}
                </>
              )}

              <button
                type="button"
                onClick={feedback.limitReached ? onStrikeReset : onNext}
              >
                {feedback.type === "success"
                  ? nextLabel
                  : feedback.limitReached
                    ? "Kapitel neu starten →"
                    : "Weiter →"}
              </button>
            </div>
          )}
          {completed && !feedback && (
            <div className="feedback-box recap">
              <strong>FRAGE BEREITS GELÖST</strong>
              <p>{mission.decision}</p>
              <button type="button" onClick={onNext}>
                {nextLabel}
              </button>
            </div>
          )}
        </div>
      </div>

      <details className="learning-debrief" open={solved}>
        <summary>Signal → Werkzeug → Entscheidung</summary>
        <dl>
          <div>
            <dt>Signal</dt>
            <dd>{mission.signal}</dd>
          </div>
          <div>
            <dt>Werkzeug</dt>
            <dd>
              <code>{mission.tool}</code>
            </dd>
          </div>
          <div>
            <dt>Entscheidung</dt>
            <dd>{mission.decision}</dd>
          </div>
          <div>
            <dt>Risiko</dt>
            <dd>{mission.risk}</dd>
          </div>
        </dl>
      </details>
    </section>
  );
}
