<script>
  /**
   * /study/topics/[id]/questions/new — 문제 입력 페이지 (PR-6 보강).
   *
   * 시험·회차·문항 자동 관리:
   *   - 시험명: topic.name 자동 prefill (수정 가능)
   *   - 과목: 드롭다운 (topic.exam_subjects + 기존 question.subject distinct + 직접 입력)
   *   - 회차: 드롭다운 (기존 distinct + 새 회차 입력). query string ?exam_round= prefill
   *   - 문항 번호: 회차 선택 시 next_question_number 자동, query ?start_qnum= prefill
   *   - 출처/메모: 비어있으면 자동 합성 "{exam_round} {N}번"
   *   - 저장 후 계속 입력: 본문/보기/정답 reset, 시험명/과목/회차 유지, 문항 번호 +1
   *   - 회차 변경 시 문항 번호 1로 reset
   *   - exam_round_size 도달 시 안내 + 회차 강조
   */
  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, Repeat, ListChecks, AlertCircle, ImagePlus, X } from 'lucide-svelte';
  import Button from '$lib/components/ui/Button.svelte';
  import Card from '$lib/components/ui/Card.svelte';
  import TextInput from '$lib/components/ui/TextInput.svelte';
  import Textarea from '$lib/components/ui/Textarea.svelte';

  let topicId = $derived(Number($page.params.id));
  let topicName = $state('');
  let topicExamSubjects = $state([]); // study_topics.exam_subjects
  let topicExamRoundSize = $state(null);

  // 회차 진행률 캐시 (드롭다운 선택 시 next_question_number 조회용)
  let examRounds = $state([]); // [{exam_round, max_question_number, next_question_number, is_complete}]

  // 입력 필드
  let q_text = $state('');
  let c1 = $state('');
  let c2 = $state('');
  let c3 = $state('');
  let c4 = $state('');
  let correct = $state(1);

  // 시험·과목·회차 (저장 후 계속 입력 시 유지)
  let f_exam_name = $state('');
  let f_subject = $state(''); // dropdown 값. 빈 값 = 직접 입력 모드
  let f_subject_custom = $state(''); // 직접 입력 모드 시 값
  let f_subject_mode = $state('dropdown'); // 'dropdown' | 'custom'
  let f_scope = $state('');
  let f_exam_round = $state('');
  let f_exam_round_mode = $state('select'); // 'select' | 'new'
  let f_exam_round_new = $state('');
  let f_qnum = $state(1); // 문항 번호 (표시용 — 저장 시 서버 max+1 우선)
  // PR-7: 사용자가 input 박스를 직접 편집했는지 추적. true 면 저장 시 명시 전송,
  // false 면 null 보내고 서버가 같은 회차 max+1 자동 채움. 회차 변경/저장 후/onMount
  // 에서 false 로 reset.
  let f_qnum_user_edited = $state(false);

  // 본문 자동 reset 안 되는 메타 (편의성 — 비워둠이 default)
  let explanation = $state('');
  let source_note = $state('');

  let saving = $state(false);
  let isCompleteRound = $state(false); // 회차 도달 여부

  // PR-8: 첨부 이미지 (저장 전 client-side 보유 → 저장 후 자동 업로드)
  /** @type {{file: File, previewUrl: string}[]} */
  let pendingImages = $state([]);
  let uploading = $state(false);

  function onPickImages(e) {
    const files = Array.from(e.target.files ?? []);
    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;
      }
      pendingImages = [...pendingImages, { file: f, previewUrl: URL.createObjectURL(f) }];
    }
    e.target.value = ''; // 같은 파일 재선택 가능
  }

  function removePending(idx) {
    const item = pendingImages[idx];
    if (item) URL.revokeObjectURL(item.previewUrl);
    pendingImages = pendingImages.filter((_, i) => i !== idx);
  }

  async function uploadPendingImages(qid) {
    if (pendingImages.length === 0) return 0;
    uploading = true;
    let success = 0;
    try {
      for (const it of pendingImages) {
        const fd = new FormData();
        fd.append('file', it.file, it.file.name);
        try {
          await uploadFile(`/study-questions/${qid}/images`, fd);
          success += 1;
        } catch (err) {
          addToast('error', `${it.file.name} 업로드 실패: ${err?.detail || err?.status || '알수없음'}`);
        }
      }
    } finally {
      uploading = false;
    }
    return success;
  }

  function clearPendingImages() {
    for (const it of pendingImages) URL.revokeObjectURL(it.previewUrl);
    pendingImages = [];
  }

  const STORAGE_KEY = $derived(`study_q_persist_v2_${topicId}`);

  function persist() {
    try {
      sessionStorage.setItem(STORAGE_KEY, JSON.stringify({
        f_exam_name, f_subject, f_subject_custom, f_subject_mode,
        f_scope, f_exam_round, f_qnum,
      }));
    } catch {}
  }

  function loadPersist() {
    try {
      const raw = sessionStorage.getItem(STORAGE_KEY);
      if (!raw) return;
      const p = JSON.parse(raw);
      f_exam_name = p.f_exam_name ?? f_exam_name;
      f_subject = p.f_subject ?? '';
      f_subject_custom = p.f_subject_custom ?? '';
      f_subject_mode = p.f_subject_mode ?? 'dropdown';
      f_scope = p.f_scope ?? '';
      f_exam_round = p.f_exam_round ?? '';
      f_qnum = Number(p.f_qnum) || 1;
    } catch {}
  }

  // 같은 토픽의 기존 question.subject distinct (드롭다운 fallback)
  let questionSubjects = $state([]);

  async function loadTopicAndRounds() {
    try {
      const [t, r] = await Promise.all([
        api(`/study-topics/${topicId}`),
        api(`/study-topics/${topicId}/exam-rounds`),
      ]);
      topicName = t?.topic?.name ?? '';
      topicExamSubjects = t?.topic?.exam_subjects ?? [];
      topicExamRoundSize = t?.topic?.exam_round_size ?? null;
      examRounds = r.items ?? [];
      // exam_name 미설정 시 토픽명 prefill
      if (!f_exam_name) f_exam_name = topicName;
      // 기존 입력 question 의 subject distinct 도 가져옴
      try {
        const list = await api(`/study-topics/${topicId}/questions?page_size=200`);
        const subjs = new Set();
        for (const q of (list.items ?? [])) {
          if (q.subject) subjs.add(q.subject);
        }
        questionSubjects = Array.from(subjs);
      } catch {}
    } catch (err) {
      addToast('error', err.detail || '주제 로딩 실패');
    }
  }

  // query string 처리 (회차 목록에서 ?exam_round=&start_qnum= 로 진입)
  // 반환: start_qnum 이 명시되었는지 여부 (true 면 onMount 가 next_question_number 자동 적용 skip)
  function applyQueryParams() {
    const params = $page.url.searchParams;
    const r = params.get('exam_round');
    const sq = params.get('start_qnum');
    if (r) {
      f_exam_round = r;
      f_exam_round_mode = 'select';
    }
    if (sq) {
      const n = Number(sq);
      if (Number.isFinite(n) && n > 0) {
        f_qnum = n;
        return true;
      }
    }
    return false;
  }

  onMount(async () => {
    loadPersist();
    const explicitQnum = applyQueryParams();
    await loadTopicAndRounds();
    refreshCompleteFlag();
    // PR-7 fix: $effect 가 examRounds fetch 전에 첫 실행되면 found=undefined → f_qnum=1 로
    // 잘못 reset 됨. examRounds 채워진 후 명시적으로 next_question_number 재적용.
    // start_qnum query 가 있으면 그 값 우선 (회차 목록의 [N번부터 이어서] 동선).
    if (!explicitQnum && f_exam_round) {
      const found = examRounds.find((r) => r.exam_round === f_exam_round);
      if (found && found.next_question_number) {
        f_qnum = found.next_question_number;
      }
    }
    // 진입 시점은 사용자가 input 박스를 만진 적 없음 — false 로 reset.
    f_qnum_user_edited = false;
    // $effect 의 lastExamRound 를 현재 값으로 sync — 첫 실행이 또 reset 하지 않도록.
    lastExamRound = f_exam_round;
  });

  // 드롭다운 옵션 합치기 (topic.exam_subjects + 기존 distinct, unique)
  let subjectOptions = $derived(() => {
    const set = new Set();
    for (const s of topicExamSubjects) if (s) set.add(s);
    for (const s of questionSubjects) if (s) set.add(s);
    return Array.from(set);
  });

  // PR-7 fix: 회차 변경은 명시적 onchange 핸들러로 처리 (이전 $effect 패턴은
  // examRounds fetch 전에 첫 실행되며 f_qnum=1 로 reset 하는 race 발생).
  // 사용자가 dropdown 으로 회차를 바꿀 때 + applyNewRound() 에서만 호출.
  let lastExamRound = $state('');
  function onRoundChange() {
    if (!f_exam_round) return;
    if (f_exam_round === lastExamRound) return;
    if (examRounds.length === 0) {
      // examRounds 미적재 → onMount fallback 이 처리. 현재 호출은 skip.
      lastExamRound = f_exam_round;
      return;
    }
    const found = examRounds.find((r) => r.exam_round === f_exam_round);
    if (found && found.next_question_number) {
      f_qnum = found.next_question_number;
    } else if (!found) {
      f_qnum = 1;
    }
    f_qnum_user_edited = false;
    lastExamRound = f_exam_round;
    refreshCompleteFlag();
  }

  function refreshCompleteFlag() {
    const found = examRounds.find((r) => r.exam_round === f_exam_round);
    isCompleteRound = !!(found && found.is_complete);
  }

  function effectiveSubject() {
    return f_subject_mode === 'custom' ? f_subject_custom.trim() : f_subject;
  }

  function autoSourceNote() {
    if (source_note.trim()) return source_note.trim();
    if (f_exam_round) return `${f_exam_round} ${f_qnum}번`;
    return '';
  }

  function applyNewRound() {
    if (!f_exam_round_new.trim()) {
      addToast('error', '회차명을 입력하세요');
      return;
    }
    const newRound = f_exam_round_new.trim();
    f_exam_round = newRound;
    f_exam_round_new = '';
    f_exam_round_mode = 'select';
    // PR-7 fix: 사용자가 "새 회차" 모드에 이미 존재하는 회차명을 입력했으면
    // next_question_number 로 시작 (1번부터 다시 시작 X). dropdown 선택과 동일 동작.
    const found = examRounds.find((r) => r.exam_round === newRound);
    if (found && found.next_question_number) {
      f_qnum = found.next_question_number;
    } else {
      f_qnum = 1;
    }
    f_qnum_user_edited = false;
    lastExamRound = newRound;
    refreshCompleteFlag();
  }

  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;
    }
    if (![1, 2, 3, 4].includes(Number(correct))) {
      addToast('error', '정답은 1~4 중 하나'); return false;
    }
    if (isCompleteRound) {
      addToast('error', '이 회차는 이미 완료되었습니다. 다른 회차를 선택하거나 새 회차를 시작하세요.');
      return false;
    }
    return true;
  }

  function clearForCont() {
    q_text = ''; c1 = ''; c2 = ''; c3 = ''; c4 = ''; correct = 1;
    explanation = ''; source_note = '';
  }

  async function save(continueAfter) {
    if (!validate()) return;
    saving = true;
    persist();
    try {
      const subj = effectiveSubject();
      // PR-7 fix: 클라이언트 카운터를 신뢰하지 않고 서버가 항상 max+1 결정.
      // 사용자가 직접 input 박스를 다른 값으로 수정한 경우만 명시 전송.
      const userEditedQnum = f_qnum_user_edited && f_exam_round;
      const body = {
        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: subj || null,
        scope: f_scope || null,
        exam_name: f_exam_name || null,
        exam_round: f_exam_round || null,
        // 사용자가 직접 수정 안 했으면 null → 서버가 같은 회차 max+1 자동 채움
        exam_question_number: userEditedQnum ? Number(f_qnum) : null,
        explanation: explanation || null,
        source_note: autoSourceNote() || null,
      };
      const saved = await api(`/study-topics/${topicId}/questions`, {
        method: 'POST',
        body: JSON.stringify(body),
      });
      // 응답의 실제 저장값으로 표시 동기화 (서버가 결정한 qnum)
      const actualQnum = saved?.exam_question_number ?? null;
      if (actualQnum) f_qnum = actualQnum;

      // PR-8: 첨부 이미지 자동 업로드 (qid 받은 후)
      let imgMsg = '';
      if (pendingImages.length > 0 && saved?.id) {
        const okCount = await uploadPendingImages(saved.id);
        imgMsg = ` · 이미지 ${okCount}/${pendingImages.length}건 첨부`;
      }

      addToast('success', `문제 저장됨${f_exam_round && actualQnum ? ` (${f_exam_round} ${actualQnum}번)` : ''}${imgMsg}`);
      if (continueAfter) {
        clearForCont();
        clearPendingImages();
        // 다음 표시값 = 방금 저장된 qnum + 1. 사용자가 다시 수정하기 전까지는
        // 자동(서버 max+1) 모드 유지.
        if (actualQnum) f_qnum = actualQnum + 1;
        f_qnum_user_edited = false;
        // 회차 진행률 갱신 (도달 체크)
        await refreshExamRounds();
        persist();
        setTimeout(() => document.getElementById('q-text')?.focus(), 0);
      } else {
        goto(`/study/topics/${topicId}`);
      }
    } catch (err) {
      addToast('error', err.detail || '저장 실패');
    } finally {
      saving = false;
    }
  }

  async function refreshExamRounds() {
    try {
      const r = await api(`/study-topics/${topicId}/exam-rounds`);
      examRounds = r.items ?? [];
      refreshCompleteFlag();
    } catch {}
  }

  // 진행률 표시 (현재 회차)
  let currentProgress = $derived(() => {
    if (!f_exam_round) return null;
    const found = examRounds.find((r) => r.exam_round === f_exam_round);
    const before = found?.question_count ?? 0;
    return { before, size: topicExamRoundSize };
  });
</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 flex-wrap">
    <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>
    <a href={`/study/topics/${topicId}/exam-rounds`} class="ml-auto text-xs text-accent hover:underline flex items-center gap-1">
      <ListChecks size={12} /> 회차 보기
    </a>
  </div>

  <!-- 회차 도달 안내 -->
  {#if isCompleteRound}
    <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>
        <span class="font-semibold">{f_exam_round}</span> 회차는 {topicExamRoundSize}문항 모두 입력됨. 다른 회차를 선택하거나 "새 회차" 를 시작하세요.
      </div>
    </div>
  {/if}

  <Card class="mb-3">
    {#snippet children()}
      <div class="p-4 flex flex-col gap-3">
        <Textarea label="문제 본문" bind:value={q_text} rows={3}
          placeholder="예: 다음 중 가연성 가스의 폭발범위에 대한 설명으로 옳은 것은?" id="q-text" />

        <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-3 border-t border-default">
          <TextInput label="시험명 (자동)" bind:value={f_exam_name} placeholder="예: 가스기사" />

          <!-- 과목 dropdown / 직접 입력 -->
          <div class="flex flex-col gap-1.5">
            <label class="text-xs text-dim">과목</label>
            {#if f_subject_mode === 'dropdown'}
              <div class="flex gap-2">
                <select bind:value={f_subject}
                  class="flex-1 px-3 py-2 bg-surface border border-default rounded text-sm text-text outline-none focus:border-accent">
                  <option value="">— 선택 —</option>
                  {#each subjectOptions() as s}
                    <option value={s}>{s}</option>
                  {/each}
                </select>
                <button type="button" onclick={() => { f_subject_mode = 'custom'; f_subject_custom = f_subject; }}
                  class="text-[11px] text-accent hover:underline shrink-0">직접 입력</button>
              </div>
            {:else}
              <div class="flex gap-2">
                <input type="text" bind:value={f_subject_custom}
                  placeholder="과목 직접 입력"
                  class="flex-1 px-3 py-2 bg-surface border border-default rounded text-sm text-text outline-none focus:border-accent" />
                <button type="button" onclick={() => { f_subject_mode = 'dropdown'; f_subject = f_subject_custom; }}
                  class="text-[11px] text-dim hover:text-text shrink-0">목록에서 선택</button>
              </div>
            {/if}
          </div>

          <TextInput label="범위 (선택)" bind:value={f_scope} placeholder="예: 폭발범위" />

          <!-- 회차 dropdown / 새 회차 -->
          <div class="flex flex-col gap-1.5">
            <label class="text-xs text-dim">회차</label>
            {#if f_exam_round_mode === 'select'}
              <div class="flex gap-2">
                <select bind:value={f_exam_round} onchange={onRoundChange}
                  class="flex-1 px-3 py-2 bg-surface border border-default rounded text-sm text-text outline-none focus:border-accent">
                  <option value="">— 선택 —</option>
                  {#each examRounds as r}
                    <option value={r.exam_round}>
                      {r.exam_round} ({r.question_count}{topicExamRoundSize ? `/${topicExamRoundSize}` : ''})
                    </option>
                  {/each}
                  <!-- FIX: 회차 카드 페이지에서 [새 회차 시작] 으로 진입 시 query 회차명이 기존 examRounds 에 없으면
                       그 회차를 (신규) 라벨로 dropdown 에 임시 추가 — select 옵션에 매칭이 없어서 안 보이는 회귀 차단 -->
                  {#if f_exam_round && !examRounds.some((r) => r.exam_round === f_exam_round)}
                    <option value={f_exam_round}>{f_exam_round} (신규)</option>
                  {/if}
                </select>
                <button type="button" onclick={() => (f_exam_round_mode = 'new')}
                  class="text-[11px] text-accent hover:underline shrink-0">새 회차</button>
              </div>
            {:else}
              <div class="flex gap-2">
                <input type="text" bind:value={f_exam_round_new}
                  placeholder="예: 2019년 1회"
                  onkeydown={(e) => { if (e.key === 'Enter') { e.preventDefault(); applyNewRound(); } }}
                  class="flex-1 px-3 py-2 bg-surface border border-default rounded text-sm text-text outline-none focus:border-accent" />
                <button type="button" onclick={applyNewRound} class="text-[11px] text-accent hover:underline shrink-0">확정</button>
                <button type="button" onclick={() => (f_exam_round_mode = 'select')} class="text-[11px] text-dim hover:text-text shrink-0">취소</button>
              </div>
            {/if}
          </div>
        </div>

        <!-- 문항 번호 + 진행률 -->
        <div class="flex items-end gap-3 flex-wrap">
          <label class="flex flex-col gap-1.5">
            <span class="text-xs text-dim">문항 번호</span>
            <input type="number" min="1" bind:value={f_qnum}
              oninput={() => (f_qnum_user_edited = true)}
              class="w-28 px-3 py-2 bg-surface border border-default rounded text-sm text-text outline-none focus:border-accent" />
          </label>
          {#if currentProgress() && currentProgress().size}
            <div class="flex-1 min-w-32">
              <div class="text-[11px] text-dim mb-1">진행률 {currentProgress().before}/{currentProgress().size}</div>
              <div class="h-1.5 bg-bg rounded-full overflow-hidden">
                <div class="h-full bg-accent transition-all"
                  style="width: {Math.min(100, (currentProgress().before / currentProgress().size) * 100)}%"></div>
              </div>
            </div>
          {/if}
        </div>

        <Textarea label="해설 (선택)" bind:value={explanation} rows={2} placeholder="정답 근거 요약" />
        <TextInput label="출처/메모 (자동: '회차 N번', 수정 가능)" bind:value={source_note}
          placeholder={autoSourceNote() || "예: 산업안전기사 2023 1회 기출 7번"} />

        <!-- PR-8: 이미지 첨부 -->
        <div class="flex flex-col gap-2 pt-3 border-t border-default">
          <div class="flex items-center justify-between">
            <span class="text-xs text-dim">이미지 (선택, PNG/JPEG/WEBP/GIF, 10MB/파일)</span>
            <label class="cursor-pointer text-xs text-accent hover:underline flex items-center gap-1">
              <ImagePlus size={14} /> 이미지 추가
              <input type="file" accept="image/png,image/jpeg,image/webp,image/gif" multiple
                onchange={onPickImages} class="hidden" />
            </label>
          </div>
          {#if pendingImages.length > 0}
            <div class="grid grid-cols-2 sm:grid-cols-3 gap-2">
              {#each pendingImages as it, idx (it.previewUrl)}
                <div class="relative border border-default rounded overflow-hidden bg-bg/30">
                  <img src={it.previewUrl} alt={it.file.name} class="w-full h-24 object-cover" />
                  <div class="px-2 py-1 text-[10px] text-dim truncate">{it.file.name}</div>
                  <button type="button" onclick={() => removePending(idx)}
                    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>
          {:else}
            <div class="text-[11px] text-dim">첨부할 이미지가 없습니다.</div>
          {/if}
        </div>
      </div>
    {/snippet}
  </Card>

  <div class="flex items-center justify-between gap-2 flex-wrap">
    <Button href={`/study/topics/${topicId}`} variant="ghost" icon={ArrowLeft}>주제로</Button>
    <div class="flex gap-2">
      <Button onclick={() => save(false)} loading={saving} variant="ghost" icon={Save}>저장</Button>
      <Button onclick={() => save(true)} loading={saving} icon={Repeat} disabled={isCompleteRound}>저장 후 계속 입력</Button>
    </div>
  </div>
</div>
