import { useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Link } from "react-router-dom";
import { useAI } from "../context/AIContext";
import { api } from "../lib/api";
import { aiApi } from "../lib/ai";
import {
  computeDrillChartStats,
  formatChartStatsForCoach,
  formatChartStatsForUser,
  pricePointsToOhlc,
} from "../lib/skillDrillChart";
import { getDrillOverride } from "../lib/skillDrillBank";
import {
  buildDrillPack,
  formatDrillForAssess,
  isStep1Correct,
  MASTERY_SCORE_THRESHOLD,
  parseSkillAssessResponse,
  type DrillAnswers,
  type SkillAssessResult,
} from "../lib/skillDrill";
import { recordDrillAttemptApi } from "../lib/skillProgress";
import {
  cleanPrincipleTitle,
  parsePrincipleCard,
  type DrillMistakeBook,
  type SkillProgressMap,
  type SkillTreeNode,
} from "../lib/skillTree";
import { AppIcon } from "./PixelIcons";
import PixelMascot from "./PixelMascot";
import SkillDrillChart from "./SkillDrillChart";
import { Loading, Tag } from "./ui";

type DrillStep = 1 | 2 | 3 | "result";

const EMPTY_ANSWERS: DrillAnswers = {
  step1Choice: "",
  step2Action: "",
  step2Reason: "",
  step3Judgment: "",
  step3Reasoning: "",
};

export default function SkillDrillPanel({
  node,
  progressEntry,
  onProgressChange,
  onMistakeBookChange,
  onAttemptRecorded,
}: {
  node: SkillTreeNode;
  progressEntry?: SkillProgressMap[string];
  onProgressChange: (map: SkillProgressMap) => void;
  onMistakeBookChange?: (book: DrillMistakeBook) => void;
  onAttemptRecorded?: () => void;
}) {
  const ai = useAI();
  const card = useMemo(() => parsePrincipleCard(node), [node]);
  const bankQ = useQuery({
    queryKey: ["skill-drills"],
    queryFn: () => api.skillDrills(),
    staleTime: 3600_000,
    retry: 1,
  });
  const pack = useMemo(() => {
    const override = getDrillOverride(bankQ.data, node.principle.id);
    const distractorTitles = (override?.distractorPrinciples || []).map((id) =>
      cleanPrincipleTitle(id),
    );
    return buildDrillPack(node, card, { override, distractorTitles });
  }, [node, card, bankQ.data]);

  const [step, setStep] = useState<DrillStep>(1);
  const [answers, setAnswers] = useState<DrillAnswers>(EMPTY_ANSWERS);
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState<SkillAssessResult | null>(null);
  const [error, setError] = useState("");
  const chartCtx = pack.step3.chart;

  const priceQ = useQuery({
    queryKey: ["skill-drill-price", chartCtx.symbol, chartCtx.range],
    queryFn: () => api.price(chartCtx.symbol, chartCtx.range, "1d"),
    enabled: step === 3,
    staleTime: 600_000,
  });

  const ohlc = useMemo(() => pricePointsToOhlc(priceQ.data?.points ?? []), [priceQ.data?.points]);
  const chartStats = useMemo(() => computeDrillChartStats(ohlc), [ohlc]);
  const chartUserNotes = chartStats
    ? formatChartStatsForUser(chartStats, chartCtx.symbolLabel)
    : "";
  const chartCoachNotes = formatChartStatsForCoach(chartCtx, chartStats, !!ohlc.length);

  const resetDrill = () => {
    setStep(1);
    setAnswers(EMPTY_ANSWERS);
    setResult(null);
    setError("");
  };

  const canNext1 = !!answers.step1Choice;
  const canNext2 = !!answers.step2Action && answers.step2Reason.trim().length >= 8;
  const canSubmit =
    answers.step3Judgment.trim().length >= 6 && answers.step3Reasoning.trim().length >= 12;

  const submitAssess = async () => {
    if (!canSubmit || busy) return;
    if (!ai.status?.ready) {
      setError("尚未設定 AI API Key，請先到設定頁填入。");
      return;
    }
    setBusy(true);
    setError("");
    try {
      const ctx = await aiApi.context(
        "skills",
        {
          cardTitle: card.cleanTitle,
          label: card.label,
          tab: "skills",
          principleId: node.principle.id,
          view: "skills",
        },
        { pathname: "/skills" },
      );
      const drillText = formatDrillForAssess(pack, answers, chartCoachNotes);
      const res = await aiApi.skillAssess({
        provider: ai.provider,
        model: ai.model || undefined,
        principleId: node.principle.id,
        drillAnswers: drillText,
        context: ctx,
      });
      const parsed: SkillAssessResult | null = res.assessment
        ? (res.assessment as unknown as SkillAssessResult)
        : parseSkillAssessResponse(res.text);
      if (!parsed) {
        setError("教練評分解析失敗，請重試。");
        return;
      }
      setResult(parsed);
      setStep("result");

      const step1Wrong = !isStep1Correct(pack, answers);
      const s1 = pack.step1.options.find((o) => o.id === answers.step1Choice);
      const s2 = pack.step2.actions.find((a) => a.id === answers.step2Action);
      const summary = [
        `第1關：${s1?.label || "—"}${step1Wrong ? "（錯）" : ""}`,
        `第2關：${s2?.label || "—"}`,
        `第3關：${answers.step3Judgment.trim() || "—"}`,
      ].join(" · ");

      const saved = await recordDrillAttemptApi({
        principleId: node.principle.id,
        principleTitle: node.principle.title,
        result: parsed,
        step1Wrong,
        answersSummary: summary,
        answers,
      });
      onProgressChange(saved.progressMap);
      onMistakeBookChange?.(saved.openMistakes);
      onAttemptRecorded?.();
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setBusy(false);
    }
  };

  if (step === "result" && result) {
    const mastered = result.score >= MASTERY_SCORE_THRESHOLD && result.fatalErrors.length === 0;
    return (
      <section className="skill-drill" aria-label="試煉結果">
        <div className="skill-drill-result-head">
          <PixelMascot size={44} variant="chat" />
          <div>
            <div className="skill-coach-chat-name">教練評分</div>
            <div className={"skill-drill-score" + (mastered ? " mastered" : "")}>
              <span className="skill-drill-score-num">{result.score}</span>
              <span className="skill-drill-score-unit">/ 100</span>
            </div>
          </div>
          {mastered ? (
            <Tag tone="gold">精通解鎖</Tag>
          ) : (
            <Tag>{`距精通還差 ${Math.max(0, MASTERY_SCORE_THRESHOLD - result.score)} 分`}</Tag>
          )}
        </div>

        <p className="skill-drill-feedback">{result.feedback}</p>

        {result.fatalErrors.length > 0 && (
          <div className="skill-drill-fatal">
            <strong>致命錯誤</strong>
            <ul>
              {result.fatalErrors.map((f, i) => (
                <li key={i}>{f}</li>
              ))}
            </ul>
          </div>
        )}

        <div className="skill-drill-breakdown">
          {(
            [
              ["mechanism", "機制理解", 25],
              ["trigger", "觸發辨識", 25],
              ["scenario", "情境判斷", 30],
              ["discipline", "紀律風險", 20],
            ] as const
          ).map(([key, label, max]) => {
            const v = result.breakdown[key];
            const pct = max ? Math.round((v / max) * 100) : 0;
            return (
              <div className="skill-drill-bar-row" key={key}>
                <span className="skill-drill-bar-label">
                  {label} {v}/{max}
                </span>
                <div className="bar">
                  <span style={{ width: `${pct}%` }} />
                </div>
              </div>
            );
          })}
        </div>

        {result.weakPoints.length > 0 && (
          <div className="skill-drill-weak">
            <div className="skill-drill-weak-k">待加強</div>
            <ul>
              {result.weakPoints.map((w, i) => (
                <li key={i}>{w}</li>
              ))}
            </ul>
          </div>
        )}

        {result.nextDrill ? (
          <p className="small muted">下一步：{result.nextDrill}</p>
        ) : null}

        <div className="skill-drill-actions">
          <button type="button" className="btn-primary sm" onClick={resetDrill}>
            {mastered ? "再練一次" : "重考試煉"}
          </button>
        </div>
      </section>
    );
  }

  return (
    <section className="skill-drill" aria-label="修煉試煉">
      <div className="skill-drill-intro">
        <AppIcon name="sword" size={22} framed variant="hero" />
        <div>
          <strong>修煉試煉</strong>
          <p className="small muted">
            三關試煉（含第 3 關 K 線圖判）由教練評分 1–100，{MASTERY_SCORE_THRESHOLD} 分以上才算精通。
            {progressEntry?.bestScore != null ? ` 目前最高 ${progressEntry.bestScore} 分。` : ""}
          </p>
        </div>
      </div>

      <div className="skill-drill-steps" aria-label="試煉進度">
        {([1, 2, 3] as const).map((n) => (
          <span
            key={n}
            className={
              "skill-drill-step-pill" +
              (step === n ? " active" : "") +
              (typeof step === "number" && step > n ? " done" : "")
            }
          >
            第{n}關
          </span>
        ))}
      </div>

      {!ai.status?.ready && (
        <div className="skill-coach-setup">
          <p>評分需要 AI。請先到設定頁填入 API Key。</p>
          <Link to="/settings" className="guide-setup-link">
            前往 AI 設定 →
          </Link>
        </div>
      )}

      {error ? <p className="skill-drill-error">{error}</p> : null}

      {step === 1 && (
        <div className="skill-drill-stage">
          <h3 className="skill-drill-prompt">{pack.step1.prompt}</h3>
          <div className="skill-drill-options">
            {pack.step1.options.map((opt) => (
              <label key={opt.id} className="skill-drill-option">
                <input
                  type="radio"
                  name="step1"
                  checked={answers.step1Choice === opt.id}
                  onChange={() => setAnswers((a) => ({ ...a, step1Choice: opt.id }))}
                />
                <span>{opt.label}</span>
              </label>
            ))}
          </div>
          <button
            type="button"
            className="btn-primary sm"
            disabled={!canNext1}
            onClick={() => setStep(2)}
          >
            下一關
          </button>
        </div>
      )}

      {step === 2 && (
        <div className="skill-drill-stage">
          <div className="skill-drill-scenario card pad-sm">
            <div className="skill-instance-ep">{pack.step2.ep}</div>
            <p>{pack.step2.scenario}</p>
          </div>
          <h3 className="skill-drill-prompt">{pack.step2.prompt}</h3>
          <div className="skill-drill-options">
            {pack.step2.actions.map((act) => (
              <label key={act.id} className="skill-drill-option">
                <input
                  type="radio"
                  name="step2"
                  checked={answers.step2Action === act.id}
                  onChange={() => setAnswers((a) => ({ ...a, step2Action: act.id }))}
                />
                <span>{act.label}</span>
              </label>
            ))}
          </div>
          <label className="skill-drill-field">
            <span>一句理由（至少 8 字）</span>
            <textarea
              rows={2}
              value={answers.step2Reason}
              onChange={(e) => setAnswers((a) => ({ ...a, step2Reason: e.target.value }))}
              placeholder="為什麼選這個動作？如何符合這條心法？"
            />
          </label>
          <div className="skill-drill-actions">
            <button type="button" className="btn-ghost sm" onClick={() => setStep(1)}>
              上一關
            </button>
            <button
              type="button"
              className="btn-primary sm"
              disabled={!canNext2}
              onClick={() => setStep(3)}
            >
              下一關
            </button>
          </div>
        </div>
      )}

      {step === 3 && (
        <div className="skill-drill-stage">
          <div className="skill-drill-chart-panel card pad-sm">
            {priceQ.isLoading ? (
              <Loading label="載入 K 線走勢…" />
            ) : priceQ.error ? (
              <p className="small muted">K 線暫時無法載入，仍可依文字快照作答。</p>
            ) : ohlc.length ? (
              <>
                <SkillDrillChart
                  data={ohlc}
                  symbol={chartCtx.symbolLabel}
                  focusDate={chartCtx.focusDate}
                  markerLabel={chartCtx.markerLabel}
                />
                {chartUserNotes ? (
                  <pre className="skill-drill-chart-stats">{chartUserNotes}</pre>
                ) : null}
              </>
            ) : (
              <p className="small muted">此標的暫無足夠 K 線，請依下方文字快照判斷。</p>
            )}
            {chartCtx.eventHint ? (
              <p className="small muted skill-drill-event-hint">歷史情境提示：{chartCtx.eventHint}</p>
            ) : null}
          </div>
          <div className="skill-drill-snapshot card pad-sm">
            <div className="skill-drill-snapshot-k">心法快照</div>
            <pre>{pack.step3.snapshot}</pre>
          </div>
          <h3 className="skill-drill-prompt">{pack.step3.prompt}</h3>
          <p className="small muted">{pack.step3.hint}</p>
          <label className="skill-drill-field">
            <span>你的判斷</span>
            <input
              type="text"
              value={answers.step3Judgment}
              onChange={(e) => setAnswers((a) => ({ ...a, step3Judgment: e.target.value }))}
              placeholder="例如：觸發跌就買，但先小倉試單"
            />
          </label>
          <label className="skill-drill-field">
            <span>理由與紀律（至少 12 字）</span>
            <textarea
              rows={3}
              value={answers.step3Reasoning}
              onChange={(e) => setAnswers((a) => ({ ...a, step3Reasoning: e.target.value }))}
              placeholder="說明總經/觸發訊號、倉位與停損觀望…"
            />
          </label>
          <div className="skill-drill-actions">
            <button type="button" className="btn-ghost sm" onClick={() => setStep(2)}>
              上一關
            </button>
            <button
              type="button"
              className="btn-primary sm"
              disabled={!canSubmit || busy}
              onClick={() => void submitAssess()}
            >
              {busy ? "教練評分中…" : "送出 · 請教練評分"}
            </button>
          </div>
        </div>
      )}
    </section>
  );
}