<script>
  import { api, getAccessToken } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import { marked } from 'marked';
  import DOMPurify from 'dompurify';
  import { ExternalLink, Save } from 'lucide-svelte';
  import Tabs from '$lib/components/ui/Tabs.svelte';
  import MarkdownDoc from '$lib/components/MarkdownDoc.svelte';
  import MarkdownStatusBadge from '$lib/components/MarkdownStatusBadge.svelte';
  import SectionOutline from '$lib/components/SectionOutline.svelte';
  import { getViewerType } from '$lib/utils/viewerType';
  import { isMdSuccess } from '$lib/utils/mdStatus';
  import { resolveAnchorMap } from '$lib/utils/resolveAnchorMap';
  import { cleanHeading } from '$lib/utils/headingPath';

  // 편집 미리보기 전용 plain marked (본문 렌더는 MarkdownDoc 가 담당).
  marked.use({ mangle: false, headerIds: false });
  function renderMd(text) {
    return DOMPurify.sanitize(marked(text), {
      USE_PROFILES: { html: true },
      FORBID_TAGS: ['style', 'script'],
      FORBID_ATTR: ['onerror', 'onclick'],
      ALLOW_UNKNOWN_PROTOCOLS: false,
    });
  }

  let { doc } = $props();
  let fullDoc = $state(null);
  let loading = $state(true);
  let viewerType = $state('none');

  // Markdown 편집 (md/txt — extracted_text 가 표시·편집 단일 필드)
  let editMode = $state(false);
  let editContent = $state('');
  let editTab = $state('edit');
  let saving = $state(false);
  let rawMarkdown = $state('');

  const ODF_FORMATS = ['ods', 'odt', 'odp', 'odoc', 'osheet'];

  function getEditInfo(d) {
    if (d.edit_url) return { url: d.edit_url, label: '편집' };
    if (ODF_FORMATS.includes(d.file_format)) return { url: 'https://link.hyungi.net', label: 'Synology Drive에서 열기' };
    if (['dwg', 'dxf'].includes(d.file_format)) return { url: 'https://web.autocad.com', label: 'AutoCAD Web' };
    return null;
  }

  $effect(() => {
    if (doc?.id) {
      loadFullDoc(doc.id);
      editMode = false;
    }
  });

  async function loadFullDoc(id) {
    loading = true;
    rawMarkdown = '';
    sections = [];
    try {
      fullDoc = await api(`/documents/${id}`);
      viewerType = getViewerType(fullDoc.file_format, fullDoc.source_channel);
      loadSections(id);

      // 본문 markdown(md/txt) 인데 extracted_text 가 비면 원본 파일 직접 로드.
      if (viewerType === 'markdown' && !fullDoc.extracted_text) {
        try {
          const resp = await fetch(`/api/documents/${id}/file?token=${getAccessToken()}`);
          if (resp.ok) rawMarkdown = await resp.text();
        } catch (e) { rawMarkdown = ''; }
      }
    } catch (err) {
      fullDoc = null;
      viewerType = 'none';
    } finally {
      loading = false;
    }
  }

  // PDF markdown-first: marker 가 만든 canonical md_content 가 있으면 기본으로 그것을 보여주고
  // "PDF 원본" 토글 제공. lastDocId 는 prop(fullDoc.id) 로 키잉 — 3-pane 은 라우트 리마운트가
  // 없어 page.params 가드는 no-op 이 된다.
  let pdfViewMode = $state('markdown');
  let lastDocId = $state(null);
  let canShowMarkdown = $derived(
    !!(isMdSuccess(fullDoc?.md_status) && fullDoc?.md_content?.trim())
  );
  $effect(() => {
    if (!fullDoc) return;
    if (fullDoc.id !== lastDocId) {
      lastDocId = fullDoc.id;
      pdfViewMode = canShowMarkdown ? 'markdown' : 'pdf';
    }
    if (!canShowMarkdown && pdfViewMode === 'markdown') pdfViewMode = 'pdf';
  });

  // ── 절 목차(개요) rail + 점프 + scroll-spy (outlineAnchors, 경로 A) ──
  let sections = $state([]);
  async function loadSections(id) {
    try {
      const r = await api(`/documents/${id}/sections`);
      if (id === doc?.id) sections = r?.sections ?? [];
    } catch {
      if (id === doc?.id) sections = [];
    }
  }
  // window 빈제목(31% 노이즈) 등 표시 가능한 제목 없는 항목은 rail 에서 제외(클린업).
  let outlineSections = $derived(
    sections.filter(
      (s) => !!(cleanHeading(s.section_title) || cleanHeading((s.heading_path || '').split('>').pop() || '')),
    ),
  );
  // MarkdownDoc 가 실제 렌더하는 텍스트(rail 표시 게이트용).
  let mdRenderText = $derived.by(() => {
    if (!fullDoc) return '';
    if (viewerType === 'pdf') return pdfViewMode === 'markdown' && canShowMarkdown ? (fullDoc.md_content || '') : '';
    if (viewerType === 'markdown') return fullDoc.extracted_text || rawMarkdown || '';
    if (viewerType === 'hwp-markdown' || viewerType === 'article') return fullDoc.md_content || fullDoc.extracted_text || '';
    return '';
  });
  // [g5-t3] basis 는 RENDER SITE 별. anchorMap 을 basis 별로 분리 — 같은 component 가 두 basis 를
  // 공유하면(md_content vs extracted_text) trustBE 가 어긋난다.
  //   - md_content site(pdf-markdown): trustBE=true (BE char_start 1순위, 비면 내부 string-match 폴백).
  //   - extracted_text site(3-pane markdown): trustBE=false (char_start 는 md_content offset 이라 무효 → 무조건 폴백).
  let mdBasisText = $derived.by(() => {
    if (!fullDoc) return '';
    if (viewerType === 'pdf') return pdfViewMode === 'markdown' && canShowMarkdown ? (fullDoc.md_content || '') : '';
    return '';
  });
  let extractedBasisText = $derived.by(() => {
    if (!fullDoc) return '';
    if (viewerType === 'markdown') return fullDoc.extracted_text || rawMarkdown || '';
    return '';
  });
  let anchorMapMd = $derived(
    sections.length && mdBasisText ? resolveAnchorMap(mdBasisText, sections, { trustBE: true }).anchors : {},
  );
  let anchorMapExtracted = $derived(
    sections.length && extractedBasisText ? resolveAnchorMap(extractedBasisText, sections, { trustBE: false }).anchors : {},
  );
  let showRail = $derived(outlineSections.length > 0 && !!mdRenderText);

  let scrollEl = $state();
  let activeKey = $state(null);
  function jumpTo(chunkId) {
    const el = scrollEl?.querySelector(`#sec-${chunkId}`);
    if (el) el.scrollIntoView({ block: 'start', behavior: 'smooth' });
  }
  // scroll-spy: scrollEl 내 .md-anchor 중 컨테이너 상단(+120) 지난 마지막 = 현재 절.
  $effect(() => {
    void anchorMapMd;
    void anchorMapExtracted;
    const el = scrollEl;
    if (!el) return;
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = 0;
        const threshold = el.getBoundingClientRect().top + 120;
        let cur = null;
        el.querySelectorAll('.md-anchor').forEach((a) => {
          if (a.getBoundingClientRect().top <= threshold) cur = a;
        });
        if (cur) {
          const m = cur.id.match(/^sec-(\d+)$/);
          if (m) activeKey = Number(m[1]);
        }
      });
    };
    el.addEventListener('scroll', onScroll, { passive: true });
    const t = setTimeout(onScroll, 0);
    return () => {
      el.removeEventListener('scroll', onScroll);
      clearTimeout(t);
      if (raf) cancelAnimationFrame(raf);
    };
  });

  function startEdit() {
    editContent = fullDoc?.extracted_text || rawMarkdown || '';
    editMode = true;
    editTab = 'edit';
  }

  async function saveContent() {
    saving = true;
    try {
      await api(`/documents/${fullDoc.id}/content`, {
        method: 'PUT',
        body: JSON.stringify({ content: editContent }),
      });
      fullDoc.extracted_text = editContent;
      editMode = false;
      addToast('success', '저장됨');
    } catch (err) {
      addToast('error', '저장 실패');
    } finally {
      saving = false;
    }
  }

  function handleKeydown(e) {
    if ((e.metaKey || e.ctrlKey) && e.key === 's' && editMode) {
      e.preventDefault();
      saveContent();
    }
  }

  let editInfo = $derived(fullDoc ? getEditInfo(fullDoc) : null);
  const PROSE = 'prose prose-invert prose-base max-w-none';
</script>

<svelte:window on:keydown={handleKeydown} />

<div class="h-full flex flex-col bg-surface border-t border-default">
  <!-- 뷰어 툴바 -->
  {#if fullDoc && !loading}
    <div class="flex items-center justify-between px-3 py-1.5 border-b border-default bg-sidebar shrink-0">
      <span class="text-xs text-dim truncate">{fullDoc.title || '제목 없음'}</span>
      <div class="flex items-center gap-2">
        {#if viewerType === 'markdown'}
          {#if editMode}
            <button onclick={saveContent} disabled={saving}
              class="flex items-center gap-1 px-2 py-1 text-xs bg-accent text-white rounded hover:bg-accent-hover disabled:opacity-50">
              <Save size={12} /> {saving ? '저장 중...' : '저장'}
            </button>
            <button onclick={() => editMode = false} class="px-2 py-1 text-xs text-dim hover:text-text">취소</button>
          {:else}
            <button onclick={startEdit} class="px-2 py-1 text-xs text-dim hover:text-accent border border-default rounded">편집</button>
          {/if}
        {/if}
        {#if editInfo}
          <a href={editInfo.url} target="_blank" rel="noopener"
            class="flex items-center gap-1 px-2 py-1 text-xs text-dim hover:text-accent border border-default rounded">
            <ExternalLink size={12} /> {editInfo.label}
          </a>
        {/if}
        <a href="/documents/{fullDoc.id}" class="px-2 py-1 text-xs text-dim hover:text-accent border border-default rounded">전체 보기</a>
      </div>
    </div>
  {/if}

  <!-- 뷰어 본문 (+ 절 목차 rail) -->
  <div class="flex-1 flex min-h-0">
    {#if showRail}
      <aside class="hidden lg:block w-[176px] shrink-0 overflow-y-auto border-r border-default p-2 bg-sidebar">
        <SectionOutline sections={outlineSections} onJump={jumpTo} {activeKey} />
      </aside>
    {/if}
    <div class="flex-1 overflow-auto min-h-0" bind:this={scrollEl}>
    {#if loading}
      <div class="flex items-center justify-center h-full"><p class="text-sm text-dim">로딩 중...</p></div>
    {:else if fullDoc}
      {#if viewerType === 'markdown'}
        {#if editMode}
          <div class="flex flex-col h-full">
            <Tabs tabs={[{ id: 'edit', label: '편집' }, { id: 'preview', label: '미리보기' }]} bind:value={editTab} class="flex flex-col h-full">
              {#snippet children(activeId)}
                {#if activeId === 'edit'}
                  <textarea bind:value={editContent}
                    class="flex-1 w-full p-4 bg-bg text-text text-sm font-mono resize-none outline-none min-h-[300px]"
                    spellcheck="false" aria-label="마크다운 편집"></textarea>
                {:else}
                  <div class="flex-1 overflow-auto p-4 markdown-body">{@html renderMd(editContent)}</div>
                {/if}
              {/snippet}
            </Tabs>
          </div>
        {:else}
          <!-- md/txt = extracted_text 단일 필드(표시=편집), MarkdownDoc 로 앵커/KaTeX/이미지 렌더 -->
          <div class="p-4">
            <MarkdownDoc
              documentId={fullDoc.id}
              mdContent={null}
              mdStatus={fullDoc.md_status}
              mdExtractionError={fullDoc.md_extraction_error}
              mdExtractionQuality={fullDoc.md_extraction_quality}
              anchorMap={anchorMapExtracted}
              extractedText={fullDoc.extracted_text || rawMarkdown}
              class={PROSE}
            />
          </div>
        {/if}
      {:else if viewerType === 'pdf'}
        <div class="p-4">
          <div class="mb-2 flex items-center gap-2">
            <MarkdownStatusBadge mdStatus={fullDoc.md_status} mdExtractionError={fullDoc.md_extraction_error} mdExtractionQuality={fullDoc.md_extraction_quality} />
            {#if canShowMarkdown}
              <button onclick={() => (pdfViewMode = 'markdown')}
                class="px-2 py-1 text-xs rounded border {pdfViewMode === 'markdown' ? 'bg-accent text-white border-accent' : 'text-dim border-default hover:text-accent'}">Markdown</button>
              <button onclick={() => (pdfViewMode = 'pdf')}
                class="px-2 py-1 text-xs rounded border {pdfViewMode === 'pdf' ? 'bg-accent text-white border-accent' : 'text-dim border-default hover:text-accent'}">PDF 원본</button>
            {/if}
          </div>
          {#if pdfViewMode === 'markdown' && canShowMarkdown}
            <MarkdownDoc
              documentId={fullDoc.id}
              mdContent={fullDoc.md_content}
              mdFrontmatter={fullDoc.md_frontmatter}
              mdStatus={fullDoc.md_status}
              mdExtractionError={fullDoc.md_extraction_error}
              mdExtractionQuality={fullDoc.md_extraction_quality}
              anchorMap={anchorMapMd}
              extractedText={fullDoc.extracted_text}
              class={PROSE}
            />
          {:else}
            <iframe src="/api/documents/{fullDoc.id}/file?token={getAccessToken()}" class="w-full h-[80vh] border-0 rounded" title={fullDoc.title}></iframe>
          {/if}
        </div>
      {:else if viewerType === 'hwp-markdown'}
        <div class="p-4">
          <MarkdownDoc
            documentId={fullDoc.id}
            mdContent={fullDoc.md_content}
            mdFrontmatter={fullDoc.md_frontmatter}
            mdStatus={fullDoc.md_status}
            mdExtractionError={fullDoc.md_extraction_error}
            mdExtractionQuality={fullDoc.md_extraction_quality}
            extractedText={fullDoc.extracted_text}
            class={PROSE}
          />
        </div>
      {:else if viewerType === 'preview-pdf'}
        <iframe src="/api/documents/{fullDoc.id}/preview?token={getAccessToken()}" class="w-full h-full border-0" title={fullDoc.title} onerror={() => {}}></iframe>
      {:else if viewerType === 'image'}
        <div class="flex items-center justify-center h-full p-4">
          <img src="/api/documents/{fullDoc.id}/file?token={getAccessToken()}" alt={fullDoc.title} class="max-w-full max-h-full object-contain rounded" />
        </div>
      {:else if viewerType === 'text'}
        <div class="p-4"><pre class="text-sm text-text whitespace-pre-wrap font-mono">{fullDoc.extracted_text || '텍스트 없음'}</pre></div>
      {:else if viewerType === 'synology'}
        <div class="flex flex-col items-center justify-center h-full gap-3">
          <p class="text-sm text-dim">Synology Office 문서 — 외부 편집기에서 열어야 합니다.</p>
          <a href={fullDoc.edit_url || 'https://link.hyungi.net'} target="_blank" rel="noopener"
            class="flex items-center gap-1 px-3 py-1.5 text-sm bg-accent text-white rounded-lg hover:bg-accent-hover">
            <ExternalLink size={14} /> 새 창에서 열기
          </a>
        </div>
      {:else if viewerType === 'cad'}
        <div class="flex flex-col items-center justify-center h-full gap-3">
          <p class="text-sm text-dim">CAD 미리보기 (향후 지원 예정)</p>
          <a href="https://web.autocad.com" target="_blank" rel="noopener" class="px-3 py-1.5 text-sm bg-accent text-white rounded hover:bg-accent-hover">AutoCAD Web에서 열기</a>
        </div>
      {:else if viewerType === 'article'}
        <div class="p-5 max-w-3xl mx-auto">
          <h1 class="text-lg font-bold mb-2 text-text">{fullDoc.title}</h1>
          <div class="flex items-center gap-2 mb-4 text-xs text-dim">
            {#if fullDoc.ai_tags?.length}
              {#each fullDoc.ai_tags.filter(t => t.startsWith('News/')) as tag}
                <span class="px-1.5 py-0.5 rounded bg-accent/15 text-accent-hover">{tag.replace('News/', '')}</span>
              {/each}
            {/if}
            <span>{new Date(fullDoc.created_at).toLocaleDateString('ko-KR', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}</span>
          </div>
          <MarkdownDoc
            documentId={fullDoc.id}
            mdContent={fullDoc.md_content}
            mdStatus={fullDoc.md_status}
            mdExtractionError={fullDoc.md_extraction_error}
            mdExtractionQuality={fullDoc.md_extraction_quality}
            extractedText={fullDoc.extracted_text}
            class="{PROSE} mb-6"
          />
          {#if fullDoc.edit_url}
            <div class="flex items-center gap-3 pt-4 border-t border-default">
              <a href={fullDoc.edit_url} target="_blank" rel="noopener noreferrer"
                class="flex items-center gap-1 px-3 py-1.5 text-sm bg-accent text-white rounded-lg hover:bg-accent-hover">
                <ExternalLink size={14} /> 원문 보기
              </a>
            </div>
          {/if}
        </div>
      {:else}
        <div class="flex items-center justify-center h-full"><p class="text-sm text-dim">미리보기를 지원하지 않는 형식입니다 ({fullDoc.file_format})</p></div>
      {/if}
    {/if}
    </div>
  </div>
</div>
