import React, { useEffect, useMemo, useRef, useState, Fragment } from 'react';
import { Dialog, Transition } from '@headlessui/react';
import {
  Plus, Upload, Link as LinkIcon, FileText, Files, Search, Trash2, MoreVertical,
  CheckCircle2, Circle, ChevronRight, ChevronDown, Send, Copy, ThumbsUp, ThumbsDown,
  RefreshCw, Notebook, Bold, Italic, Underline, List, ListOrdered, Sparkles, X, Edit3
} from 'lucide-react';

function NotebookLMFrontend() {
  // -----------------------------
  // Types (JSDoc for clarity)
  // -----------------------------
  /**
   * @typedef {{ id: string; title: string; type: 'text'|'url'|'pdf'|'gdoc'; content: string; selected: boolean; }} Source
   * @typedef {{ num: number; sourceId: string; quote: string; }} Citation
   * @typedef {{ id: string; role: 'user'|'ai'; content: string; citations?: Citation[]; suggestions?: string[]; liked?: boolean; disliked?: boolean; }} ChatMessage
   */

  // -----------------------------
  // Initial mock data from public post (paraphrased)
  // -----------------------------
  const initialSources = /** @type {Source[]} */ ([
    {
      id: 's1',
      title: 'Introducing NotebookLM (Google Keyword, 2023)',
      type: 'url',
      content:
        "NotebookLM is an experimental, AI-first notebook by Google Labs (formerly Project Tailwind). It grounds a language model in your chosen sources to help summarize, explain, and brainstorm. It supports adding Google Docs now and will add more formats. Each response includes citations back to your sources, and your files/conversations are private and not used to train new models.",
      selected: true,
    },
    {
      id: 's2',
      title: 'Core interactions & safety',
      type: 'text',
      content:
        "When you add a source, NotebookLM can auto-summarize and propose key topics and questions. You can ask deeper questions, create glossaries, and generate creative ideas like scripts or investor Q&A. Source-grounding reduces hallucinations, and answers include citations for easy fact checking. Built by Google Labs with user feedback and strict safety criteria aligned with AI Principles.",
      selected: true,
    },
    {
      id: 's3',
      title: 'Use cases & workflow',
      type: 'text',
      content:
        "Example use cases: A medical student creates a dopamine glossary from a neuroscience article. An author summarizes Houdini and Conan Doyle interactions. A creator drafts a short video script. An entrepreneur asks for expected investor questions. The system is rolling out as an experiment in the U.S. with a waitlist.",
      selected: true,
    },
  ]);

  // -----------------------------
  // App State
  // -----------------------------
  const [notebookTitle, setNotebookTitle] = useState('My Research Notebook');
  const [sources, setSources] = useState(initialSources);
  const [messages, setMessages] = useState(/** @type {ChatMessage[]} */([]));
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const [openAddSource, setOpenAddSource] = useState(false);
  const [addMode, setAddMode] = useState('text'); // 'text'|'url'|'file'
  const [newSourceTitle, setNewSourceTitle] = useState('');
  const [newSourceText, setNewSourceText] = useState('');
  const [newSourceUrl, setNewSourceUrl] = useState('');
  const [fileError, setFileError] = useState('');
  const [renamingId, setRenamingId] = useState(null);
  const [renameText, setRenameText] = useState('');
  const [activeSourceViewId, setActiveSourceViewId] = useState(null);
  const [highlightedSourceId, setHighlightedSourceId] = useState(null);
  const [toolbarStatus, setToolbarStatus] = useState({ copying: false });
  const [caretAtEnd, setCaretAtEnd] = useState(true);

  // Notepad state (autosave in memory)
  const [notepadHtml, setNotepadHtml] = useState('<p class="mb-2">Ghi chú của bạn sẽ xuất hiện ở đây…</p>');
  const notepadRef = useRef(null);

  // Refs to source cards for scrolling/highlight on citation click
  const sourceRefs = useRef({}); // id -> element
  const setSourceRef = (id) => (el) => {
    if (el) sourceRefs.current[id] = el;
  };

  // -----------------------------
  // Derived
  // -----------------------------
  const selectedSources = sources.filter((s) => s.selected);
  const selectedCount = selectedSources.length;
  const totalWordCount = useMemo(() => {
    return selectedSources.reduce((acc, s) => acc + (s.content.trim().split(/\s+/).filter(Boolean).length || 0), 0);
  }, [selectedSources]);

  // -----------------------------
  // Utility: simplistic tokenizer & scorer for mock retrieval
  // -----------------------------
  const stopWords = new Set(['the','a','an','and','or','to','of','in','on','for','with','is','are','was','were','be','as','by','it','that','this','at','from','your','you']);
  const tokenize = (text) =>
    text
      .toLowerCase()
      .replace(/[^a-z0-9\s]/g, ' ')
      .split(/\s+/)
      .filter((t) => t && !stopWords.has(t));

  const scoreSourceRelevance = (question, source) => {
    const qTokens = new Set(tokenize(question));
    const sTokens = tokenize(source.content);
    let matches = 0;
    for (const t of sTokens) if (qTokens.has(t)) matches++;
    return matches / (sTokens.length + 1e-6);
  };

  const makeQuote = (source, question) => {
    // Return a short matching quote snippet
    const qTokens = new Set(tokenize(question));
    const sentences = source.content.split(/(?<=[.!?])\s+/);
    let best = sentences[0] || source.content.slice(0, 140);
    let bestScore = -1;
    for (const s of sentences) {
      const st = tokenize(s);
      const m = st.reduce((acc, t) => acc + (qTokens.has(t) ? 1 : 0), 0);
      if (m > bestScore) {
        bestScore = m;
        best = s;
      }
    }
    return best.length > 240 ? best.slice(0, 240) + '…' : best;
  };

  // -----------------------------
  // Fake RAG answer generator
  // -----------------------------
  const generateAIAnswer = async (question, activeSources) => {
    // Rank sources by relevance
    const ranked = activeSources
      .map((s) => ({ s, score: scoreSourceRelevance(question, s) }))
      .sort((a, b) => b.score - a.score);

    // Pick top K sources (2-3)
    const top = ranked.slice(0, Math.min(3, ranked.length)).map((r) => r.s);
    const citations = top.map((s, i) => ({
      num: i + 1,
      sourceId: s.id,
      quote: makeQuote(s, question),
    }));

    // Drafted answer referencing [1], [2], ...
    const bullets = [
      `NotebookLM là một sổ tay ưu tiên AI, “nối đất” vào nguồn bạn chọn để tóm tắt, giải thích, và gợi ý ý tưởng [1].`,
      `Mỗi câu trả lời kèm trích dẫn để bạn kiểm tra lại nguồn, giúp giảm “ảo giác” và tăng độ tin cậy [1][2].`,
      `Luồng sử dụng: thêm nguồn (Google Docs/tài liệu), đọc tóm tắt & chủ đề gợi ý, đặt câu hỏi sâu, và trích dẫn tự động [2][3].`,
    ];

    // Mix question keywords into an opening line
    const opening =
      question.trim().length > 0
        ? `Dựa trên nguồn đang chọn, đây là phần trả lời cho: “${question}”.`
        : `Dưới đây là tóm tắt nhanh theo nguồn đang chọn.`;

    const content =
      `${opening}\n\n` +
      bullets.map((b) => `• ${b}`).join('\n') +
      `\n\nGợi ý: Bạn có thể yêu cầu “tạo glossary”, “viết script ngắn”, hoặc “liệt kê câu hỏi nhà đầu tư thường hỏi” [2][3].`;

    // Suggested follow-ups
    const suggestions = [
      'Tạo danh mục thuật ngữ (glossary) cho chủ đề chính từ các nguồn đang chọn',
      'Liệt kê 5 câu hỏi tiếp theo để đào sâu “source-grounding” và trích dẫn',
      'Tóm tắt 3 ý chính và đề xuất 3 câu hỏi nghiên cứu mới',
      'Viết dàn ý (outline) cho một bài viết ngắn dựa trên nguồn',
    ];

    // Simulate latency
    await new Promise((r) => setTimeout(r, 600));

    return { content, citations, suggestions };
  };

  // -----------------------------
  // Chat handlers
  // -----------------------------
  const sendMessage = async (text) => {
    if (!text.trim() || sending) return;
    setSending(true);
    const q = text.trim();

    const userMsg = /** @type {ChatMessage} */ ({
      id: `m_${Date.now()}_u`,
      role: 'user',
      content: q,
    });
    setMessages((prev) => [...prev, userMsg]);

    try {
      const { content, citations, suggestions } = await generateAIAnswer(q, selectedSources);
      const aiMsg = /** @type {ChatMessage} */ ({
        id: `m_${Date.now()}_a`,
        role: 'ai',
        content,
        citations,
        suggestions,
      });
      setMessages((prev) => [...prev, aiMsg]);
    } catch (e) {
      const aiMsg = /** @type {ChatMessage} */ ({
        id: `m_${Date.now()}_a`,
        role: 'ai',
        content: 'Xin lỗi, đã có lỗi khi tạo câu trả lời. Vui lòng thử lại.',
      });
      setMessages((prev) => [...prev, aiMsg]);
    } finally {
      setSending(false);
      setInput('');
    }
  };

  const regenerateAnswer = async (aiMsg) => {
    if (sending) return;
    setSending(true);
    try {
      const lastUser = [...messages].reverse().find((m) => m.role === 'user');
      const q = lastUser ? lastUser.content : '';
      const { content, citations, suggestions } = await generateAIAnswer(q, selectedSources);
      const newAiMsg = { ...aiMsg, id: `m_${Date.now()}_a2`, content, citations, suggestions };
      setMessages((prev) => prev.map((m) => (m.id === aiMsg.id ? newAiMsg : m)));
    } finally {
      setSending(false);
    }
  };

  // -----------------------------
  // Citations: click to scroll/highlight
  // -----------------------------
  const onClickCitation = (citation) => {
    const id = citation.sourceId;
    setHighlightedSourceId(id);
    const el = sourceRefs.current[id];
    if (el && el.scrollIntoView) {
      el.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
    // Remove highlight after a moment
    setTimeout(() => setHighlightedSourceId(null), 1800);
  };

  // -----------------------------
  // Rendering helpers
  // -----------------------------
  const renderWithCitations = (msg) => {
    const parts = msg.content.split(/(\[\d+\])/g);
    return parts.map((p, idx) => {
      const match = p.match(/^\[(\d+)\]$/);
      if (!match) return <span key={idx}>{p}</span>;
      const num = Number(match[1]);
      const c = msg.citations?.find((ci) => ci.num === num);
      if (!c) return <span key={idx} className="text-indigo-600">[{num}]</span>;
      const source = sources.find((s) => s.id === c.sourceId);
      return (
        <button
          key={idx}
          className="text-indigo-600 hover:underline focus:outline-none"
          title={(source?.title || '') + (c.quote ? ` — “${c.quote}”` : '')}
          onClick={() => onClickCitation(c)}
        >
          [{num}]
        </button>
      );
    });
  };

  // -----------------------------
  // Notepad: Rich text controls
  // -----------------------------
  const exec = (cmd) => {
    document.execCommand(cmd, false, null);
    // sync state from DOM
    if (notepadRef.current) {
      setNotepadHtml(notepadRef.current.innerHTML);
    }
  };

  const insertHtmlAtCursor = (html) => {
    // place at caret or append to end
    const sel = window.getSelection();
    if (sel && sel.rangeCount > 0 && notepadRef.current && notepadRef.current.contains(sel.anchorNode)) {
      const range = sel.getRangeAt(0);
      range.deleteContents();
      const el = document.createElement('div');
      el.innerHTML = html;
      const frag = document.createDocumentFragment();
      let node, lastNode;
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      range.insertNode(frag);
      // move caret after inserted content
      if (lastNode) {
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    } else {
      // append
      if (notepadRef.current) {
        notepadRef.current.insertAdjacentHTML('beforeend', html);
      }
    }
    if (notepadRef.current) setNotepadHtml(notepadRef.current.innerHTML);
  };

  const addMessageToNotepad = (msg) => {
    const citationHtml =
      (msg.citations && msg.citations.length > 0)
        ? `<div class="mt-2 text-sm text-gray-500">${msg.citations.map(c => {
            const s = sources.find(ss => ss.id === c.sourceId);
            return `<span class="mr-2">[${c.num}] ${s ? s.title : c.sourceId}${c.quote ? ` — “${escapeHtml(c.quote)}”` : ''}</span>`;
          }).join(' ')}</div>`
        : '';
    const block =
      `<div class="mb-4"><div class="font-semibold mb-1">AI Answer</div><div>${escapeHtml(msg.content).replace(/\n/g,'<br/>')}</div>${citationHtml}</div>`;
    insertHtmlAtCursor(block);
  };

  const escapeHtml = (s) =>
    s.replace(/&/g, '&amp;')
     .replace(/</g, '&lt;')
     .replace(/>/g, '&gt;');

  // -----------------------------
  // Add Source modal
  // -----------------------------
  const resetAddForm = () => {
    setAddMode('text');
    setNewSourceTitle('');
    setNewSourceText('');
    setNewSourceUrl('');
    setFileError('');
  };

  const addSource = (src) => {
    setSources((prev) => [src, ...prev]);
  };

  const handleAddSource = () => {
    if (addMode === 'text') {
      const title = newSourceTitle.trim() || 'Untitled Text';
      const content = newSourceText.trim();
      if (!content) return;
      addSource({
        id: `s_${Date.now()}`,
        title,
        type: 'text',
        content,
        selected: true,
      });
      setOpenAddSource(false);
      resetAddForm();
    } else if (addMode === 'url') {
      const url = newSourceUrl.trim();
      if (!url) return;
      addSource({
        id: `s_${Date.now()}`,
        title: newSourceTitle.trim() || url,
        type: 'url',
        content: `URL: ${url}\n(Placeholder) Dán tóm tắt hoặc nội dung chính của trang này vào đây để “grounding”.`,
        selected: true,
      });
      setOpenAddSource(false);
      resetAddForm();
    }
  };

  const handleFile = async (file) => {
    setFileError('');
    if (!file) return;
    const ext = file.name.toLowerCase().split('.').pop();
    if (ext === 'txt') {
      const text = await file.text();
      addSource({
        id: `s_${Date.now()}`,
        title: newSourceTitle.trim() || file.name,
        type: 'text',
        content: text.slice(0, 20000),
        selected: true,
      });
      setOpenAddSource(false);
      resetAddForm();
    } else if (ext === 'pdf') {
      // No PDF parsing in frontend-only demo
      addSource({
        id: `s_${Date.now()}`,
        title: newSourceTitle.trim() || file.name,
        type: 'pdf',
        content: '(PDF) Demo frontend chưa parse nội dung PDF. Hãy dùng TXT/URL hoặc dán văn bản.',
        selected: true,
      });
      setOpenAddSource(false);
      resetAddForm();
    } else {
      setFileError('Định dạng không hỗ trợ trong demo. Vui lòng dùng .txt hoặc .pdf.');
    }
  };

  // -----------------------------
  // Source actions
  // -----------------------------
  const toggleSource = (id) => {
    setSources((prev) => prev.map((s) => (s.id === id ? { ...s, selected: !s.selected } : s)));
  };
  const removeSource = (id) => {
    setSources((prev) => prev.filter((s) => s.id !== id));
    if (activeSourceViewId === id) setActiveSourceViewId(null);
  };
  const startRename = (id, current) => {
    setRenamingId(id);
    setRenameText(current);
  };
  const commitRename = () => {
    setSources((prev) => prev.map((s) => (s.id === renamingId ? { ...s, title: renameText.trim() || s.title } : s)));
    setRenamingId(null);
    setRenameText('');
  };

  // -----------------------------
  // Source Preview (middle panel when clicking a source)
  // -----------------------------
  const getSourceSummary = (s) => {
    const words = s.content.split(/\s+/).filter(Boolean);
    const preview = words.slice(0, 70).join(' ');
    return preview + (words.length > 70 ? '…' : '');
    };
  const getSourceTopics = (s) => {
    const tokens = tokenize(s.content);
    const freq = {};
    tokens.forEach((t) => (freq[t] = (freq[t] || 0) + 1));
    const top = Object.entries(freq)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 6)
      .map(([w]) => w);
    return top;
  };

  // -----------------------------
  // Misc
  // -----------------------------
  const copyAnswer = async (msg) => {
    try {
      setToolbarStatus({ copying: true });
      await navigator.clipboard.writeText(msg.content);
    } finally {
      setTimeout(() => setToolbarStatus({ copying: false }), 600);
    }
  };

  const likeToggle = (msg) => {
    setMessages((prev) =>
      prev.map((m) => (m.id === msg.id ? { ...m, liked: !m.liked, disliked: false } : m))
    );
  };

  const dislikeToggle = (msg) => {
    setMessages((prev) =>
      prev.map((m) => (m.id === msg.id ? { ...m, disliked: !m.disliked, liked: false } : m))
    );
  };

  const onSuggestionClick = (text) => {
    setInput(text);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    sendMessage(input);
  };

  useEffect(() => {
    // place caret at end if requested
    if (notepadRef.current && caretAtEnd) {
      const range = document.createRange();
      range.selectNodeContents(notepadRef.current);
      range.collapse(false);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
    }
  }, [notepadRef, caretAtEnd]);

  // -----------------------------
  // UI
  // -----------------------------
  return (
    <div className="h-screen w-full bg-gray-50 text-gray-900">
      {/* Header */}
      <div className="h-14 border-b bg-white px-4 flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Notebook className="w-5 h-5 text-indigo-600" />
          <input
            className="text-sm font-semibold bg-transparent focus:outline-none px-2 py-1 rounded hover:bg-gray-100"
            value={notebookTitle}
            onChange={(e) => setNotebookTitle(e.target.value)}
            aria-label="Notebook title"
          />
        </div>
        <div className="text-xs text-gray-500">
          Demo Frontend — mô phỏng NotebookLM (không kết nối backend)
        </div>
      </div>

      {/* Body: 3 columns */}
      <div className="h-[calc(100vh-3.5rem)] flex">
        {/* Left: Sources */}
        <div className="w-80 border-r bg-white flex flex-col">
          <div className="p-3 border-b flex items-center justify-between">
            <div className="text-sm font-medium">Sources</div>
            <button
              className="inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-indigo-600 text-white hover:bg-indigo-700"
              onClick={() => setOpenAddSource(true)}
            >
              <Plus className="w-4 h-4" /> Add
            </button>
          </div>

          <div className="px-3 pt-2 pb-1 text-xs text-gray-600">
            {selectedCount}/25 sources selected • {totalWordCount} words
          </div>

          <div className="flex-1 overflow-y-auto">
            {sources.length === 0 ? (
              <div className="p-4 text-sm text-gray-500">Chưa có nguồn. Bấm “Add” để thêm.</div>
            ) : (
              <ul className="divide-y">
                {sources.map((s) => {
                  const isHighlighted = highlightedSourceId === s.id;
                  return (
                    <li
                      key={s.id}
                      ref={setSourceRef(s.id)}
                      className={`px-3 py-3 hover:bg-gray-50 ${isHighlighted ? 'bg-yellow-50 ring-2 ring-yellow-300' : ''}`}
                    >
                      <div className="flex items-start gap-2">
                        <button
                          onClick={() => toggleSource(s.id)}
                          className="mt-1"
                          aria-label={s.selected ? 'Deselect source' : 'Select source'}
                        >
                          {s.selected ? (
                            <CheckCircle2 className="w-5 h-5 text-indigo-600" />
                          ) : (
                            <Circle className="w-5 h-5 text-gray-400" />
                          )}
                        </button>

                        <div className="flex-1 min-w-0">
                          {renamingId === s.id ? (
                            <div className="flex items-center gap-2">
                              <input
                                className="text-sm border px-2 py-1 rounded w-full"
                                value={renameText}
                                onChange={(e) => setRenameText(e.target.value)}
                                onKeyDown={(e) => {
                                  if (e.key === 'Enter') commitRename();
                                  if (e.key === 'Escape') {
                                    setRenamingId(null);
                                    setRenameText('');
                                  }
                                }}
                                autoFocus
                              />
                              <button
                                className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200"
                                onClick={commitRename}
                              >
                                Lưu
                              </button>
                            </div>
                          ) : (
                            <button
                              className="text-sm font-medium text-left w-full hover:underline"
                              onClick={() => setActiveSourceViewId(s.id)}
                              title="Xem trước nguồn"
                            >
                              {s.title}
                            </button>
                          )}

                          <div className="text-xs text-gray-500 line-clamp-2 mt-1">
                            {s.content.slice(0, 100)}
                            {s.content.length > 100 ? '…' : ''}
                          </div>
                        </div>

                        <div className="relative">
                          <button className="px-1 py-1 rounded hover:bg-gray-100">
                            <MoreVertical className="w-4 h-4 text-gray-500" />
                          </button>
                          <div className="mt-1 flex gap-2">
                            <button
                              className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 inline-flex items-center gap-1"
                              onClick={() => startRename(s.id, s.title)}
                              title="Đổi tên"
                            >
                              <Edit3 className="w-3 h-3" /> Rename
                            </button>
                            <button
                              className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 inline-flex items-center gap-1"
                              onClick={() => removeSource(s.id)}
                              title="Xóa"
                            >
                              <Trash2 className="w-3 h-3" /> Remove
                            </button>
                          </div>
                        </div>
                      </div>
                    </li>
                  );
                })}
              </ul>
            )}
          </div>
        </div>

        {/* Middle: Chat or Source Preview */}
        <div className="flex-1 flex flex-col">
          <div className="h-10 border-b bg-white px-4 flex items-center justify-between">
            {activeSourceViewId ? (
              <div className="flex items-center gap-2 text-sm">
                <ChevronRight className="w-4 h-4 text-gray-400" />
                <span className="font-medium">Source preview</span>
                <span className="text-gray-500">
                  — {sources.find((s) => s.id === activeSourceViewId)?.title}
                </span>
              </div>
            ) : (
              <div className="text-sm text-gray-600">
                Answering from {selectedCount} source{selectedCount !== 1 ? 's' : ''}
              </div>
            )}
            <div className="text-xs text-gray-500">Inline citations • Suggested follow-ups • Toolbar</div>
          </div>

          <div className="flex-1 overflow-y-auto px-4 py-3">
            {activeSourceViewId ? (
              <SourcePreview
                source={sources.find((s) => s.id === activeSourceViewId)}
                onClose={() => setActiveSourceViewId(null)}
                getSummary={getSourceSummary}
                getTopics={getSourceTopics}
              />
            ) : (
              <div className="space-y-4">
                {messages.length === 0 ? (
                  <EmptyState selectedCount={selectedCount} />
                ) : (
                  messages.map((m) => (
                    <div key={m.id} className="flex items-start gap-3">
                      <div className="w-7 h-7 rounded-full bg-indigo-600 text-white flex items-center justify-center text-xs font-semibold">
                        {m.role === 'user' ? 'U' : 'AI'}
                      </div>
                      <div className="flex-1">
                        {m.role === 'ai' ? (
                          <div className="bg-white border rounded p-3">
                            <div className="prose prose-sm max-w-none">
                              <div className="whitespace-pre-wrap break-words">
                                {renderWithCitations(m)}
                              </div>
                            </div>
                            <div className="mt-2 flex items-center gap-2 text-xs text-gray-500">
                              {m.citations?.map((c) => {
                                const s = sources.find((ss) => ss.id === c.sourceId);
                                return (
                                  <button
                                    key={c.num}
                                    onClick={() => onClickCitation(c)}
                                    title={s?.title || ''}
                                    className="px-1.5 py-0.5 rounded bg-gray-100 hover:bg-gray-200"
                                  >
                                    [{c.num}] {s?.title || c.sourceId}
                                  </button>
                                );
                              })}
                            </div>
                            <div className="mt-2 flex items-center gap-2">
                              <button
                                className="inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200"
                                onClick={() => copyAnswer(m)}
                              >
                                <Copy className="w-3.5 h-3.5" />
                                {toolbarStatus.copying ? 'Copied' : 'Copy'}
                              </button>
                              <button
                                className="inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200"
                                onClick={() => addMessageToNotepad(m)}
                              >
                                <Files className="w-3.5 h-3.5" />
                                Add to notepad
                              </button>
                              <button
                                className={`inline-flex items-center gap-1 text-xs px-2 py-1 rounded ${m.liked ? 'bg-green-100' : 'bg-gray-100 hover:bg-gray-200'}`}
                                onClick={() => likeToggle(m)}
                              >
                                <ThumbsUp className="w-3.5 h-3.5" /> Like
                              </button>
                              <button
                                className={`inline-flex items-center gap-1 text-xs px-2 py-1 rounded ${m.disliked ? 'bg-red-100' : 'bg-gray-100 hover:bg-gray-200'}`}
                                onClick={() => dislikeToggle(m)}
                              >
                                <ThumbsDown className="w-3.5 h-3.5" /> Dislike
                              </button>
                              <button
                                className="inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200"
                                onClick={() => regenerateAnswer(m)}
                                disabled={sending}
                              >
                                <RefreshCw className={`w-3.5 h-3.5 ${sending ? 'animate-spin' : ''}`} />
                                Regenerate
                              </button>
                            </div>

                            {m.suggestions && m.suggestions.length > 0 && (
                              <div className="mt-3 border-t pt-2">
                                <div className="text-xs font-medium text-gray-600 mb-1">Suggested questions</div>
                                <div className="flex flex-wrap gap-2">
                                  {m.suggestions.map((sug, i) => (
                                    <button
                                      key={i}
                                      className="text-xs px-2 py-1 rounded bg-indigo-50 text-indigo-700 hover:bg-indigo-100 inline-flex items-center gap-1"
                                      onClick={() => onSuggestionClick(sug)}
                                    >
                                      <Sparkles className="w-3.5 h-3.5" />
                                      {sug}
                                    </button>
                                  ))}
                                </div>
                              </div>
                            )}
                          </div>
                        ) : (
                          <div className="text-sm text-gray-800 whitespace-pre-wrap">{m.content}</div>
                        )}
                      </div>
                    </div>
                  ))
                )}
              </div>
            )}
          </div>

          {/* Composer */}
          {!activeSourceViewId && (
            <form onSubmit={handleSubmit} className="border-t bg-white p-3">
              <div className="flex items-end gap-2">
                <div className="flex-1">
                  <div className="text-xs text-gray-500 mb-1">
                    Answering from {selectedCount} source{selectedCount !== 1 ? 's' : ''}
                  </div>
                  <textarea
                    className="w-full border rounded p-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
                    rows={2}
                    placeholder="Đặt câu hỏi của bạn…"
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                  />
                </div>
                <button
                  type="submit"
                  disabled={sending || input.trim().length === 0}
                  className={`h-9 px-3 rounded inline-flex items-center gap-1 text-sm ${sending || input.trim().length === 0 ? 'bg-gray-200 text-gray-500' : 'bg-indigo-600 text-white hover:bg-indigo-700'}`}
                >
                  <Send className="w-4 h-4" />
                  Send
                </button>
              </div>
            </form>
          )}
        </div>

        {/* Right: Notepad */}
        <div className="w-96 border-l bg-white flex flex-col">
          <div className="h-10 border-b px-3 flex items-center justify-between">
            <div className="text-sm font-medium">Notepad</div>
            <div className="text-xs text-gray-500">Autosave</div>
          </div>

          {/* Toolbar */}
          <div className="p-2 border-b flex items-center gap-1">
            <button className="px-2 py-1 rounded hover:bg-gray-100" title="Bold" onClick={() => exec('bold')}>
              <Bold className="w-4 h-4" />
            </button>
            <button className="px-2 py-1 rounded hover:bg-gray-100" title="Italic" onClick={() => exec('italic')}>
              <Italic className="w-4 h-4" />
            </button>
            <button className="px-2 py-1 rounded hover:bg-gray-100" title="Underline" onClick={() => exec('underline')}>
              <Underline className="w-4 h-4" />
            </button>
            <div className="mx-1 w-px h-5 bg-gray-200" />
            <button className="px-2 py-1 rounded hover:bg-gray-100" title="Bulleted list" onClick={() => exec('insertUnorderedList')}>
              <List className="w-4 h-4" />
            </button>
            <button className="px-2 py-1 rounded hover:bg-gray-100" title="Numbered list" onClick={() => exec('insertOrderedList')}>
              <ListOrdered className="w-4 h-4" />
            </button>
          </div>

          {/* Editor */}
          <div
            ref={notepadRef}
            className="flex-1 overflow-y-auto p-3 text-sm prose prose-sm max-w-none focus:outline-none"
            contentEditable
            suppressContentEditableWarning
            onInput={(e) => setNotepadHtml(e.currentTarget.innerHTML)}
            onFocus={() => setCaretAtEnd(true)}
            dangerouslySetInnerHTML={{ __html: notepadHtml }}
          />
        </div>
      </div>

      {/* Add Source Modal */}
      <Transition show={openAddSource} as={Fragment}>
        <Dialog onClose={() => { setOpenAddSource(false); resetAddForm(); }} className="relative z-50">
          <Transition.Child
            as={Fragment}
            enter="transition-opacity ease-out duration-150"
            enterFrom="opacity-0"
            enterTo="opacity-100"
            leave="transition-opacity ease-in duration-100"
            leaveFrom="opacity-100"
            leaveTo="opacity-0"
          >
            <div className="fixed inset-0 bg-black/30" />
          </Transition.Child>
          <div className="fixed inset-0 p-4 flex items-center justify-center">
            <Transition.Child
              as={Fragment}
              enter="transition ease-out duration-150 transform"
              enterFrom="opacity-0 scale-95"
              enterTo="opacity-100 scale-100"
              leave="transition ease-in duration-100 transform"
              leaveFrom="opacity-100 scale-100"
              leaveTo="opacity-0 scale-95"
            >
              <Dialog.Panel className="w-full max-w-lg bg-white rounded shadow">
                <div className="border-b px-4 py-2 flex items-center justify-between">
                  <Dialog.Title className="text-sm font-semibold">Add Sources</Dialog.Title>
                  <button className="p-1 rounded hover:bg-gray-100" onClick={() => { setOpenAddSource(false); resetAddForm(); }}>
                    <X className="w-4 h-4" />
                  </button>
                </div>

                <div className="p-4">
                  <div className="flex gap-2 mb-3">
                    <button
                      className={`text-xs px-2 py-1 rounded inline-flex items-center gap-1 ${addMode === 'text' ? 'bg-indigo-600 text-white' : 'bg-gray-100'}`}
                      onClick={() => setAddMode('text')}
                    >
                      <FileText className="w-3.5 h-3.5" /> Paste text
                    </button>
                    <button
                      className={`text-xs px-2 py-1 rounded inline-flex items-center gap-1 ${addMode === 'url' ? 'bg-indigo-600 text-white' : 'bg-gray-100'}`}
                      onClick={() => setAddMode('url')}
                    >
                      <LinkIcon className="w-3.5 h-3.5" /> URL
                    </button>
                    <button
                      className={`text-xs px-2 py-1 rounded inline-flex items-center gap-1 ${addMode === 'file' ? 'bg-indigo-600 text-white' : 'bg-gray-100'}`}
                      onClick={() => setAddMode('file')}
                    >
                      <Upload className="w-3.5 h-3.5" /> File
                    </button>
                  </div>

                  <div className="mb-2">
                    <label className="text-xs text-gray-600">Title (optional)</label>
                    <input
                      className="w-full border rounded px-2 py-1 text-sm"
                      value={newSourceTitle}
                      onChange={(e) => setNewSourceTitle(e.target.value)}
                    />
                  </div>

                  {addMode === 'text' && (
                    <div>
                      <label className="text-xs text-gray-600">Paste text</label>
                      <textarea
                        rows={6}
                        className="w-full border rounded px-2 py-1 text-sm"
                        placeholder="Dán nội dung văn bản làm nguồn"
                        value={newSourceText}
                        onChange={(e) => setNewSourceText(e.target.value)}
                      />
                    </div>
                  )}

                  {addMode === 'url' && (
                    <div>
                      <label className="text-xs text-gray-600">URL</label>
                      <input
                        className="w-full border rounded px-2 py-1 text-sm"
                        placeholder="https://example.com/article"
                        value={newSourceUrl}
                        onChange={(e) => setNewSourceUrl(e.target.value)}
                      />
                      <div className="text-xs text-gray-500 mt-1">
                        Demo không crawl nội dung. Hãy dán tóm tắt vào dạng “Paste text” để grounding tốt.
                      </div>
                    </div>
                  )}

                  {addMode === 'file' && (
                    <div>
                      <label className="text-xs text-gray-600">Upload .txt hoặc .pdf</label>
                      <input
                        type="file"
                        accept=".txt,.pdf"
                        className="w-full text-sm"
                        onChange={(e) => handleFile(e.target.files?.[0])}
                      />
                      {fileError && <div className="text-xs text-red-600 mt-1">{fileError}</div>}
                    </div>
                  )}
                </div>

                <div className="border-t px-4 py-2 flex justify-end gap-2">
                  <button
                    className="text-xs px-3 py-1 rounded bg-gray-100 hover:bg-gray-200"
                    onClick={() => { setOpenAddSource(false); resetAddForm(); }}
                  >
                    Cancel
                  </button>
                  {(addMode === 'text' || addMode === 'url') && (
                    <button
                      className="text-xs px-3 py-1 rounded bg-indigo-600 text-white hover:bg-indigo-700"
                      onClick={handleAddSource}
                    >
                      Add
                    </button>
                  )}
                </div>
              </Dialog.Panel>
            </Transition.Child>
          </div>
        </Dialog>
      </Transition>
    </div>
  );
}

// -----------------------------
// Subcomponents
// -----------------------------
function EmptyState({ selectedCount }) {
  return (
    <div className="mt-16 max-w-xl mx-auto text-center">
      <div className="inline-flex items-center justify-center w-12 h-12 rounded-full bg-indigo-50 text-indigo-600 mb-3">
        <Sparkles className="w-6 h-6" />
      </div>
      <div className="text-lg font-semibold mb-1">Chào mừng đến với NotebookLM (Demo)</div>
      <div className="text-sm text-gray-600">
        Thêm nguồn ở cột trái và đặt câu hỏi ở đây. Mỗi câu trả lời sẽ có trích dẫn nội tuyến để bạn kiểm chứng.
      </div>
      <div className="mt-4 text-xs text-gray-500">
        Đang dùng {selectedCount} nguồn cho câu trả lời.
      </div>
    </div>
  );
}

function SourcePreview({ source, onClose, getSummary, getTopics }) {
  if (!source) return null;
  const summary = getSummary(source);
  const topics = getTopics(source);

  return (
    <div className="max-w-3xl mx-auto">
      <div className="bg-white border rounded p-4">
        <div className="flex items-center justify-between">
          <div className="text-base font-semibold">{source.title}</div>
          <button className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200" onClick={onClose}>
            Đóng
          </button>
        </div>
        <div className="mt-3">
          <div className="text-sm font-medium mb-1">Tóm tắt tự động</div>
          <div className="text-sm text-gray-800">{summary}</div>
        </div>
        <div className="mt-3">
          <div className="text-sm font-medium mb-1">Chủ đề gợi ý</div>
          <div className="flex flex-wrap gap-2">
            {topics.map((t, i) => (
              <span key={i} className="text-xs px-2 py-1 rounded bg-indigo-50 text-indigo-700">#{t}</span>
            ))}
          </div>
        </div>
        <div className="mt-4">
          <div className="text-sm font-medium mb-1">Nội dung nguồn (rút gọn)</div>
          <div className="text-sm text-gray-700 whitespace-pre-wrap">{source.content.slice(0, 1200)}{source.content.length > 1200 ? '…' : ''}</div>
        </div>
      </div>
    </div>
  );
}

export default NotebookLMFrontend;