<script>
  /**
   * /study/topics/[id]/stats — 학습 통계 대시보드 (Phase 2-D).
   *
   * 6 섹션 — 진척도 / 패턴 분포 / 복습 큐 / 세션 추이 / 일별 풀이량 / 과목별 약점.
   * 차트는 SVG 직접 (의존성 0). backend GET /study-topics/{tid}/stats 한 번에 받음.
   */
  import { onMount } from 'svelte';
  import { page } from '$app/stores';
  import { api } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import { ArrowLeft, BarChart3, BookOpen, Clock, TrendingUp, Sparkles } from 'lucide-svelte';
  import Button from '$lib/components/ui/Button.svelte';
  import Card from '$lib/components/ui/Card.svelte';
  import Skeleton from '$lib/components/ui/Skeleton.svelte';

  let topicId = $derived(Number($page.params.id));
  let topicName = $state('');
  let stats = $state(null);
  let loading = $state(true);

  async function loadTopic() {
    try {
      const t = await api(`/study-topics/${topicId}`);
      topicName = t?.topic?.name ?? '';
    } catch {}
  }

  async function load() {
    loading = true;
    try {
      stats = await api(`/study-topics/${topicId}/stats`);
    } catch (err) {
      addToast('error', err?.detail || '통계 조회 실패');
      stats = null;
    } finally {
      loading = false;
    }
  }

  onMount(async () => {
    await loadTopic();
    await load();
  });

  // 패턴 → 한국어 라벨 + 색상 (Tailwind class — 그래프와 범례 공유)
  const PATTERN_META = [
    { key: 'stable',         label: '안정',      cls: 'bg-success' },
    { key: 'recovered',      label: '회복',      cls: 'bg-success/60' },
    { key: 'unstable',       label: '불안정',    cls: 'bg-accent/60' },
    { key: 'unsure',         label: '모르겠음',  cls: 'bg-warning' },
    { key: 'regressed',      label: '퇴행',      cls: 'bg-error/70' },
    { key: 'chronic_wrong',  label: '반복 오답', cls: 'bg-error' },
    { key: 'unattempted',    label: '미학습',    cls: 'bg-bg/40' },
  ];

  function fmtDateShort(d) {
    if (!d) return '';
    return new Date(d).toLocaleDateString('ko-KR', { month: 'numeric', day: 'numeric' });
  }
  function fmtDateTime(d) {
    if (!d) return '';
    return new Date(d).toLocaleString('ko-KR', { dateStyle: 'short', timeStyle: 'short' });
  }

  // SVG sparkline — accuracy 0~100 범위 폴리라인
  function buildSparkline(points, w, h, padding = 4) {
    if (!points || points.length === 0) return { line: '', dots: [] };
    if (points.length === 1) {
      const cx = w / 2;
      const cy = h - padding - ((points[0] / 100) * (h - 2 * padding));
      return { line: `M ${cx} ${cy}`, dots: [{ x: cx, y: cy, v: points[0] }] };
    }
    const stepX = (w - 2 * padding) / (points.length - 1);
    const xs = points.map((_, i) => padding + i * stepX);
    const ys = points.map((v) => h - padding - ((Math.max(0, Math.min(100, v)) / 100) * (h - 2 * padding)));
    const line = xs.map((x, i) => `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${ys[i].toFixed(1)}`).join(' ');
    const dots = xs.map((x, i) => ({ x, y: ys[i], v: points[i] }));
    return { line, dots };
  }

  // SVG bar chart — daily attempts (0~max 범위)
  function buildBars(daily, w, h, padding = 4) {
    if (!daily || daily.length === 0) return { bars: [], maxV: 0 };
    const maxV = Math.max(...daily.map((d) => d.count), 1);
    const slot = (w - 2 * padding) / daily.length;
    const barW = Math.max(2, slot * 0.7);
    const bars = daily.map((d, i) => {
      const x = padding + i * slot + (slot - barW) / 2;
      const bh = (d.count / maxV) * (h - 2 * padding);
      return { x, y: h - padding - bh, w: barW, h: bh, v: d.count, date: d.date };
    });
    return { bars, maxV };
  }

  // 세션 추이는 oldest→newest 가 sparkline 자연 — backend 는 newest→oldest 라 reverse.
  let sessionPoints = $derived(
    stats?.session_trend ? [...stats.session_trend].reverse().map((s) => s.accuracy) : []
  );
  let sessionRecent = $derived(stats?.session_trend?.slice(0, 5) ?? []);

  // 30일 daily — backend 는 그날 풀이가 있는 날만 반환. UI 표시는 그대로 (gap 무시)
  let dailyChart = $derived(buildBars(stats?.daily_attempts_30d ?? [], 300, 60));
  let sessionChart = $derived(buildSparkline(sessionPoints, 300, 60));

  function statusLabel(k) {
    return ({
      none: '미생성',
      ready: '캐시됨',
      pending: '생성 중',
      failed: '실패',
      skipped: '자료 부족',
      stale: '구버전',
    }[k] ?? k);
  }
  function jobLabel(k) {
    return ({
      'completed': '완료',
      'pending': '대기',
      'processing': '처리 중',
      'failed:guard_fail': '환각 차단',
      'failed:parse_fail': '파싱 실패',
      'failed:llm_timeout': 'LLM timeout',
      'failed:unknown': '알 수 없음',
      'skipped:evidence_missing': '자료 없음 skip',
    }[k] ?? k);
  }

  let totalQ = $derived(stats?.questions?.total ?? 0);
  let attempted = $derived(stats?.questions?.attempted ?? 0);
  let attemptedPct = $derived(totalQ > 0 ? Math.round((attempted / totalQ) * 100) : 0);

  // 패턴 분포 stacked bar 비율
  let patternTotal = $derived(
    PATTERN_META.reduce((sum, p) => sum + (stats?.pattern_distribution?.[p.key] ?? 0), 0)
  );
</script>

<svelte:head><title>학습 통계 — {topicName || '주제'}</title></svelte:head>

<div class="p-4 md:p-6 max-w-3xl mx-auto">
  <div class="flex items-center gap-2 text-xs md:text-sm mb-3">
    <a href="/study" class="text-dim hover:text-text">공부</a>
    <span class="text-faint">/</span>
    <a href="/study/topics" class="text-dim hover:text-text">주제</a>
    <span class="text-faint">/</span>
    <a href={`/study/topics/${topicId}`} class="text-dim hover:text-text truncate">{topicName || '...'}</a>
    <span class="text-faint">/</span>
    <span class="text-text font-medium">통계</span>
  </div>

  {#if loading}
    <Skeleton h="h-32" rounded="lg" />
  {:else if !stats}
    <Card>
      {#snippet children()}
        <div class="p-6 text-center text-dim">통계를 불러올 수 없습니다.</div>
      {/snippet}
    </Card>
  {:else}
    <div class="flex flex-col gap-3">
      <!-- 1. 진척도 -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <div class="flex items-center gap-2">
              <BarChart3 size={14} class="text-accent" />
              <h2 class="text-sm font-semibold text-text">진척도</h2>
            </div>
            <div class="flex items-baseline gap-3">
              <span class="text-2xl font-semibold text-text">{attempted}</span>
              <span class="text-sm text-dim">/ {totalQ} 시도 ({attemptedPct}%)</span>
            </div>
            <div class="h-2 bg-bg/30 rounded-full overflow-hidden">
              <div class="h-full bg-accent" style="width: {attemptedPct}%"></div>
            </div>
            <div class="text-xs text-dim">
              미학습 <span class="text-text">{stats.questions.unattempted}</span>
            </div>
          </div>
        {/snippet}
      </Card>

      <!-- 2. 패턴 분포 (stacked bar + 범례) -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <h2 class="text-sm font-semibold text-text">학습 상태 분포</h2>
            {#if patternTotal === 0}
              <div class="text-xs text-dim">아직 데이터가 없습니다.</div>
            {:else}
              <div class="h-3 flex w-full rounded-full overflow-hidden">
                {#each PATTERN_META as p}
                  {@const cnt = stats.pattern_distribution[p.key] ?? 0}
                  {#if cnt > 0}
                    <div class="h-full {p.cls}" style="width: {(cnt / patternTotal) * 100}%" title={`${p.label} ${cnt}`}></div>
                  {/if}
                {/each}
              </div>
              <ul class="grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1 text-xs">
                {#each PATTERN_META as p}
                  {@const cnt = stats.pattern_distribution[p.key] ?? 0}
                  <li class="flex items-center gap-2">
                    <span class="inline-block w-3 h-3 rounded {p.cls}"></span>
                    <span class="text-dim">{p.label}</span>
                    <span class="text-text font-medium ml-auto">{cnt}</span>
                  </li>
                {/each}
              </ul>
            {/if}
          </div>
        {/snippet}
      </Card>

      <!-- 3. 복습 큐 -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <div class="flex items-center gap-2">
              <Clock size={14} class="text-warning" />
              <h2 class="text-sm font-semibold text-text">복습 큐</h2>
              <a href={`/study/topics/${topicId}/review-queue`} class="ml-auto text-[11px] text-accent hover:underline">복습함 →</a>
            </div>
            <div class="grid grid-cols-2 sm:grid-cols-4 gap-2">
              <div class="p-3 rounded border border-default text-center">
                <div class="text-xs text-dim">오늘</div>
                <div class="text-lg font-semibold text-warning">{stats.due.today}</div>
              </div>
              <div class="p-3 rounded border border-default text-center">
                <div class="text-xs text-dim">이번 주</div>
                <div class="text-lg font-semibold text-text">{stats.due.this_week}</div>
              </div>
              <div class="p-3 rounded border border-default text-center">
                <div class="text-xs text-dim">이후</div>
                <div class="text-lg font-semibold text-dim">{stats.due.later}</div>
              </div>
              <div class="p-3 rounded border border-default text-center">
                <div class="text-xs text-dim">학습완료</div>
                <div class="text-lg font-semibold text-success">{stats.due.mastered}</div>
              </div>
            </div>
            <!-- review_stage 분포 inline -->
            <div class="text-[11px] text-dim">
              stage 분포:
              {#each Object.entries(stats.review_stage_distribution) as [k, v], i}
                <span>{i > 0 ? ' · ' : ''}{k === 'mastered' ? '완료' : `S${k}`} {v}</span>
              {/each}
            </div>
          </div>
        {/snippet}
      </Card>

      <!-- 4. 세션 추이 -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <div class="flex items-center gap-2">
              <TrendingUp size={14} class="text-accent" />
              <h2 class="text-sm font-semibold text-text">세션 추이</h2>
              <span class="ml-auto text-[11px] text-dim">최근 {stats.session_trend.length}회</span>
            </div>
            {#if stats.session_trend.length === 0}
              <div class="text-xs text-dim">완료된 세션이 없습니다.</div>
            {:else}
              <!-- sparkline -->
              <svg viewBox="0 0 300 60" class="w-full h-16 stroke-accent fill-none" stroke-width="1.5">
                <!-- baseline 50% -->
                <line x1="0" y1="30" x2="300" y2="30" class="stroke-default" stroke-dasharray="2 4" stroke-width="0.5" />
                <path d={sessionChart.line} stroke-linejoin="round" stroke-linecap="round" />
                {#each sessionChart.dots as d}
                  <circle cx={d.x} cy={d.y} r="2" class="fill-accent" />
                {/each}
              </svg>
              <div class="text-[11px] text-dim text-right">정답률 100% · · · 0%</div>

              <!-- 최근 5 세션 표 -->
              <ul class="flex flex-col gap-1.5 text-xs">
                {#each sessionRecent as s}
                  <li class="flex items-center gap-2 border-b border-default/40 pb-1.5">
                    <a href={`/study/topics/${topicId}/quiz-sessions/${s.id}`} class="text-dim hover:text-text">{fmtDateTime(s.finished_at)}</a>
                    <span class="text-text font-medium">{s.accuracy}%</span>
                    <span class="text-dim">({s.correct_count}/{s.total})</span>
                    {#if s.recovered_count > 0}<span class="text-success">↗{s.recovered_count}</span>{/if}
                    {#if s.relapsed_count > 0}<span class="text-error">↘{s.relapsed_count}</span>{/if}
                    {#if s.newly_correct_count > 0}<span class="text-success">🆕{s.newly_correct_count}</span>{/if}
                  </li>
                {/each}
              </ul>
            {/if}
          </div>
        {/snippet}
      </Card>

      <!-- 5. 일별 풀이량 30일 -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <div class="flex items-center gap-2">
              <h2 class="text-sm font-semibold text-text">최근 30일 풀이량</h2>
              <span class="ml-auto text-[11px] text-dim">{stats.daily_attempts_30d.reduce((s, d) => s + d.count, 0)} 문제</span>
            </div>
            {#if stats.daily_attempts_30d.length === 0}
              <div class="text-xs text-dim">최근 30일 안에 풀이 기록이 없습니다.</div>
            {:else}
              <svg viewBox="0 0 300 60" class="w-full h-16">
                {#each dailyChart.bars as b}
                  <rect x={b.x} y={b.y} width={b.w} height={b.h} class="fill-accent">
                    <title>{b.date} · {b.v}문제</title>
                  </rect>
                {/each}
              </svg>
              <div class="flex justify-between text-[10px] text-dim">
                {#if stats.daily_attempts_30d.length > 0}
                  <span>{fmtDateShort(stats.daily_attempts_30d[0].date)}</span>
                  <span>최대 {dailyChart.maxV}문제</span>
                  <span>{fmtDateShort(stats.daily_attempts_30d[stats.daily_attempts_30d.length - 1].date)}</span>
                {/if}
              </div>
            {/if}
          </div>
        {/snippet}
      </Card>

      <!-- 6.5 Phase 4-A: AI 풀이 캐시 진척 + 최근 7일 worker 결과 -->
      {#if stats.ai_explanation}
        {@const ae = stats.ai_explanation}
        {@const targetPct = ae.target_total > 0 ? Math.round((ae.target_ready / ae.target_total) * 100) : 0}
        <Card>
          {#snippet children()}
            <div class="p-5 flex flex-col gap-3">
              <div class="flex items-center gap-2">
                <Sparkles size={14} class="text-accent" />
                <h2 class="text-sm font-semibold text-text">AI 풀이 캐시</h2>
              </div>

              <!-- 핵심 진척: wrong/unsure 중 ready 비율 -->
              {#if ae.target_total > 0}
                <div class="flex items-baseline gap-3">
                  <span class="text-2xl font-semibold text-text">{ae.target_ready}</span>
                  <span class="text-sm text-dim">/ {ae.target_total} 오답·모르겠음 풀이 준비됨 ({targetPct}%)</span>
                </div>
                <div class="h-2 bg-bg/30 rounded-full overflow-hidden">
                  <div class="h-full bg-success" style="width: {targetPct}%"></div>
                </div>
              {:else}
                <div class="text-xs text-dim">오답·모르겠음 문제가 없습니다.</div>
              {/if}

              <!-- 토픽 전체 status 분포 -->
              <div class="text-[11px] text-dim">
                토픽 전체 풀이 상태:
                {#each Object.entries(ae.status_distribution).filter(([_,v]) => v > 0) as [k, v], i}
                  <span>{i > 0 ? ' · ' : ''}{statusLabel(k)} {v}</span>
                {/each}
              </div>

              <!-- 최근 7일 worker 결과 분포 (운영 관찰) -->
              {#if Object.keys(ae.recent_jobs).length > 0}
                <div class="border-t border-default pt-2 text-[11px] text-dim">
                  <div class="mb-1">최근 7일 worker:</div>
                  <ul class="grid grid-cols-2 sm:grid-cols-3 gap-x-3 gap-y-0.5">
                    {#each Object.entries(ae.recent_jobs) as [k, v]}
                      <li class="flex justify-between">
                        <span>{jobLabel(k)}</span>
                        <span class="text-text">{v}</span>
                      </li>
                    {/each}
                  </ul>
                </div>
              {/if}
            </div>
          {/snippet}
        </Card>
      {/if}

      <!-- 6. 과목별 약점 -->
      <Card>
        {#snippet children()}
          <div class="p-5 flex flex-col gap-3">
            <div class="flex items-center gap-2">
              <BookOpen size={14} class="text-accent" />
              <h2 class="text-sm font-semibold text-text">과목별</h2>
            </div>
            {#if stats.subject_breakdown.length === 0}
              <div class="text-xs text-dim">과목 분류된 문제가 없습니다.</div>
            {:else}
              <ul class="flex flex-col gap-2">
                {#each stats.subject_breakdown as sb}
                  <li class="text-xs text-text">
                    <div class="flex items-center gap-2 flex-wrap">
                      <span class="font-medium truncate">{sb.subject}</span>
                      <span class="text-dim">{sb.attempted}/{sb.total}</span>
                      {#if sb.attempted > 0}
                        <span class="ml-auto">정답률 <span class="text-text font-medium">{sb.accuracy}%</span></span>
                      {/if}
                    </div>
                    {#if sb.attempted > 0}
                      <div class="mt-1 h-1.5 bg-bg/30 rounded-full overflow-hidden">
                        <div class="h-full bg-accent" style="width: {(sb.accuracy / 100) * 100}%"></div>
                      </div>
                    {/if}
                    {#if sb.pending_review > 0 || sb.chronic > 0}
                      <div class="text-[11px] text-dim mt-1 flex gap-3">
                        {#if sb.pending_review > 0}
                          <span><span class="text-error">미확인</span> {sb.pending_review}</span>
                        {/if}
                        {#if sb.chronic > 0}
                          <span><span class="text-warning">반복 오답</span> {sb.chronic}</span>
                        {/if}
                      </div>
                    {/if}
                  </li>
                {/each}
              </ul>
            {/if}
          </div>
        {/snippet}
      </Card>

      <div class="flex justify-end pt-1">
        <Button href={`/study/topics/${topicId}`} variant="ghost" icon={ArrowLeft}>주제로</Button>
      </div>
    </div>
  {/if}
</div>
