import { useMemo } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { AppIcon } from "./PixelIcons";
import PixelMascot from "./PixelMascot";
import { Loading } from "./ui";
import { fetchDrillHistory, resolveMistakeApi, type DrillAttemptRecord } from "../lib/skillProgress";
import { MASTERY_SCORE_THRESHOLD } from "../lib/skillDrill";
import type { DrillMistakeBook } from "../lib/skillTree";

function formatWhen(iso: string) {
  try {
    const d = new Date(iso);
    return d.toLocaleString("zh-TW", {
      year: "numeric",
      month: "short",
      day: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso;
  }
}

function sortAttempts(rows: DrillAttemptRecord[]) {
  return [...rows].sort((a, b) => {
    if (a.openMistake !== b.openMistake) return a.openMistake ? -1 : 1;
    return new Date(b.attemptedAt).getTime() - new Date(a.attemptedAt).getTime();
  });
}

function readNextDrill(answers?: DrillAttemptRecord["answers"]) {
  if (!answers || typeof answers !== "object") return "";
  const v = (answers as Record<string, string>)._nextDrill;
  return typeof v === "string" ? v.trim() : "";
}

function readUserAnswers(answers?: DrillAttemptRecord["answers"]) {
  if (!answers || typeof answers !== "object") return null;
  const a = answers as Record<string, string>;
  const rows = [
    a.step2Reason ? { k: "第 2 關理由", v: a.step2Reason } : null,
    a.step3Judgment ? { k: "第 3 關判斷", v: a.step3Judgment } : null,
    a.step3Reasoning ? { k: "紀律說明", v: a.step3Reasoning } : null,
  ].filter(Boolean) as { k: string; v: string }[];
  return rows.length ? rows : null;
}

function AttemptLogItem({
  attempt,
  onResolveAttempt,
  onRetryDrill,
  pinned,
}: {
  attempt: DrillAttemptRecord;
  onResolveAttempt?: (attemptId: number) => void;
  onRetryDrill?: () => void;
  pinned?: boolean;
}) {
  const mastered = attempt.masteredPass || attempt.score >= MASTERY_SCORE_THRESHOLD;
  const wrong = attempt.isMistake || attempt.step1Wrong || attempt.fatalErrors.length > 0;
  const nextDrill = readNextDrill(attempt.answers);
  const userDetail = readUserAnswers(attempt.answers);

  return (
    <li
      className={
        "skill-drill-log-item" +
        (mastered ? " passed" : "") +
        (wrong ? " wrong" : "") +
        (attempt.openMistake ? " open" : "") +
        (pinned ? " pinned" : "")
      }
    >
      <div className="skill-drill-log-meta">
        <span className={"skill-drill-log-score" + (mastered ? " mastered" : "")}>{attempt.score} 分</span>
        <span className="skill-drill-log-when small muted">{formatWhen(attempt.attemptedAt)}</span>
        {attempt.openMistake ? <span className="skill-drill-log-badge open">待補</span> : null}
        {mastered ? <span className="skill-drill-log-badge">通關</span> : null}
      </div>

      {attempt.answersSummary ? (
        <div className="skill-drill-log-you">
          <span className="skill-drill-log-you-k">你的作答</span>
          <p>{attempt.answersSummary}</p>
          {userDetail ? (
            <dl className="skill-drill-log-you-detail">
              {userDetail.map((row) => (
                <div key={row.k}>
                  <dt>{row.k}</dt>
                  <dd>{row.v}</dd>
                </div>
              ))}
            </dl>
          ) : null}
        </div>
      ) : null}

      <div className="skill-drill-log-coach">
        <PixelMascot size={32} variant="chat" />
        <div className="skill-drill-log-coach-body">
          <div className="skill-drill-log-coach-name">貓頭鷹教練 · 當時回饋</div>
          <div className="guide-bubble-wrap">
            <div className="guide-bubble">
              {attempt.feedback?.trim() || "（此次試煉沒有留下文字回饋）"}
            </div>
          </div>
        </div>
      </div>

      {wrong ? (
        <div className="skill-drill-log-wrong">
          {attempt.step1Wrong ? <span className="skill-drill-history-tag">第 1 關答錯</span> : null}
          {attempt.fatalErrors.map((f, i) => (
            <span className="skill-drill-history-tag fatal" key={i}>
              {f}
            </span>
          ))}
          {attempt.weakPoints.length ? (
            <div className="skill-drill-history-weak small">待加強：{attempt.weakPoints.join("、")}</div>
          ) : null}
        </div>
      ) : null}

      {nextDrill ? (
        <p className="skill-drill-log-next small muted">
          <strong>教練建議下一步：</strong>
          {nextDrill}
        </p>
      ) : null}

      {attempt.openMistake ? (
        <div className="skill-drill-log-actions">
          {onRetryDrill ? (
            <button type="button" className="btn-primary sm" onClick={onRetryDrill}>
              重練這題
            </button>
          ) : null}
          {onResolveAttempt ? (
            <button
              type="button"
              className="btn-ghost sm"
              onClick={() => onResolveAttempt(attempt.id)}
            >
              標記已掌握
            </button>
          ) : null}
        </div>
      ) : null}
    </li>
  );
}

export default function SkillDrillHistory({
  principleId,
  refreshKey = 0,
  onMistakeBookChange,
  onRetryDrill,
  compact = false,
}: {
  principleId: string;
  refreshKey?: number;
  onMistakeBookChange?: (book: DrillMistakeBook) => void;
  onRetryDrill?: () => void;
  compact?: boolean;
}) {
  const queryClient = useQueryClient();
  const historyQ = useQuery({
    queryKey: ["skill-drill-history", principleId, refreshKey],
    queryFn: () => fetchDrillHistory(principleId),
    staleTime: 30_000,
  });

  const attempts = useMemo(() => sortAttempts(historyQ.data || []), [historyQ.data]);
  const openAttempts = attempts.filter((a) => a.openMistake);
  const pastAttempts = attempts.filter((a) => !a.openMistake);

  const handleResolve = (attemptId: number) => {
    void resolveMistakeApi(String(attemptId)).then((book) => {
      onMistakeBookChange?.(book);
      void queryClient.invalidateQueries({ queryKey: ["skill-drill-history", principleId] });
    });
  };

  return (
    <section
      className={"skill-drill-history" + (compact ? " skill-drill-history--compact" : "")}
      aria-label="修煉紀錄"
    >
      <div className="skill-drill-history-head">
        <AppIcon name="scroll" size={20} framed variant="hero" />
        <div>
          <strong>修煉紀錄</strong>
          <p className="small muted">
            每次試煉都留在這張卡上，含你的作答與教練當時說的話，方便回頭理解。
          </p>
        </div>
      </div>

      {historyQ.isLoading ? (
        <Loading label="載入修煉紀錄…" />
      ) : historyQ.error ? (
        <p className="small muted">暫時無法載入修煉紀錄。</p>
      ) : !attempts.length ? (
        <p className="small muted">尚無試煉紀錄，完成修煉試煉後會出現在這裡。</p>
      ) : (
        <>
          {openAttempts.length ? (
            <div className="skill-drill-log-open-block">
              <div className="skill-drill-log-open-head">
                <AppIcon name="warning" size={18} framed={false} />
                <strong>待補錯題 · {openAttempts.length}</strong>
                <span className="small muted">還沒解決的會固定在最上面</span>
              </div>
              <ol className="skill-drill-log-list">
                {openAttempts.map((a) => (
                  <AttemptLogItem
                    key={a.id}
                    attempt={a}
                    pinned
                    onResolveAttempt={onMistakeBookChange ? handleResolve : undefined}
                    onRetryDrill={onRetryDrill}
                  />
                ))}
              </ol>
            </div>
          ) : null}

          {pastAttempts.length ? (
            <>
              {openAttempts.length ? (
                <div className="skill-drill-log-past-label small muted">過往紀錄</div>
              ) : null}
              <ol className="skill-drill-log-list">
                {pastAttempts.map((a) => (
                  <AttemptLogItem key={a.id} attempt={a} />
                ))}
              </ol>
            </>
          ) : null}
        </>
      )}
    </section>
  );
}