"use client";
// 回响星核 / Echo Nexus — 回响编年史对话框（v0.4 跨周目叙事时间轴）
import { useEffect, useState, useMemo } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import { useGameStore } from "@/store/gameStore";
import {
  PERK_NAME_MAP,
  getCategoryColor,
  getCategoryName,
  getPerkCategoryBreakdown,
  regenerateLoreFromEntry,
} from "@/lib/game/chronicle";
import { getPerk } from "@/lib/game/constellation";
import { TIDE_EVENTS } from "@/lib/game/starTide";
import { sfx } from "@/hooks/useAudio";
import type { ChronicleEntry } from "@/lib/game/types";
import { BookOpen, Clock, Swords, Trophy, Sparkles, Star, Waves, Cpu, Zap, ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "@/components/ui/button";

interface Props {
  open: boolean;
  onOpenChange: (v: boolean) => void;
}

/** tide ID (tide_xxx) → 展示信息（从 TIDE_EVENTS 复用） */
function getTideDisplay(tideId: string): { name: string; color: string } {
  // tideId 形如 "tide_crystal"，剥离前缀后查 TIDE_EVENTS
  const type = tideId.startsWith("tide_") ? tideId.slice(5) : tideId;
  const ev = TIDE_EVENTS[type as keyof typeof TIDE_EVENTS];
  return ev ? { name: ev.name, color: ev.color } : { name: tideId, color: "#94a3b8" };
}

function formatDuration(sec: number): string {
  if (sec < 60) return `${sec}秒`;
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  if (m < 60) return s > 0 ? `${m}分${s}秒` : `${m}分钟`;
  const h = Math.floor(m / 60);
  return `${h}小时${m % 60}分`;
}

function formatDate(ts: number): string {
  const d = new Date(ts);
  const mm = String(d.getMonth() + 1).padStart(2, "0");
  const dd = String(d.getDate()).padStart(2, "0");
  const hh = String(d.getHours()).padStart(2, "0");
  const mi = String(d.getMinutes()).padStart(2, "0");
  return `${mm}-${dd} ${hh}:${mi}`;
}

export function ChronicleDialog({ open, onOpenChange }: Props) {
  const chronicle = useGameStore((s) => s.chronicle ?? []);
  const ascensions = useGameStore((s) => s.ascensions ?? 0);
  const bossKills = useGameStore((s) => s.bossKills ?? 0);
  const tidesAll = useGameStore((s) => s.starTidesEncountered ?? []);
  // 倒序展示（最新的在前）
  const entries: ChronicleEntry[] = useMemo(() => [...chronicle].reverse(), [chronicle]);

  // v0.8.2 分页（工单 #8）：编年史上限 200 条，每页 10 条
  const PAGE_SIZE = 10;
  const totalPages = Math.max(1, Math.ceil(entries.length / PAGE_SIZE));
  const [page, setPage] = useState(1);
  // 当 entries 变化（新飞升）且当前页超出范围时，回到第 1 页（最新）
  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    if (page > totalPages) setPage(1);
  }, [page, totalPages]);
  // 打开时默认回到第 1 页（最新）
  useEffect(() => {
    if (open) {
      sfx("chronicleOpen");
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setPage(1);
    }
  }, [open]);
  const pagedEntries = entries.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="bg-gradient-to-br from-violet-950/80 via-black/90 to-fuchsia-950/60 border-fuchsia-400/30 max-w-3xl max-h-[88vh] overflow-hidden flex flex-col p-0 gap-0">
        {/* 顶部装饰条 */}
        <div className="h-1 bg-gradient-to-r from-emerald-500 via-fuchsia-500 to-amber-500 opacity-70" />

        <DialogHeader className="px-6 pt-5 pb-3 space-y-1">
          <DialogTitle className="flex items-center gap-2 text-fuchsia-100 text-xl">
            <BookOpen className="h-5 w-5 text-fuchsia-300" />
            回响编年史
            <span className="text-[11px] font-normal text-fuchsia-300/60 ml-2">
              Chronicle of Echoes
            </span>
          </DialogTitle>
          <DialogDescription className="text-fuchsia-200/60 text-xs">
            每一次飞升都在深空留下回响。这里铭刻着跨越维度的全部纪元。
          </DialogDescription>

          {/* 总览统计条 */}
          <div className="grid grid-cols-3 gap-2 pt-2">
            <OverviewStat
              icon={<Sparkles className="h-3 w-3" />}
              label="飞升次数"
              value={ascensions}
              color="#e879f9"
            />
            <OverviewStat
              icon={<Trophy className="h-3 w-3" />}
              label="BOSS 击破"
              value={bossKills}
              color="#fbbf24"
            />
            <OverviewStat
              icon={<Waves className="h-3 w-3" />}
              label="星潮亲历"
              value={tidesAll.length}
              color="#34d399"
            />
          </div>
        </DialogHeader>

        {/* 时间轴滚动区 */}
        <div className="flex-1 overflow-y-auto px-6 pb-3 echo-scroll">
          {entries.length === 0 ? (
            <EmptyState ascensions={ascensions} />
          ) : (
            <div className="relative">
              {/* 中央时间轴线 */}
              <div className="absolute left-[27px] top-2 bottom-2 w-px bg-gradient-to-b from-fuchsia-400/40 via-violet-400/30 to-transparent" />

              <div className="space-y-4">
                {pagedEntries.map((entry, idx) => (
                  <ChronicleCard
                    key={`${entry.ascensionNumber}-${entry.timestamp}`}
                    entry={entry}
                    isLatest={(page - 1) * PAGE_SIZE + idx === 0}
                    index={(page - 1) * PAGE_SIZE + idx}
                  />
                ))}
              </div>
            </div>
          )}
        </div>

        {/* v0.8.2 分页控制栏（工单 #8） */}
        {entries.length > PAGE_SIZE && (
          <div className="px-6 py-2.5 border-t border-fuchsia-400/15 bg-black/40 flex items-center justify-between gap-2">
            <span className="text-[11px] text-muted-foreground font-mono">
              第 {page} / {totalPages} 页 · 共 {entries.length} 条飞升记录
            </span>
            <div className="flex items-center gap-1.5">
              <Button
                variant="ghost"
                size="sm"
                disabled={page <= 1}
                onClick={() => { sfx("tabSwitch"); setPage((p) => Math.max(1, p - 1)); }}
                className="h-7 px-2 text-fuchsia-300 hover:bg-fuchsia-500/15 disabled:opacity-30"
              >
                <ChevronLeft className="h-3.5 w-3.5" />
                上一页
              </Button>
              <Button
                variant="ghost"
                size="sm"
                disabled={page >= totalPages}
                onClick={() => { sfx("tabSwitch"); setPage((p) => Math.min(totalPages, p + 1)); }}
                className="h-7 px-2 text-fuchsia-300 hover:bg-fuchsia-500/15 disabled:opacity-30"
              >
                下一页
                <ChevronRight className="h-3.5 w-3.5" />
              </Button>
            </div>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}

function OverviewStat({
  icon,
  label,
  value,
  color,
}: {
  icon: React.ReactNode;
  label: string;
  value: number;
  color: string;
}) {
  return (
    <div
      className="rounded-md border px-3 py-2 flex items-center gap-2"
      style={{
        borderColor: `${color}33`,
        background: `${color}0d`,
      }}
    >
      <div style={{ color }}>{icon}</div>
      <div className="flex-1 min-w-0">
        <div className="text-[10px] text-muted-foreground truncate">{label}</div>
        <div className="text-sm font-mono font-bold" style={{ color }}>
          {value}
        </div>
      </div>
    </div>
  );
}

function EmptyState({ ascensions }: { ascensions: number }) {
  const isPreV04 = ascensions > 0;
  return (
    <div className="flex flex-col items-center justify-center py-20 text-center">
      <div className="relative mb-4">
        <div className="absolute inset-0 blur-xl bg-fuchsia-500/20 rounded-full animate-pulse" />
        <BookOpen className="relative h-12 w-12 text-fuchsia-400/50" />
      </div>
      {isPreV04 ? (
        <>
          <div className="text-fuchsia-200/70 text-sm">
            已飞升 {ascensions} 次，但编年史尚无记录
          </div>
          <div className="text-fuchsia-300/40 text-[11px] mt-2 max-w-xs">
            编年史于 v0.4 启用。下一次飞升将自动铭刻新纪元，开启永恒叙事时间轴。
          </div>
        </>
      ) : (
        <>
          <div className="text-fuchsia-200/70 text-sm">尚未飞升，等待第一次跨越维度</div>
          <div className="text-fuchsia-300/40 text-[11px] mt-2 max-w-xs">
            当接触进度满溢时，发起飞升将开启新周目，并在编年史中铭刻一段永恒回响。
          </div>
        </>
      )}
    </div>
  );
}

function ChronicleCard({
  entry,
  isLatest,
  index,
}: {
  entry: ChronicleEntry;
  isLatest: boolean;
  index: number;
}) {
  // 5 纪元循环颜色
  const epochColors = ["#34d399", "#fb7185", "#fbbf24", "#e879f9", "#fcd34d"];
  const epochColor = epochColors[(entry.ascensionNumber - 1) % 5];

  return (
    <div
      className="relative pl-16 animate-in fade-in slide-in-from-bottom-2 duration-500"
      style={{ animationDelay: `${index * 80}ms` }}
    >
      {/* 时间轴节点 */}
      <div className="absolute left-[19px] top-3 z-10">
        <div
          className="w-4 h-4 rounded-full border-2 flex items-center justify-center"
          style={{
            borderColor: epochColor,
            background: `${epochColor}22`,
            boxShadow: `0 0 12px ${epochColor}88, 0 0 24px ${epochColor}44`,
          }}
        >
          <div
            className="w-1.5 h-1.5 rounded-full"
            style={{ background: epochColor }}
          />
        </div>
        {isLatest && (
          <div
            className="absolute inset-0 rounded-full animate-ping"
            style={{ background: `${epochColor}33` }}
          />
        )}
      </div>

      {/* 卡片主体 */}
      <div
        className="rounded-lg border bg-black/40 backdrop-blur-sm overflow-hidden transition-all hover:scale-[1.005] hover:border-fuchsia-400/40"
        style={{
          borderColor: `${epochColor}33`,
          boxShadow: isLatest
            ? `0 0 0 1px ${epochColor}22, 0 4px 24px ${epochColor}22`
            : `0 2px 8px rgba(0,0,0,0.4)`,
        }}
      >
        {/* 卡片头部 */}
        <div
          className="px-4 py-3 flex items-center justify-between border-b"
          style={{
            background: `linear-gradient(135deg, ${epochColor}11, transparent)`,
            borderColor: `${epochColor}22`,
          }}
        >
          <div className="flex-1 min-w-0">
            <div className="flex items-baseline gap-2">
              <span
                className="text-[10px] font-mono font-bold px-1.5 py-0.5 rounded"
                style={{
                  color: epochColor,
                  background: `${epochColor}22`,
                }}
              >
                #{String(entry.ascensionNumber).padStart(2, "0")}
              </span>
              <h4
                className="text-sm font-bold tracking-wide truncate"
                style={{
                  color: epochColor,
                  textShadow: `0 0 12px ${epochColor}55`,
                }}
              >
                {entry.epochName}
              </h4>
            </div>
            <div className="flex items-center gap-2 mt-1 text-[10px] text-muted-foreground/80">
              <span className="flex items-center gap-0.5">
                <Clock className="h-2.5 w-2.5" />
                {formatDate(entry.timestamp)}
              </span>
              <span className="text-muted-foreground/40">·</span>
              <span>{formatDuration(entry.durationSec)}</span>
              {isLatest && (
                <>
                  <span className="text-muted-foreground/40">·</span>
                  <span className="text-fuchsia-300 font-bold">最新</span>
                </>
              )}
            </div>
          </div>
        </div>

        {/* 叙事文本（显示时重新生成，修复历史条目中 tide_ruins 等原始键名） */}
        <div className="px-4 py-3 text-[12px] leading-relaxed text-fuchsia-100/75 font-serif">
          {regenerateLoreFromEntry(entry)}
        </div>

        {/* 统计芯片 */}
        <div className="px-4 pb-3 flex flex-wrap gap-1.5">
          <StatChip
            icon={<Cpu className="h-2.5 w-2.5" />}
            label="解码"
            value={entry.summary.crystalsDecodedThisRun}
            color="#fb7185"
          />
          <StatChip
            icon={<Sparkles className="h-2.5 w-2.5" />}
            label="技术"
            value={entry.summary.techsUnlocked}
            color="#34d399"
          />
          <StatChip
            icon={<Swords className="h-2.5 w-2.5" />}
            label="探险"
            value={entry.summary.expeditionsCompleted}
            color="#fbbf24"
          />
          {entry.summary.bossKills > 0 && (
            <StatChip
              icon={<Trophy className="h-2.5 w-2.5" />}
              label="BOSS"
              value={entry.summary.bossKills}
              color="#e879f9"
            />
          )}
          <StatChip
            icon={<Waves className="h-2.5 w-2.5" />}
            label="星潮"
            value={entry.tidesThisRun.length}
            color="#94a3b8"
          />
          <StatChip
            icon={<Star className="h-2.5 w-2.5" />}
            label="星图"
            value={entry.summary.constellationsTotal}
            color="#fcd34d"
          />
        </div>

        {/* 星潮列表 */}
        {entry.tidesThisRun.length > 0 && (
          <div className="px-4 pb-2 flex flex-wrap gap-1">
            {entry.tidesThisRun.map((tide) => {
              const td = getTideDisplay(tide);
              return (
                <span
                  key={tide}
                  className="text-[9px] px-1.5 py-0.5 rounded border"
                  style={{
                    color: td.color,
                    borderColor: `${td.color}44`,
                    background: `${td.color}11`,
                  }}
                >
                  ✦ {td.name}
                </span>
              );
            })}
          </div>
        )}

        {/* 天赋徽章 */}
        {entry.perksThisAscension.length > 0 && (
          <div className="px-4 pb-2 flex flex-wrap gap-1">
            {entry.perksThisAscension.map((perkId) => {
              const perk = getPerk(perkId);
              const cat = perk?.category || "cosmic";
              const color = getCategoryColor(cat);
              const catName = getCategoryName(cat);
              const perkName = PERK_NAME_MAP[perkId] || perkId;
              return (
                <span
                  key={perkId}
                  className="text-[9px] px-1.5 py-0.5 rounded border inline-flex items-center gap-1"
                  style={{
                    color,
                    borderColor: `${color}55`,
                    background: `${color}11`,
                  }}
                  title={`${catName} · ${perk?.desc || ""}`}
                >
                  <Zap className="h-2 w-2" />
                  {perkName}
                </span>
              );
            })}
          </div>
        )}

        {/* 里程碑 */}
        {entry.milestones.length > 0 && (
          <div
            className="px-4 py-2 border-t flex flex-wrap gap-1.5"
            style={{
              borderColor: `${epochColor}22`,
              background: `${epochColor}08`,
            }}
          >
            {entry.milestones.map((m, i) => (
              <span
                key={i}
                className="text-[10px] px-1.5 py-0.5 rounded-full bg-fuchsia-500/15 text-fuchsia-200 border border-fuchsia-400/30 inline-flex items-center gap-1"
              >
                <Sparkles className="h-2 w-2" />
                {m}
              </span>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function StatChip({
  icon,
  label,
  value,
  color,
}: {
  icon: React.ReactNode;
  label: string;
  value: number;
  color: string;
}) {
  return (
    <span
      className="text-[10px] px-1.5 py-0.5 rounded inline-flex items-center gap-1 font-mono"
      style={{
        color,
        background: `${color}11`,
        border: `1px solid ${color}22`,
      }}
    >
      {icon}
      <span className="opacity-70">{label}</span>
      <span className="font-bold">{value}</span>
    </span>
  );
}

/** 当前周目进度预览（在编年史对话框中以小卡片显示，提示玩家本周目已有数据） */
export function ChronicleCurrentRunBadge() {
  const runStart = useGameStore((s) => s.runStart);
  const totalExpeditions = useGameStore((s) => s.totalExpeditions);
  const totalDecoded = useGameStore((s) => s.totalDecoded);
  const techCount = useGameStore((s) => Object.keys(s.tech || {}).length);

  const exps = Math.max(0, totalExpeditions - (runStart?.expeditionsCompleted || 0));
  const decoded = Math.max(0, totalDecoded - (runStart?.crystalsDecoded || 0));
  const techs = Math.max(0, techCount - (runStart?.techsUnlocked || 0));

  if (exps === 0 && decoded === 0 && techs === 0) return null;

  return (
    <div className="text-[10px] text-muted-foreground/60 flex items-center gap-2">
      <span className="text-fuchsia-300/80">本周目:</span>
      <span>{decoded}解码</span>
      <span>·</span>
      <span>{techs}技术</span>
      <span>·</span>
      <span>{exps}探险</span>
    </div>
  );
}
