import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { AttributeRadar } from "../components/AttributeRadar";
import { AppIcon } from "../components/PixelIcons";
import { Card, ErrorState, Loading, Tag } from "../components/ui";
import { usePlayerProgress } from "../hooks/usePlayerProgress";
import { api } from "../lib/api";
import { syncPlayerProgress } from "../lib/learningSync";
import {
  LEVEL_TITLES,
  type AchievementCategory,
  type BranchEpithet,
  type EpithetBranchKind,
} from "../lib/playerProgress";

const EPITHET_BRANCH_ORDER: EpithetBranchKind[] = [
  "macro",
  "pick",
  "timing",
  "discipline",
  "pattern",
  "strategy",
];

function fmtPct(v: number | null) {
  if (v == null || Number.isNaN(v)) return "—";
  return `${v.toFixed(0)}%`;
}

const TIER_LABEL = { bronze: "銅", silver: "銀", gold: "金", legend: "傳說" } as const;

export default function Profile() {
  const qc = useQueryClient();
  const { player, isLoading, isError } = usePlayerProgress();
  const [resetBusy, setResetBusy] = useState(false);
  const [resetMsg, setResetMsg] = useState<string | null>(null);
  const [nameDraft, setNameDraft] = useState("");
  const [nameBusy, setNameBusy] = useState(false);
  const [nameMsg, setNameMsg] = useState<string | null>(null);
  const [epithetBusy, setEpithetBusy] = useState<string | null>(null);
  const [epithetMsg, setEpithetMsg] = useState<string | null>(null);

  useEffect(() => {
    if (player?.displayName) setNameDraft(player.displayName);
  }, [player?.displayName]);

  const equipEpithet = async (id: string | null) => {
    setEpithetBusy(id ?? "auto");
    setEpithetMsg(null);
    try {
      const res = await api.setPlayerEpithet(id);
      syncPlayerProgress(qc);
      setEpithetMsg(res.message || "已更新稱號");
    } catch (e) {
      setEpithetMsg((e as Error).message || "裝備失敗");
    } finally {
      setEpithetBusy(null);
    }
  };

  const saveName = async () => {
    const trimmed = nameDraft.trim();
    if (trimmed.length < 2) {
      setNameMsg("名稱至少 2 個字。");
      return;
    }
    setNameBusy(true);
    setNameMsg(null);
    try {
      const res = await api.setPlayerName(trimmed);
      syncPlayerProgress(qc);
      setNameDraft(res.displayName || trimmed);
      setNameMsg(res.message || "已儲存");
    } catch (e) {
      setNameMsg((e as Error).message || "儲存失敗");
    } finally {
      setNameBusy(false);
    }
  };

  const resetCharacter = async () => {
    const ok = window.confirm(
      "確定要重置角色養成？\n\n將清空：心法進度、試煉、筆記、圖鑑、EXP／金幣／徽章，以及交易上的復盤欄位。\n交易紀錄與帳號會保留。",
    );
    if (!ok) return;
    setResetBusy(true);
    setResetMsg(null);
    try {
      const res = await api.resetPlayerCharacter();
      syncPlayerProgress(qc);
      qc.invalidateQueries({ queryKey: ["skill-state"] });
      qc.invalidateQueries({ queryKey: ["pattern-state"] });
      qc.invalidateQueries({ queryKey: ["trades"] });
      qc.invalidateQueries({ queryKey: ["trade-stats"] });
      setResetMsg(res.message || "角色已重置。");
    } catch (e) {
      setResetMsg((e as Error).message || "重置失敗");
    } finally {
      setResetBusy(false);
    }
  };

  if (isLoading) return <Loading label="載入角色資料…" />;
  if (isError || !player) return <ErrorState detail="無法載入角色養成資料" />;

  const xpPct = player.xpToNext ? Math.round((player.xpInLevel / player.xpToNext) * 100) : 100;
  const unlockedCount = player.achievements.filter((a) => a.unlocked).length;

  const questsByChapter = player.quests.reduce<Record<string, typeof player.quests>>((acc, q) => {
    (acc[q.chapter] ||= []).push(q);
    return acc;
  }, {});

  const epithetsByBranch = (player.epithets || []).reduce<Record<string, BranchEpithet[]>>((acc, e) => {
    (acc[e.branch] ||= []).push(e);
    return acc;
  }, {});

  const achievementsByCategory = player.achievements.reduce<
    Record<AchievementCategory, typeof player.achievements>
  >((acc, a) => {
    (acc[a.category] ||= []).push(a);
    return acc;
  }, {} as Record<AchievementCategory, typeof player.achievements>);

  return (
    <>
      <div className="page-head">
        <div className="eyebrow">我的</div>
        <h1 className="page-title-row">
          <AppIcon name="wizard" size={38} framed glow variant="hero" />
          角色養成
        </h1>
        <p>EXP 只獎勵「學懂、驗證、反思」——不看你短期勝率或賺賠。這是投資學習的冒險地圖。</p>
      </div>

      <Card className="profile-hero-card">
        <div className="profile-hero">
          <div className="profile-hero-avatar">
            <AppIcon name="wizard" size={48} framed glow variant="hero" />
          </div>
          <div className="profile-hero-body">
            <div className="profile-hero-top">
              <div>
                <div className="profile-name-form">
                  <label className="small muted" htmlFor="profile-display-name">
                    冒險者名稱
                  </label>
                  <div className="profile-name-row">
                    <input
                      id="profile-display-name"
                      className="profile-name-input"
                      value={nameDraft}
                      maxLength={16}
                      placeholder="取一個名字…"
                      onChange={(e) => setNameDraft(e.target.value)}
                      onKeyDown={(e) => {
                        if (e.key === "Enter") void saveName();
                      }}
                    />
                    <button
                      type="button"
                      className="btn-ghost sm"
                      disabled={nameBusy || nameDraft.trim() === player.displayName}
                      onClick={() => void saveName()}
                    >
                      {nameBusy ? "儲存中…" : "儲存"}
                    </button>
                  </div>
                  {nameMsg ? <span className="small profile-name-msg">{nameMsg}</span> : null}
                </div>
                <div className="profile-hero-title">
                  Lv.{player.level} · {player.title}
                  {player.epithet ? <span className="profile-hero-epithet">「{player.epithet}」</span> : null}
                </div>
                <span className="profile-stage-tag">
                  <Tag tone="gold">{player.learningStage}</Tag>
                </span>
              </div>
              <div className="profile-hero-gold">
                <AppIcon name="coin" size={20} framed variant="nav" />
                <span>{player.gold.toLocaleString()} G</span>
              </div>
            </div>
            <p className="small profile-stage-hint">{player.learningStageHint}</p>
            <div className="xp-label">
              <span>EXP</span>
              <span>
                {player.xpInLevel.toLocaleString()} / {player.xpToNext.toLocaleString()}
              </span>
            </div>
            <div className="bar">
              <span style={{ width: `${xpPct}%` }} />
            </div>
            <p className="small muted profile-hero-xp-note">累積 {player.totalXp.toLocaleString()} EXP</p>
          </div>
        </div>
      </Card>

      <div className="grid g2 mt">
        <Card title="冒險階級" ico={<AppIcon name="key" size={22} framed variant="nav" />}>
          <p className="small muted" style={{ marginTop: 0, marginBottom: 12 }}>
            主稱號只看 <b>Lv</b>，代表你的冒險資歷。
          </p>
          <div className="profile-title-ladder">
            {LEVEL_TITLES.map((t) => {
              const unlocked = player.level >= t.minLevel;
              const current = player.title === t.title;
              return (
                <div
                  key={t.minLevel}
                  className={`profile-title-step${unlocked ? " unlocked" : ""}${current ? " current" : ""}`}
                >
                  <span className="profile-title-lv">Lv.{t.minLevel}</span>
                  <span className="profile-title-label">{t.title}</span>
                  {current ? <Tag tone="gold">目前</Tag> : unlocked ? <Tag>已達</Tag> : <Tag>未達</Tag>}
                </div>
              );
            })}
          </div>
        </Card>

        <Card title="支線稱號 · 裝備" ico={<AppIcon name="sword" size={22} framed variant="nav" />}>
          <p className="small muted" style={{ marginTop: 0, marginBottom: 10 }}>
            依 <b>五維屬性</b>與<b>實戰流派</b>解鎖不同稱謂，可自由裝備展示。
            {player.dominantAttribute
              ? ` 目前主屬性：${player.attributes.find((a) => a.id === player.dominantAttribute)?.label || "—"}。`
              : " 多修煉後會出現主屬性。"}
          </p>
          <div className="profile-epithet-toolbar">
            <button
              type="button"
              className={`btn-ghost sm${player.equippedEpithetId === "auto" || !player.equippedEpithetId ? " active" : ""}`}
              disabled={epithetBusy !== null}
              onClick={() => void equipEpithet(null)}
            >
              自動（依主屬性）
            </button>
            {player.epithet ? <Tag tone="gold">展示中：{player.epithet}</Tag> : <Tag>尚無支線稱號</Tag>}
          </div>
          {epithetMsg ? <p className="small profile-name-msg">{epithetMsg}</p> : null}
        </Card>
      </div>

      <Card title="支線稱號圖鑑" ico={<AppIcon name="map" size={22} framed variant="nav" />} className="mt">
        <p className="small muted" style={{ marginTop: 0, marginBottom: 14 }}>
          走不同學習路線會解鎖不同稱謂——總經派、選股派、波段派、紀律派、圖鑑派，或實戰流派組合。
        </p>
        {EPITHET_BRANCH_ORDER.map((branch) => {
          const items = epithetsByBranch[branch];
          if (!items?.length) return null;
          return (
            <div key={branch} className="profile-epithet-branch">
              <div className="profile-epithet-branch-title">{items[0].branchLabel}</div>
              <div className="profile-epithet-grid">
                {items.map((e) => {
                  const equipped = player.epithetId === e.id;
                  const isAutoEquipped =
                    (player.equippedEpithetId === "auto" || !player.equippedEpithetId) && equipped;
                  return (
                    <div
                      key={e.id}
                      className={`profile-epithet-card${e.unlocked ? " unlocked" : " locked"}${equipped ? " equipped" : ""}`}
                    >
                      <AppIcon name={e.icon} size={22} framed variant="nav" glow={e.unlocked && equipped} />
                      <div className="profile-epithet-body">
                        <div className="profile-epithet-name">{e.label}</div>
                        <div className="small muted">{e.desc}</div>
                        <div className="small muted profile-epithet-req">{e.requirement}</div>
                        {!e.unlocked && e.progress ? (
                          <div className="small profile-epithet-progress">{e.progress}</div>
                        ) : null}
                      </div>
                      {e.unlocked ? (
                        <button
                          type="button"
                          className="btn-ghost sm"
                          disabled={epithetBusy !== null || equipped}
                          onClick={() => void equipEpithet(e.id)}
                        >
                          {epithetBusy === e.id
                            ? "…"
                            : equipped
                              ? isAutoEquipped
                                ? "自動中"
                                : "已裝備"
                              : "裝備"}
                        </button>
                      ) : (
                        <Tag>未解鎖</Tag>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </Card>

      <Card
        title="經驗值怎麼來？"
        ico={<AppIcon name="hourglass" size={22} framed variant="nav" />}
        className="mt"
      >
        <p className="small muted" style={{ marginTop: 0 }}>
          設計原則：<b>理解 &gt; 勝率</b>、<b>反思 &gt; 交易次數</b>、<b>精通 &gt; 瀏覽</b>。
        </p>
        <div className="profile-xp-grid">
          {player.xpBreakdown.map((line) => (
            <div key={line.label} className="profile-xp-line" title={line.hint}>
              <div className="profile-xp-line-head">
                <span>{line.label}</span>
                <strong>+{line.xp.toLocaleString()}</strong>
              </div>
              <p className="small muted">{line.hint}</p>
            </div>
          ))}
        </div>
      </Card>

      <div className="grid g2 mt">
        <Card title="五維屬性" ico={<AppIcon name="compass" size={22} framed variant="nav" />}>
          <p className="small muted" style={{ marginTop: 0, marginBottom: 12 }}>
            每項滿分 100，由底下可核對的計分項加總。點開可看公式與你的實際數字。
          </p>
          <div className="radar-wrap">
            <AttributeRadar attributes={player.attributes} />
            <div className="attr-list">
              {player.attributes.map((attr) => (
                <div key={attr.id} className="attr-block">
                  <div className="attr-row" title={attr.hint}>
                    <span className="nm">{attr.label}</span>
                    <div className="bar">
                      <span style={{ width: `${attr.value}%` }} />
                    </div>
                    <span className="vv">{attr.value}</span>
                  </div>
                  <p className="small muted attr-formula-hint">{attr.hint}</p>
                  <div className="attr-breakdown">
                    <div className="attr-breakdown-head">
                      <span>計分項</span>
                      <span>
                        {attr.earned}/{attr.max} 分
                      </span>
                    </div>
                    {attr.breakdown.map((line) => (
                      <div key={line.label} className="attr-breakdown-row" title={line.detail}>
                        <span className="attr-bd-label">{line.label}</span>
                        <span className="attr-bd-score">
                          {line.earned}/{line.max}
                        </span>
                        <span className="attr-bd-detail">{line.detail}</span>
                      </div>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </Card>

        <Card title="學習戰績" ico={<AppIcon name="chart" size={22} framed variant="nav" />}>
          <div className="dl">
            <div className="row">
              <span className="k">心法解鎖</span>
              <span className="v">
                {player.skillStats.read} / {player.skillStats.total}
              </span>
            </div>
            <div className="row">
              <span className="k">心法精通</span>
              <span className="v">{player.skillStats.mastered} 條</span>
            </div>
            <div className="row">
              <span className="k">線型圖鑑</span>
              <span className="v">
                {player.patternStats.collected} / {player.patternStats.total}
              </span>
            </div>
            <div className="row">
              <span className="k">完整復盤</span>
              <span className="v">{player.journalStats.withReflection} 筆</span>
            </div>
            <div className="row">
              <span className="k">心法標註交易</span>
              <span className="v">{player.journalStats.withPrinciple} 筆</span>
            </div>
            <div className="row">
              <span className="k">多元心法復盤</span>
              <span className="v">{player.journalStats.distinctPrinciples} 種</span>
            </div>
            <div className="row">
              <span className="k">無犯錯率</span>
              <span className="v">{fmtPct(player.journalStats.discipline)}</span>
            </div>
          </div>
          <div className="profile-quick-links">
            <Link to="/skills" className="btn-ghost sm">
              <AppIcon name="scroll" size={16} framed variant="nav" />
              心法技能樹
            </Link>
            <Link to="/patterns" className="btn-ghost sm">
              <AppIcon name="cards" size={16} framed variant="nav" />
              線型圖鑑
            </Link>
            <Link to="/journal" className="btn-ghost sm">
              <AppIcon name="folder" size={16} framed variant="nav" />
              復盤戰績
            </Link>
          </div>
        </Card>
      </div>

      <Card
        title="冒險委託 · 投資學習路線"
        ico={<AppIcon name="map" size={22} framed variant="nav" />}
        className="mt"
      >
        <p className="small muted" style={{ marginTop: 0, marginBottom: 12 }}>
          依你目前的階段排列；每章都在回答「下一步該學什麼、為什麼」。
        </p>
        {Object.entries(questsByChapter).map(([chapter, items]) => (
          <div key={chapter} className="profile-quest-chapter">
            <div className="profile-quest-chapter-title">{chapter}</div>
            {items.map((q) => (
              <div key={q.id} className={`quest${q.done ? " done" : ""}`}>
                <span className="chk">{q.done ? "✓" : ""}</span>
                <div className="q-body">
                  <div className="q-title">
                    {q.title}
                    {q.progress ? <span className="profile-quest-progress"> {q.progress}</span> : null}
                  </div>
                  <div className="q-sub">{q.sub}</div>
                  <div className="profile-quest-why">{q.why}</div>
                </div>
                <span className="q-xp">+{q.xp} EXP</span>
                {q.href && !q.done ? (
                  <Link to={q.href} className="profile-quest-go">
                    前往
                  </Link>
                ) : null}
              </div>
            ))}
          </div>
        ))}
      </Card>

      <Card
        title={`成就徽章 · ${unlockedCount}/${player.achievements.length}`}
        ico={<AppIcon name="coin" size={22} framed variant="nav" />}
        className="mt"
      >
        <div className="profile-ach-summary">
          {player.achievementCategories.map((c) => (
            <span key={c.id} className="profile-ach-pill">
              {c.label} {c.unlocked}/{c.total}
            </span>
          ))}
        </div>
        {player.achievementCategories.map((cat) => {
          const items = achievementsByCategory[cat.id] || [];
          if (!items.length) return null;
          return (
            <div key={cat.id} className="profile-ach-section">
              <div className="profile-ach-section-title">
                {cat.label}
                <span className="muted small">
                  {cat.unlocked}/{cat.total}
                </span>
              </div>
              <div className="ach-grid">
                {items.map((a) => (
                  <div key={a.id} className={`ach${a.unlocked ? " unlocked" : " locked"}`}>
                    <div className="a-ic">
                      <AppIcon name={a.icon} size={22} framed variant="nav" glow={a.unlocked} />
                    </div>
                    <div>
                      <div className="a-nm">
                        {a.name}
                        {a.tier ? (
                          <span className={`profile-ach-tier tier-${a.tier}`}>{TIER_LABEL[a.tier]}</span>
                        ) : null}
                      </div>
                      <div className="a-d">{a.desc}</div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </Card>

      <Card title="重置角色" ico={<AppIcon name="hourglass" size={22} framed variant="nav" />} className="mt">
        <p className="small muted" style={{ marginTop: 0 }}>
          從 Lv.1 重新開始學習路線。不會刪除交易帳號與買賣紀錄，但會清掉復盤心得、心法標註等養成資料。
        </p>
        {resetMsg ? <p className="small" style={{ color: "var(--teal)" }}>{resetMsg}</p> : null}
        <button type="button" className="btn-ghost sm" disabled={resetBusy} onClick={() => void resetCharacter()}>
          {resetBusy ? "重置中…" : "清空角色養成"}
        </button>
      </Card>

      <Card title="內容統計" ico={<AppIcon name="folder" size={22} framed variant="nav" />} className="mt">
        <ContentReadingStats />
      </Card>

      <Card title="重置角色" ico={<AppIcon name="hourglass" size={22} framed variant="nav" />} className="mt">
        <p className="small muted" style={{ marginTop: 0 }}>
          從 Lv.1 重新開始學習路線。不會刪除交易帳號與買賣紀錄，但會清掉復盤心得、心法標註等養成資料。
        </p>
        {resetMsg ? <p className="small" style={{ color: "var(--teal)" }}>{resetMsg}</p> : null}
        <button type="button" className="btn-ghost sm" disabled={resetBusy} onClick={() => void resetCharacter()}>
          {resetBusy ? "重置中…" : "清空角色養成"}
        </button>
      </Card>
    </>
  );
}

function ContentReadingStats() {
  const q = useQuery({
    queryKey: ["content-stats"],
    queryFn: () => api.contentStats(),
    staleTime: 30000,
  });
  if (!q.data) return null;
  const stats = q.data;
  const total = stats.total || 0;
  if (!total) return <p className="muted small">尚未從 YouTube 或 HyRead 匯入內容</p>;
  return (
    <div className="dl">
      <div className="row"><span className="k">YouTube 影片</span><span className="v">{stats.byKind?.youtube?.ready || 0} 部</span></div>
      <div className="row"><span className="k">HyRead 書籍</span><span className="v">{stats.byKind?.hyread?.ready || 0} 本</span></div>
      <div className="row"><span className="k">知識庫總計</span><span className="v">{total} 個來源</span></div>
    </div>
  );
}