<script>
  import { onMount } from 'svelte';
  import { api } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import { renderMemoHtml, todayIso, countHiddenTasks, DEFAULT_HIDE_AFTER_MS } from '$lib/utils/memoRenderer';
  import { Pin, PinOff, Pencil, Trash2, Eye, EyeOff, X, Check, Archive, ArchiveRestore, ListChecks, Bold, Heading, CalendarDays, Mic, Calendar, Activity, ArrowRight, FileText, BookOpen } from 'lucide-svelte';
  import { getAccessToken } from '$lib/api';
  import Button from '$lib/components/ui/Button.svelte';
  import Card from '$lib/components/ui/Card.svelte';
  import EmptyState from '$lib/components/ui/EmptyState.svelte';
  import Skeleton from '$lib/components/ui/Skeleton.svelte';

  let memos = $state([]);
  let total = $state(0);
  let page = $state(1);
  let loading = $state(true);

  // 빠른 입력
  let newContent = $state('');
  let newTitle = $state('');
  let showTitle = $state(false);
  let submitting = $state(false);
  let inputRef = $state(null);

  // 인라인 편집
  let editingId = $state(null);
  let editContent = $state('');
  let editTitle = $state('');
  let saving = $state(false);

  // 필터
  let activeTag = $state(null);
  let showArchived = $state(false);

  // 자동 숨김 tick (1초 해상도) + 메모별 "숨겨진 항목 펼침" 상태
  let nowTick = $state(new Date());
  let showHiddenByMemo = $state({});

  $effect(() => {
    const id = setInterval(() => { nowTick = new Date(); }, 1000);
    return () => clearInterval(id);
  });

  function toggleShowHidden(memoId) {
    showHiddenByMemo = { ...showHiddenByMemo, [memoId]: !showHiddenByMemo[memoId] };
  }

  onMount(() => {
    const params = new URLSearchParams(window.location.search);
    activeTag = params.get('tag');
    loadMemos();
  });

  async function loadMemos() {
    loading = true;
    try {
      const tagParam = activeTag ? `&tag=${encodeURIComponent(activeTag)}` : '';
      const res = await api(`/memos/?page=${page}&page_size=20&archived=${showArchived}${tagParam}`);
      memos = res.items;
      total = res.total;
    } catch (err) {
      addToast('error', '메모 로딩 실패');
    } finally {
      loading = false;
    }
  }

  async function createMemo() {
    const content = newContent.trim();
    if (!content) return;
    submitting = true;
    try {
      const body = { content };
      if (newTitle.trim()) body.title = newTitle.trim();
      const memo = await api('/memos/', {
        method: 'POST',
        body: JSON.stringify(body),
      });
      memos = [memo, ...memos];
      total += 1;
      newContent = '';
      newTitle = '';
      showTitle = false;
      addToast('success', '메모 생성됨');
    } catch (err) {
      addToast('error', '메모 생성 실패');
    } finally {
      submitting = false;
    }
  }

  // ─── 툴바: textarea에 텍스트 삽입 ───
  function insertAtCursor(textarea, text) {
    if (!textarea) return;
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;
    const before = newContent.slice(0, start);
    const after = newContent.slice(end);

    // 줄 시작에 삽입해야 하는 경우
    const needsNewline = start > 0 && before[before.length - 1] !== '\n';
    const prefix = needsNewline ? '\n' : '';

    newContent = before + prefix + text + after;
    // 커서 위치 조정
    requestAnimationFrame(() => {
      const pos = start + prefix.length + text.length;
      textarea.focus();
      textarea.setSelectionRange(pos, pos);
    });
  }

  function addCheckbox() {
    const ta = document.querySelector('[data-memo-input]');
    insertAtCursor(ta, '- [ ] ');
  }

  function addHeading() {
    const ta = document.querySelector('[data-memo-input]');
    insertAtCursor(ta, '## ');
  }

  function addBold() {
    const ta = document.querySelector('[data-memo-input]');
    if (!ta) return;
    const start = ta.selectionStart;
    const end = ta.selectionEnd;
    const selected = newContent.slice(start, end);
    if (selected) {
      newContent = newContent.slice(0, start) + `**${selected}**` + newContent.slice(end);
      requestAnimationFrame(() => {
        ta.focus();
        ta.setSelectionRange(start + 2, end + 2);
      });
    } else {
      insertAtCursor(ta, '**텍스트**');
    }
  }

  function addDueDate() {
    const ta = document.querySelector('[data-memo-input]');
    if (!ta) return;
    const start = ta.selectionStart;
    const end = ta.selectionEnd;
    const ins = ` @${todayIso()}`;
    newContent = newContent.slice(0, start) + ins + newContent.slice(end);
    requestAnimationFrame(() => {
      const pos = start + ins.length;
      ta.focus();
      ta.setSelectionRange(pos, pos);
    });
  }

  // 편집 모드 툴바
  function editInsertAtCursor(text) {
    const ta = document.querySelector('[data-edit-input]');
    if (!ta) return;
    const start = ta.selectionStart;
    const end = ta.selectionEnd;
    const before = editContent.slice(0, start);
    const after = editContent.slice(end);
    const needsNewline = start > 0 && before[before.length - 1] !== '\n';
    const prefix = needsNewline ? '\n' : '';
    editContent = before + prefix + text + after;
    requestAnimationFrame(() => {
      const pos = start + prefix.length + text.length;
      ta.focus();
      ta.setSelectionRange(pos, pos);
    });
  }

  function startEdit(memo) {
    editingId = memo.id;
    editContent = memo.content || '';
    editTitle = memo.title || '';
  }

  function cancelEdit() {
    editingId = null;
    editContent = '';
    editTitle = '';
  }

  async function saveEdit(memoId) {
    saving = true;
    try {
      const body = { content: editContent };
      if (editTitle.trim()) body.title = editTitle.trim();
      const updated = await api(`/memos/${memoId}`, {
        method: 'PATCH',
        body: JSON.stringify(body),
      });
      memos = memos.map((m) => (m.id === memoId ? updated : m));
      editingId = null;
      addToast('success', '메모 수정됨');
    } catch (err) {
      addToast('error', '메모 수정 실패');
    } finally {
      saving = false;
    }
  }

  async function deleteMemo(memoId) {
    if (!confirm('이 메모를 삭제하시겠습니까?')) return;
    try {
      await api(`/memos/${memoId}`, { method: 'DELETE' });
      memos = memos.filter((m) => m.id !== memoId);
      total -= 1;
      addToast('success', '메모 삭제됨');
    } catch (err) {
      addToast('error', '메모 삭제 실패');
    }
  }

  async function togglePin(memoId) {
    try {
      const updated = await api(`/memos/${memoId}/pin`, { method: 'PATCH' });
      memos = memos.map((m) => (m.id === memoId ? updated : m));
      if (!showArchived) {
        memos = [...memos].sort((a, b) => {
          if (a.pinned !== b.pinned) return b.pinned ? 1 : -1;
          return new Date(b.created_at) - new Date(a.created_at);
        });
      }
    } catch (err) {
      addToast('error', '핀 변경 실패');
    }
  }

  async function setArchive(memoId, archived) {
    try {
      await api(`/memos/${memoId}/archive`, {
        method: 'PATCH',
        body: JSON.stringify({ archived }),
      });
      memos = memos.filter((m) => m.id !== memoId);
      total -= 1;
      addToast('success', archived ? '아카이브됨' : '복원됨');
    } catch (err) {
      addToast('error', archived ? '아카이브 실패' : '복원 실패');
    }
  }

  async function toggleAskIncludable(memoId) {
    try {
      const updated = await api(`/memos/${memoId}/ask-includable`, { method: 'PATCH' });
      memos = memos.map((m) => (m.id === memoId ? updated : m));
    } catch (err) {
      addToast('error', 'AI 포함 설정 변경 실패');
    }
  }

  // ─── PR-2B: 메모 → events 1-click promote ───

  async function promoteMemo(memoId, kind) {
    const labels = { task: '할 일', calendar_event: '일정', activity_log: '활동 기록' };
    try {
      const res = await api(`/memos/${memoId}/promote-to-event`, {
        method: 'POST',
        body: JSON.stringify({ kind }),
      });
      addToast('success', `${labels[kind]} 로 승급 (events #${res.event_id})`);
      // 로컬 상태 갱신 — promoted 표시를 위해 메모에 임시 마킹 (서버 미반영, UX 힌트만)
      memos = memos.map((m) => m.id === memoId ? { ...m, _last_promoted: { event_id: res.event_id, kind } } : m);
    } catch (err) {
      addToast('error', err?.detail || '승급 실패');
    }
  }

  async function dismissEventSuggestion(memoId) {
    try {
      const updated = await api(`/memos/${memoId}/dismiss-event-suggestion`, { method: 'POST' });
      memos = memos.map((m) => (m.id === memoId ? updated : m));
    } catch (err) {
      addToast('error', '처리 실패');
    }
  }

  // voice 메모 audio URL — /api/documents/{id}/file?token= 패턴 재사용
  function voiceAudioUrl(memoId) {
    const token = getAccessToken();
    return `/api/documents/${memoId}/file?token=${encodeURIComponent(token ?? '')}`;
  }

  // ai_event_kind 별 라벨 / 색상
  const KIND_LABELS = {
    note: '메모',
    task: '할 일',
    calendar_event: '일정',
    activity_log: '활동',
    reference: '참조',
  };
  const KIND_BADGE_CLASS = {
    note: 'bg-surface text-dim',
    task: 'bg-accent/15 text-accent-hover',
    calendar_event: 'bg-domain-engineering/15 text-domain-engineering',
    activity_log: 'bg-success/15 text-success',
    reference: 'bg-domain-reference/15 text-domain-reference',
  };

  async function handleCheckboxClick(e, memo) {
    const target = e.target;
    if (target.tagName !== 'INPUT' || target.type !== 'checkbox') return;
    e.preventDefault();
    const taskIndex = parseInt(target.dataset.taskIndex, 10);
    if (isNaN(taskIndex)) return;

    const checked = target.checked;
    try {
      const updated = await api(`/memos/${memo.id}/tasks/${taskIndex}`, {
        method: 'PATCH',
        body: JSON.stringify({ checked }),
      });
      memos = memos.map((m) => (m.id === memo.id ? updated : m));
    } catch (err) {
      target.checked = !checked; // 롤백
      addToast('error', '체크박스 변경 실패');
    }
  }

  function clearTag() {
    activeTag = null;
    history.replaceState(null, '', '/memos');
    loadMemos();
  }

  function filterByTag(tag) {
    activeTag = tag;
    page = 1;
    history.replaceState(null, '', `/memos?tag=${encodeURIComponent(tag)}`);
    loadMemos();
  }

  function toggleArchiveView() {
    showArchived = !showArchived;
    page = 1;
    loadMemos();
  }

  function handleKeydown(e) {
    if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      createMemo();
    }
  }

  function handleEditKeydown(e, memoId) {
    if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      saveEdit(memoId);
    }
    if (e.key === 'Escape') { cancelEdit(); }
  }

  function formatTime(dateStr) {
    const d = new Date(dateStr);
    const now = new Date();
    const diff = now - d;
    if (diff < 60000) return '방금';
    if (diff < 3600000) return `${Math.floor(diff / 60000)}분 전`;
    if (diff < 86400000) return `${Math.floor(diff / 3600000)}시간 전`;
    if (diff < 604800000) return `${Math.floor(diff / 86400000)}일 전`;
    return d.toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' });
  }
</script>

<svelte:head>
  <title>메모 — Document Server</title>
</svelte:head>

<div class="max-w-3xl mx-auto px-4 py-6">
  <!-- 헤더 -->
  <div class="flex items-center justify-between mb-4">
    <h1 class="text-xl font-bold text-text">메모</h1>
    <div class="flex items-center gap-3">
      <button
        onclick={toggleArchiveView}
        class="text-xs flex items-center gap-1 px-2 py-1 rounded transition-colors
          {showArchived ? 'bg-accent/15 text-accent' : 'text-dim hover:text-text hover:bg-surface'}"
      >
        <Archive size={12} />
        아카이브
      </button>
      {#if total > 0}
        <span class="text-sm text-dim">{total}개</span>
      {/if}
    </div>
  </div>

  <!-- 태그 필터 -->
  {#if activeTag}
    <div class="flex items-center gap-2 mb-3">
      <span class="text-sm text-dim">필터:</span>
      <button
        onclick={clearTag}
        class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs bg-accent/15 text-accent hover:bg-accent/25 transition-colors"
      >
        #{activeTag} <X size={12} />
      </button>
    </div>
  {/if}

  <!-- ═══ 빠른 입력 (상단 고정) ═══ -->
  {#if !showArchived}
    <Card class="mb-5 sticky top-0 z-10 shadow-sm">
      <!-- 선택적 제목 -->
      {#if showTitle}
        <input
          type="text"
          bind:value={newTitle}
          placeholder="제목 (선택)"
          class="w-full bg-transparent text-text text-sm font-medium outline-none placeholder:text-dim mb-2 pb-2 border-b border-default/50"
        />
      {/if}

      <textarea
        data-memo-input
        bind:value={newContent}
        onkeydown={handleKeydown}
        placeholder="메모 입력... (Ctrl+Enter 저장)"
        class="w-full h-20 bg-transparent text-text text-sm resize-none outline-none placeholder:text-dim"
      ></textarea>

      <!-- 툴바 + 저장 -->
      <div class="flex items-center justify-between mt-1.5 pt-1.5 border-t border-default/30">
        <div class="flex items-center gap-0.5">
          <button onclick={addCheckbox} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="체크리스트">
            <ListChecks size={16} />
          </button>
          <button onclick={addBold} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="굵게">
            <Bold size={16} />
          </button>
          <button onclick={addHeading} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="제목">
            <Heading size={16} />
          </button>
          <button onclick={addDueDate} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="마감일">
            <CalendarDays size={16} />
          </button>
          <span class="w-px h-4 bg-default/50 mx-1"></span>
          <button
            onclick={() => (showTitle = !showTitle)}
            class="px-1.5 py-1 rounded text-[11px] transition-colors
              {showTitle ? 'text-accent bg-accent/10' : 'text-dim hover:text-text hover:bg-surface'}"
            title="제목 추가"
          >
            제목
          </button>
        </div>
        <Button
          variant="primary"
          size="sm"
          loading={submitting}
          disabled={!newContent.trim()}
          onclick={createMemo}
        >
          저장
        </Button>
      </div>
    </Card>
  {/if}

  <!-- ═══ 메모 피드 ═══ -->
  {#if loading}
    {#each Array(3) as _}
      <div class="mb-3"><Skeleton class="h-24 w-full rounded-card" /></div>
    {/each}
  {:else if memos.length === 0}
    <EmptyState>
      {#if showArchived}
        <p>아카이브된 메모가 없습니다</p>
      {:else if activeTag}
        <p>#{activeTag} 태그의 메모가 없습니다</p>
      {:else}
        <p>아직 메모가 없습니다</p>
        <p class="text-dim text-sm mt-1">위 입력창에서 첫 메모를 작성해보세요</p>
      {/if}
    </EmptyState>
  {:else}
    <div class="space-y-2.5">
      {#each memos as memo (memo.id)}
        <Card padded={false} class="group relative {showArchived ? 'opacity-70' : ''}">
          {#if memo.pinned && !showArchived}
            <div class="absolute top-2 right-2">
              <span class="text-xs text-accent"><Pin size={12} /></span>
            </div>
          {/if}

          <div class="px-4 py-3">
            {#if editingId === memo.id}
              <!-- ═══ 인라인 편집 모드 ═══ -->
              <input
                type="text"
                bind:value={editTitle}
                placeholder="제목 (선택)"
                class="w-full bg-transparent text-text text-sm font-medium outline-none placeholder:text-dim mb-2 pb-1 border-b border-default/50"
              />
              <textarea
                data-edit-input
                bind:value={editContent}
                onkeydown={(e) => handleEditKeydown(e, memo.id)}
                class="w-full h-32 bg-bg border border-default rounded-md px-3 py-2 text-sm text-text resize-none outline-none focus:border-accent"
                placeholder="메모 내용..."
              ></textarea>
              <!-- 편집 툴바 -->
              <div class="flex items-center justify-between mt-2">
                <div class="flex items-center gap-0.5">
                  <button onclick={() => editInsertAtCursor('- [ ] ')} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="체크리스트">
                    <ListChecks size={15} />
                  </button>
                  <button onclick={() => editInsertAtCursor('**텍스트**')} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="굵게">
                    <Bold size={15} />
                  </button>
                  <button onclick={() => editInsertAtCursor(` @${todayIso()}`)} class="p-1.5 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="마감일">
                    <CalendarDays size={15} />
                  </button>
                </div>
                <div class="flex items-center gap-1.5">
                  <span class="text-[11px] text-dim">Ctrl+Enter / Esc</span>
                  <Button variant="ghost" size="sm" icon={X} onclick={cancelEdit}>취소</Button>
                  <Button variant="primary" size="sm" icon={Check} loading={saving} onclick={() => saveEdit(memo.id)}>저장</Button>
                </div>
              </div>
            {:else}
              <!-- ═══ 읽기 모드 ═══ -->
              <!-- PR-2B/2C: 분류 배지 + voice icon + 마지막 promote 결과 -->
              {#if memo.source_channel === 'voice' || memo.ai_event_kind || memo._last_promoted}
                <div class="flex flex-wrap items-center gap-1.5 mb-1.5">
                  {#if memo.source_channel === 'voice'}
                    <span class="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] bg-domain-philosophy/15 text-domain-philosophy" title="음성 메모">
                      <Mic size={10} /> 음성
                    </span>
                  {/if}
                  {#if memo.ai_event_kind && memo.ai_event_kind !== 'note'}
                    <span class="inline-flex items-center rounded px-1.5 py-0.5 text-[10px] {KIND_BADGE_CLASS[memo.ai_event_kind] || 'bg-surface text-dim'}">
                      AI 추천: {KIND_LABELS[memo.ai_event_kind] || memo.ai_event_kind}{memo.ai_event_confidence != null ? ` · ${Math.round(memo.ai_event_confidence * 100)}%` : ''}
                    </span>
                  {/if}
                  {#if memo._last_promoted}
                    <a href={`/events/${memo._last_promoted.event_id}`} class="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] bg-success/15 text-success hover:bg-success/25">
                      <ArrowRight size={10} /> events #{memo._last_promoted.event_id}
                    </a>
                  {/if}
                </div>
              {/if}

              {#if memo.title && memo.title !== memo.content?.split('\n')[0]?.replace(/^#+\s*/, '').slice(0, 80)}
                <p class="text-xs font-semibold text-dim mb-1">{memo.title}</p>
              {/if}

              <!-- voice 메모 audio player -->
              {#if memo.source_channel === 'voice' && memo.file_path}
                <audio controls preload="metadata" src={voiceAudioUrl(memo.id)} class="w-full mb-2 h-9"></audio>
              {/if}

              <!-- svelte-ignore a11y_click_events_have_key_events -->
              <!-- svelte-ignore a11y_no_static_element_interactions -->
              <div
                class="prose prose-sm text-text max-w-none memo-content"
                class:show-hidden={showHiddenByMemo[memo.id]}
                onclick={(e) => handleCheckboxClick(e, memo)}
              >
                {#if memo.content}
                  {@html renderMemoHtml(memo.content || '', {
                    taskStates: memo.memo_task_state ?? {},
                    now: nowTick,
                  })}
                {:else if memo.source_channel === 'voice'}
                  <p class="text-xs text-dim italic">음성 → 텍스트 변환 대기 중…</p>
                {/if}
              </div>
              {#if countHiddenTasks(memo.memo_task_state, nowTick, DEFAULT_HIDE_AFTER_MS) > 0 || showHiddenByMemo[memo.id]}
                <button
                  type="button"
                  class="text-[11px] text-dim hover:text-text underline-offset-2 hover:underline mt-1"
                  onclick={() => toggleShowHidden(memo.id)}
                >
                  {#if showHiddenByMemo[memo.id]}
                    완료 항목 숨기기
                  {:else}
                    완료 {countHiddenTasks(memo.memo_task_state, nowTick, DEFAULT_HIDE_AFTER_MS)}개 보기
                  {/if}
                </button>
              {/if}
            {/if}

            <!-- PR-2B: AI triage 결과 → 1-click promote 버튼 (분류 결과 있고 dismissed 아닌 메모) -->
            {#if editingId !== memo.id && memo.ai_event_kind && memo.ai_event_kind !== 'note' && !memo._last_promoted && !showArchived}
              <div class="flex flex-wrap gap-1 mt-2 pt-2 border-t border-default/30">
                <button onclick={() => promoteMemo(memo.id, 'task')} class={`inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors ${memo.ai_event_kind === 'task' ? 'bg-accent text-white hover:bg-accent-hover' : 'bg-surface text-dim hover:bg-surface-hover hover:text-text'}`}>
                  <FileText size={11} /> 할 일로
                </button>
                <button onclick={() => promoteMemo(memo.id, 'calendar_event')} class={`inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors ${memo.ai_event_kind === 'calendar_event' ? 'bg-domain-engineering text-white hover:opacity-90' : 'bg-surface text-dim hover:bg-surface-hover hover:text-text'}`}>
                  <Calendar size={11} /> 일정으로
                </button>
                <button onclick={() => promoteMemo(memo.id, 'activity_log')} class={`inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors ${memo.ai_event_kind === 'activity_log' ? 'bg-success text-white hover:opacity-90' : 'bg-surface text-dim hover:bg-surface-hover hover:text-text'}`}>
                  <Activity size={11} /> 활동으로
                </button>
                <button onclick={() => dismissEventSuggestion(memo.id)} class="inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] bg-surface text-dim hover:bg-surface-hover hover:text-text transition-colors">
                  <X size={11} /> 그냥 메모
                </button>
              </div>
            {/if}

            <!-- 태그 + 하단 -->
            {#if editingId !== memo.id}
              {#if memo.user_tags?.length || memo.ai_tags?.length}
                <div class="flex flex-wrap gap-1 mt-2">
                  {#each memo.user_tags || [] as tag}
                    <button onclick={() => filterByTag(tag)} class="px-1.5 py-0.5 rounded text-[11px] bg-accent/10 text-accent hover:bg-accent/20 transition-colors">#{tag}</button>
                  {/each}
                  {#each memo.ai_tags || [] as tag}
                    <button onclick={() => filterByTag(tag)} class="px-1.5 py-0.5 rounded text-[11px] bg-surface text-dim hover:bg-surface-hover transition-colors">{tag}</button>
                  {/each}
                </div>
              {/if}

              <div class="flex items-center justify-between mt-2 pt-1.5 border-t border-default/50">
                <div class="flex items-center gap-2">
                  <span class="text-[11px] text-dim">{formatTime(memo.created_at)}</span>
                  {#if !memo.ask_includable}
                    <span class="text-[10px] text-dim/50 flex items-center gap-0.5"><EyeOff size={10} /> AI 제외</span>
                  {/if}
                </div>
                <div class="flex items-center gap-0.5 md:opacity-0 md:group-hover:opacity-100 transition-opacity">
                  {#if !showArchived}
                    <button onclick={() => togglePin(memo.id)} class="p-1 rounded text-dim hover:text-accent hover:bg-surface transition-colors" title={memo.pinned ? '핀 해제' : '핀 고정'}>
                      {#if memo.pinned}<PinOff size={13} />{:else}<Pin size={13} />{/if}
                    </button>
                  {/if}
                  <button onclick={() => toggleAskIncludable(memo.id)} class="p-1 rounded text-dim hover:text-text hover:bg-surface transition-colors" title={memo.ask_includable ? 'AI 답변에서 제외' : 'AI 답변에 포함'}>
                    {#if memo.ask_includable}<Eye size={13} />{:else}<EyeOff size={13} />{/if}
                  </button>
                  {#if !showArchived}
                    <button onclick={() => startEdit(memo)} class="p-1 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="편집"><Pencil size={13} /></button>
                    <button onclick={() => setArchive(memo.id, true)} class="p-1 rounded text-dim hover:text-text hover:bg-surface transition-colors" title="아카이브"><Archive size={13} /></button>
                  {:else}
                    <button onclick={() => setArchive(memo.id, false)} class="p-1 rounded text-dim hover:text-accent hover:bg-surface transition-colors" title="복원"><ArchiveRestore size={13} /></button>
                  {/if}
                  <button onclick={() => deleteMemo(memo.id)} class="p-1 rounded text-dim hover:text-error hover:bg-error/10 transition-colors" title="삭제"><Trash2 size={13} /></button>
                </div>
              </div>
            {/if}
          </div>
        </Card>
      {/each}
    </div>

    {#if total > 20}
      <div class="flex justify-center gap-2 mt-6">
        <Button variant="ghost" size="sm" disabled={page <= 1} onclick={() => { page -= 1; loadMemos(); }}>이전</Button>
        <span class="text-sm text-dim self-center">{page} / {Math.ceil(total / 20)}</span>
        <Button variant="ghost" size="sm" disabled={page * 20 >= total} onclick={() => { page += 1; loadMemos(); }}>다음</Button>
      </div>
    {/if}
  {/if}
</div>

<style>
  .memo-content { overflow-wrap: anywhere; word-break: break-word; }
  .memo-content :global(p) { margin: 0.2em 0; }
  .memo-content :global(ul), .memo-content :global(ol) { margin: 0.2em 0; padding-left: 1.5em; }
  .memo-content :global(li) { margin: 0.1em 0; }
  .memo-content :global(code) { background: var(--bg); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.85em; overflow-wrap: anywhere; word-break: break-word; }
  .memo-content :global(pre) { background: var(--bg); padding: 0.75em; border-radius: 6px; overflow-x: auto; margin: 0.5em 0; }
  .memo-content :global(table) { display: block; overflow-x: auto; max-width: 100%; }
  .memo-content :global(a) { color: var(--accent); overflow-wrap: anywhere; word-break: break-word; }
  .memo-content :global(blockquote) { border-left: 3px solid var(--border-default); padding-left: 0.75em; color: var(--text-dim); margin: 0.5em 0; }
  .memo-content :global(.memo-checkbox) {
    cursor: pointer;
    width: 15px;
    height: 15px;
    accent-color: var(--accent);
    vertical-align: middle;
    margin-right: 4px;
  }
  .memo-content :global(li:has(.memo-checkbox)) { list-style: none; margin-left: -1.5em; }
  .memo-content :global(.memo-task-done) { opacity: 0.5; text-decoration: line-through; }
  /* 체크 후 10초 경과 항목 자동 숨김 (.show-hidden 클래스로 해제) */
  .memo-content :global(.memo-task-hidden) { display: none; }
  .memo-content.show-hidden :global(.memo-task-hidden) { display: list-item; }
  .memo-content :global(.due-badge) { display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 8px; margin-left: 4px; vertical-align: middle; }
  .memo-content :global(.due-overdue) { background: rgba(245, 86, 78, 0.15); color: var(--error); }
  .memo-content :global(.due-soon) { background: rgba(251, 191, 36, 0.15); color: var(--warning); }
  .memo-content :global(.due-normal) { background: var(--surface); color: var(--text-dim); }
  .memo-content :global(.due-done) { background: var(--surface); color: var(--text-dim); opacity: 0.6; }
</style>
