<script>
  /**
   * /study/topics/[id]/questions/[qid]/edit — 문제 편집 페이지.
   *
   * 정답(correct_choice) 변경 시 기존 attempts.is_correct 는 재계산되지 않음.
   * 풀이 시점의 정오답이 그대로 보존되므로 안내 배너 고정 노출.
   * 삭제는 soft delete 만 (DB FK RESTRICT 로 hard delete 차단, 이력 보존).
   */
  import { onMount } from 'svelte';
  import { page } from '$app/stores';
  import { goto } from '$app/navigation';
  import { api, uploadFile } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import { ArrowLeft, Save, Trash2, AlertCircle, Sparkles, GitCompare, ArrowRight, CheckCircle2, XCircle, ImagePlus, X } from 'lucide-svelte';
  import { renderMathMarkdown } from '$lib/utils/mathMarkdown';
  import Button from '$lib/components/ui/Button.svelte';
  import Card from '$lib/components/ui/Card.svelte';
  import Skeleton from '$lib/components/ui/Skeleton.svelte';
  import TextInput from '$lib/components/ui/TextInput.svelte';
  import Textarea from '$lib/components/ui/Textarea.svelte';
  import ImgAuth from '$lib/components/ImgAuth.svelte';

  let topicId = $derived(Number($page.params.id));
  let questionId = $derived(Number($page.params.qid));

  let loading = $state(true);
  let saving = $state(false);
  let deleting = $state(false);

  let topicName = $state('');
  let q_text = $state('');
  let c1 = $state(''); let c2 = $state(''); let c3 = $state(''); let c4 = $state('');
  let correct = $state(1);
  let subject = $state(''); let scope = $state('');
  let exam_name = $state(''); let exam_round = $state('');
  let explanation = $state(''); let source_note = $state('');
  let is_active = $state(true);
  let stats = $state({ attempt_count: 0, correct_count: 0, wrong_count: 0 });

  // PR-8: 첨부 이미지
  let images = $state([]); // [{id, served_url, mime_type, file_size, sort_order}]
  let imgUploading = $state(false);

  async function refreshImages() {
    try {
      const q = await api(`/study-questions/${questionId}`);
      images = q.images ?? [];
    } catch {}
  }

  async function uploadImages(e) {
    const files = Array.from(e.target.files ?? []);
    if (files.length === 0) return;
    imgUploading = true;
    let ok = 0;
    for (const f of files) {
      if (!f.type.startsWith('image/')) {
        addToast('error', `이미지 파일이 아닙니다: ${f.name}`);
        continue;
      }
      if (f.size > 10 * 1024 * 1024) {
        addToast('error', `${f.name} 10MB 초과`);
        continue;
      }
      const fd = new FormData();
      fd.append('file', f, f.name);
      try {
        await uploadFile(`/study-questions/${questionId}/images`, fd);
        ok += 1;
      } catch (err) {
        addToast('error', `${f.name} 업로드 실패: ${err?.detail || err?.status || '알수없음'}`);
      }
    }
    imgUploading = false;
    e.target.value = '';
    if (ok > 0) {
      await refreshImages();
      addToast('success', `${ok}건 업로드됨`);
    }
  }

  async function deleteImage(imgId) {
    if (!confirm('이미지를 삭제합니다.')) return;
    try {
      await api(`/study-questions/${questionId}/images/${imgId}`, { method: 'DELETE' });
      images = images.filter((x) => x.id !== imgId);
    } catch (err) {
      addToast('error', err?.detail || '삭제 실패');
    }
  }

  // PR-5: 비슷한 문제 검색 결과
  let similarLoading = $state(false);
  let similarItems = $state([]);
  let similarSourceStatus = $state('none');

  async function loadSimilar() {
    similarLoading = true;
    try {
      const res = await api(`/study-questions/${questionId}/similar?limit=5&topic_only=true`);
      similarItems = res.items ?? [];
      similarSourceStatus = res.source_status ?? 'none';
    } catch {
      similarItems = [];
    } finally {
      similarLoading = false;
    }
  }

  // PR-3: AI 풀이 상태 + 본문 캐시
  let aiStatus = $state('none'); // none | pending | ready | failed | stale
  let aiGeneratedAt = $state(null);
  let aiModel = $state(null);
  let aiBody = $state(null);
  let aiEvidence = $state([]);
  let aiOpen = $state(false);
  let aiLoading = $state(false);
  let aiError = $state(null);

  async function fetchAiBody(regenerate = false) {
    aiLoading = true;
    aiError = null;
    try {
      const res = await api(`/study-questions/${questionId}/ai-explanation`, {
        method: 'POST',
        body: JSON.stringify({ regenerate }),
      });
      aiBody = res.ai_explanation;
      aiStatus = res.ai_explanation_status;
      aiGeneratedAt = res.ai_explanation_generated_at;
      aiModel = res.ai_explanation_model;
      aiEvidence = res.evidence ?? [];
      aiOpen = true;
      if (aiStatus === 'failed') aiError = '풀이 생성 실패. "다시 시도" 를 눌러주세요.';
    } catch (err) {
      if (err?.status === 409) {
        aiError = '다른 호출이 풀이를 생성 중입니다. 잠시 후 다시 시도.';
      } else {
        aiError = err?.detail || 'AI 풀이 생성 실패';
      }
    } finally {
      aiLoading = false;
    }
  }

  async function load() {
    loading = true;
    try {
      const [t, q] = await Promise.all([
        api(`/study-topics/${topicId}`),
        api(`/study-questions/${questionId}`),
      ]);
      topicName = t?.topic?.name ?? '';
      q_text = q.question_text;
      c1 = q.choice_1; c2 = q.choice_2; c3 = q.choice_3; c4 = q.choice_4;
      correct = q.correct_choice;
      subject = q.subject ?? '';
      scope = q.scope ?? '';
      exam_name = q.exam_name ?? '';
      exam_round = q.exam_round ?? '';
      explanation = q.explanation ?? '';
      source_note = q.source_note ?? '';
      is_active = q.is_active;
      stats = q.stats;
      aiStatus = q.ai_explanation_status ?? 'none';
      aiGeneratedAt = q.ai_explanation_generated_at;
      aiModel = q.ai_explanation_model;
      // PR-8: 이미지 prefill
      images = q.images ?? [];
      // PR-5: 비슷한 문제 자동 로드 (페이지 로드와 병렬)
      loadSimilar();
    } catch (err) {
      addToast('error', err.detail || '문제 로딩 실패');
    } finally {
      loading = false;
    }
  }

  onMount(load);

  function validate() {
    if (!q_text.trim()) { addToast('error', '문제 본문을 입력하세요'); return false; }
    if (!c1.trim() || !c2.trim() || !c3.trim() || !c4.trim()) {
      addToast('error', '1~4번 보기를 모두 입력하세요'); return false;
    }
    return true;
  }

  async function save() {
    if (!validate()) return;
    saving = true;
    try {
      await api(`/study-questions/${questionId}`, {
        method: 'PATCH',
        body: JSON.stringify({
          question_text: q_text.trim(),
          choice_1: c1.trim(), choice_2: c2.trim(),
          choice_3: c3.trim(), choice_4: c4.trim(),
          correct_choice: Number(correct),
          subject: subject || null,
          scope: scope || null,
          exam_name: exam_name || null,
          exam_round: exam_round || null,
          explanation: explanation || null,
          source_note: source_note || null,
          is_active,
        }),
      });
      addToast('success', '저장됨');
      goto(`/study/topics/${topicId}`);
    } catch (err) {
      addToast('error', err.detail || '저장 실패');
    } finally {
      saving = false;
    }
  }

  async function remove() {
    if (!confirm('이 문제를 삭제합니다.\n풀이 기록(attempts)은 보존되지만 복습 후보에서는 제외됩니다.')) return;
    deleting = true;
    try {
      await api(`/study-questions/${questionId}`, { method: 'DELETE' });
      addToast('success', '삭제됨');
      goto(`/study/topics/${topicId}`);
    } catch (err) {
      addToast('error', err.detail || '삭제 실패');
      deleting = false;
    }
  }
</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>

  <!-- 정답 변경 → attempts 재계산 안 됨 안내 -->
  <div class="mb-3 p-3 rounded-lg border border-warning/40 bg-warning/5 text-xs text-text flex items-start gap-2">
    <AlertCircle size={14} class="text-warning shrink-0 mt-0.5" />
    <div>
      정답을 수정해도 기존 풀이 기록은 변경되지 않습니다.<br />
      풀이 시점의 정답·정오답이 그대로 보존됩니다 ({stats.attempt_count}회 누적, 정답 {stats.correct_count} / 오답 {stats.wrong_count}).
    </div>
  </div>

  {#if loading}
    <Skeleton h="h-64" rounded="lg" />
  {:else}
    <Card class="mb-3">
      {#snippet children()}
        <div class="p-4 flex flex-col gap-3">
          <Textarea label="문제 본문" bind:value={q_text} rows={3} />

          <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
            <TextInput label="① 1번 보기" bind:value={c1} />
            <TextInput label="② 2번 보기" bind:value={c2} />
            <TextInput label="③ 3번 보기" bind:value={c3} />
            <TextInput label="④ 4번 보기" bind:value={c4} />
          </div>

          <div class="flex flex-col gap-1.5">
            <label class="text-xs text-dim">정답 번호</label>
            <div class="flex items-center gap-2">
              {#each [1, 2, 3, 4] as n}
                <button
                  type="button"
                  onclick={() => (correct = n)}
                  class="px-4 py-2 rounded border text-sm font-medium transition-colors
                    {correct === n ? 'bg-accent text-white border-accent' : 'bg-surface text-dim border-default hover:text-text'}"
                  aria-pressed={correct === n}
                >{n}</button>
              {/each}
            </div>
          </div>

          <div class="grid grid-cols-1 md:grid-cols-2 gap-3 pt-2 border-t border-default">
            <TextInput label="과목" bind:value={subject} />
            <TextInput label="범위" bind:value={scope} />
            <TextInput label="시험명" bind:value={exam_name} />
            <TextInput label="회차" bind:value={exam_round} />
          </div>

          <Textarea label="해설" bind:value={explanation} rows={2} />
          <TextInput label="출처/메모" bind:value={source_note} />

          <label class="flex items-center gap-2 text-xs text-dim cursor-pointer">
            <input type="checkbox" bind:checked={is_active} />
            <span>출제 활성 (체크 해제 시 복습 후보에서 일시 제외, 데이터는 유지)</span>
          </label>
        </div>
      {/snippet}
    </Card>

    <!-- PR-8: 첨부 이미지 -->
    <Card class="mb-3">
      {#snippet children()}
        <div class="p-4 flex flex-col gap-3">
          <div class="flex items-center justify-between flex-wrap gap-2">
            <div class="flex items-center gap-2">
              <ImagePlus size={16} class="text-accent" />
              <span class="text-sm font-semibold text-text">첨부 이미지</span>
              <span class="text-[11px] text-dim">{images.length}건</span>
            </div>
            <label class="cursor-pointer text-xs text-accent hover:underline flex items-center gap-1">
              {#if imgUploading}
                <span>업로드 중...</span>
              {:else}
                <ImagePlus size={14} />
                <span>이미지 추가</span>
              {/if}
              <input type="file" accept="image/png,image/jpeg,image/webp,image/gif" multiple
                onchange={uploadImages} disabled={imgUploading} class="hidden" />
            </label>
          </div>
          {#if images.length === 0}
            <div class="text-[11px] text-dim">첨부된 이미지가 없습니다. PNG/JPEG/WEBP/GIF, 10MB/파일.</div>
          {:else}
            <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
              {#each images as img (img.id)}
                <div class="relative border border-default rounded overflow-hidden bg-bg/30">
                  <ImgAuth src={img.served_url} class="w-full h-28 object-cover" />
                  <div class="px-2 py-1 text-[10px] text-dim truncate">{Math.round(img.file_size/1024)} KB</div>
                  <button type="button" onclick={() => deleteImage(img.id)}
                    class="absolute top-1 right-1 w-5 h-5 rounded-full bg-black/60 text-white flex items-center justify-center hover:bg-error"
                    aria-label="삭제">
                    <X size={12} />
                  </button>
                </div>
              {/each}
            </div>
          {/if}
        </div>
      {/snippet}
    </Card>

    <!-- PR-3: AI 풀이 섹션 -->
    <Card class="mb-3">
      {#snippet children()}
        <div class="p-4 flex flex-col gap-3">
          <div class="flex items-center gap-2 flex-wrap">
            <Sparkles size={16} class="text-accent" />
            <span class="text-sm font-semibold text-text">AI 풀이</span>
            <span class="text-[10px] text-dim border border-default rounded px-1.5 py-0.5">{aiStatus}</span>
            {#if aiGeneratedAt}
              <span class="text-[10px] text-dim">{new Date(aiGeneratedAt).toLocaleString('ko-KR', { dateStyle: 'short', timeStyle: 'short' })}{aiModel ? ` · ${aiModel}` : ''}</span>
            {/if}
            <span class="ml-auto flex items-center gap-2">
              {#if aiStatus === 'pending'}
                <Button size="sm" variant="ghost" disabled>생성 중...</Button>
              {:else if aiStatus === 'none'}
                <Button size="sm" onclick={() => fetchAiBody(false)} loading={aiLoading} icon={Sparkles}>AI 풀이 생성</Button>
              {:else if aiStatus === 'failed'}
                <Button size="sm" onclick={() => fetchAiBody(true)} loading={aiLoading} icon={Sparkles}>다시 시도</Button>
              {:else if aiStatus === 'stale'}
                {#if !aiOpen}
                  <Button size="sm" variant="ghost" onclick={() => fetchAiBody(false)} loading={aiLoading}>이전 풀이 보기</Button>
                {/if}
                <Button size="sm" onclick={() => fetchAiBody(true)} loading={aiLoading} icon={Sparkles}>AI 풀이 다시 생성</Button>
              {:else if aiStatus === 'ready'}
                {#if !aiOpen}
                  <Button size="sm" variant="ghost" onclick={() => fetchAiBody(false)} loading={aiLoading}>본문 보기</Button>
                {:else}
                  <Button size="sm" variant="ghost" onclick={() => (aiOpen = false)}>접기</Button>
                {/if}
                <Button size="sm" onclick={() => fetchAiBody(true)} loading={aiLoading}>다시 생성</Button>
              {/if}
            </span>
          </div>

          {#if aiStatus === 'stale'}
            <div class="text-[11px] text-warning bg-warning/5 border border-warning/30 rounded px-2 py-1.5 flex items-start gap-1.5">
              <AlertCircle size={12} class="mt-0.5 shrink-0" />
              <span>문제 본문·보기·정답이 수정된 후의 이전 풀이입니다. "AI 풀이 다시 생성" 으로 새로 만들 수 있습니다.</span>
            </div>
          {/if}

          {#if aiError}
            <div class="text-[11px] text-error">{aiError}</div>
          {/if}

          {#if aiOpen && aiBody}
            <div class="text-sm text-text leading-relaxed bg-bg/30 border border-default rounded p-3 markdown-body math-area">
              {@html renderMathMarkdown(aiBody)}
            </div>
            {#if aiEvidence?.length}
              <details class="text-[10px] text-dim">
                <summary class="cursor-pointer hover:text-text">참고 근거 {aiEvidence.length}건</summary>
                <ul class="mt-1 flex flex-col gap-1">
                  {#each aiEvidence as ev}
                    <li>
                      <span class="text-text">{ev.source_type === 'document' ? '📄' : '❓'} {ev.title}</span>
                      <div class="pl-4 truncate">{ev.snippet}</div>
                    </li>
                  {/each}
                </ul>
              </details>
            {/if}
          {/if}
        </div>
      {/snippet}
    </Card>

    <!-- PR-5: 비슷한 문제 5개 (embedding cosine, 26B 호출 없음) -->
    <Card class="mb-3">
      {#snippet children()}
        <div class="p-4 flex flex-col gap-3">
          <div class="flex items-center gap-2">
            <GitCompare size={16} class="text-accent" />
            <span class="text-sm font-semibold text-text">비슷한 문제</span>
            <span class="text-[11px] text-dim">{similarItems.length}건</span>
          </div>

          {#if similarLoading}
            <div class="text-xs text-dim">불러오는 중…</div>
          {:else if similarSourceStatus !== 'ready'}
            <div class="text-xs text-dim">
              {#if similarSourceStatus === 'pending'}
                임베딩 생성 중입니다. 잠시 후 새로고침하면 비슷한 문제가 표시됩니다.
              {:else if similarSourceStatus === 'failed'}
                임베딩 생성 실패. 다음 cron 틱(약 1분)에 자동 재시도됩니다.
              {:else if similarSourceStatus === 'stale'}
                문제 본문 변경 후 임베딩 재계산 대기 중입니다. 잠시 후 새로고침해주세요.
              {:else}
                임베딩 미생성 (none). 약 1분 안에 cron 이 자동 처리합니다.
              {/if}
            </div>
          {:else if similarItems.length === 0}
            <div class="text-xs text-dim">이 주제에 비슷한 문제가 아직 없습니다.</div>
          {:else}
            <ul class="flex flex-col gap-1.5">
              {#each similarItems as it (it.id)}
                <li>
                  <a
                    href={`/study/topics/${it.study_topic_id}/questions/${it.id}/edit`}
                    class="flex items-center gap-3 p-2.5 rounded border border-default bg-bg/30 hover:border-accent hover:bg-accent/5 transition-colors"
                  >
                    <div class="flex-1 min-w-0">
                      <div class="text-sm text-text truncate">{it.question_text}</div>
                      <div class="text-[11px] text-dim mt-0.5 flex items-center gap-2 flex-wrap">
                        {#if it.subject}<span>{it.subject}</span>{/if}
                        {#if it.scope}<span>· {it.scope}</span>{/if}
                        {#if it.exam_round}<span>· {it.exam_round}</span>{/if}
                        {#if it.attempt_count > 0}
                          <span class="ml-auto flex items-center gap-1">
                            {#if it.last_correct === true}
                              <CheckCircle2 size={11} class="text-success" />
                            {:else if it.last_correct === false}
                              <XCircle size={11} class="text-error" />
                            {/if}
                            <span>{it.attempt_count}회</span>
                          </span>
                        {/if}
                      </div>
                    </div>
                    <span class="text-[11px] text-accent font-medium shrink-0">{Math.round(it.similarity * 100)}%</span>
                    <ArrowRight size={12} class="text-dim shrink-0" />
                  </a>
                </li>
              {/each}
            </ul>
          {/if}
        </div>
      {/snippet}
    </Card>

    <div class="flex items-center justify-between gap-2 flex-wrap">
      <div class="flex gap-2">
        <Button href={`/study/topics/${topicId}`} variant="ghost" icon={ArrowLeft}>주제로</Button>
        <Button onclick={remove} loading={deleting} variant="ghost" icon={Trash2}>삭제</Button>
      </div>
      <Button onclick={save} loading={saving} icon={Save}>저장</Button>
    </div>
  {/if}
</div>
