const { useState, useEffect, useRef, useMemo } = React;

    const translations = {
      vi: {
        appName: 'Notebook',
        newNote: 'Tạo ghi chú mới',
        searchPlaceholder: 'Tìm kiếm ghi chú...',
        allNotes: 'Tất cả ghi chú',
        favorites: 'Yêu thích',
        pinned: 'Đã ghim',
        lockedNotes: 'Ghi chú mã hóa',
        trash: 'Thùng rác',
        emptyTrash: 'Dọn sạch thùng rác',
        folders: 'Thư mục',
        tags: 'Thẻ tag',
        addFolder: 'Thêm thư mục',
        noNotes: 'Chưa có ghi chú nào',
        noNotesDesc: 'Bấm nút "Tạo ghi chú mới" để bắt đầu ghi chép ý tưởng của bạn.',
        noteTitlePlaceholder: 'Tiêu đề ghi chú...',
        wysiwyg: 'Trực quan',
        markdown: 'Markdown',
        save: 'Lưu',
        delete: 'Xóa',
        restore: 'Khôi phục',
        deletePermanent: 'Xóa vĩnh viễn',
        pin: 'Ghim',
        unpin: 'Bỏ ghim',
        favorite: 'Yêu thích',
        lock: 'Mã khóa mật khẩu',
        unlock: 'Mở khóa',
        export: 'Xuất file',
        import: 'Nhập file',
        backup: 'Sao lưu Toàn bộ',
        wordCount: 'Từ',
        charCount: 'Ký tự',
        readTime: 'Phút đọc',
        passwordPrompt: 'Nhập mật khẩu để giải mã ghi chú này',
        passwordMismatch: 'Mật khẩu không chính xác',
        cookieTitle: 'Thông báo Cookie',
        cookieMessage: 'Trang web sử dụng bộ nhớ cục bộ để lưu trữ các ghi chú.',
        cookieAcceptAll: 'Chấp nhận',
        cookieLearnMore: 'Xem thêm',
        saved: 'Đã lưu',
        saving: 'Đang lưu...',
        print: 'In ghi chú',
        copy: 'Sao chép văn bản',
        pageFormat: 'Định dạng trang',
        formatStandard: '📄 Chuẩn',
        formatLined: '📑 Kẻ ngang',
        formatGrid: '🔲 Ô vuông',
        formatCode: '💻 Mã nguồn',
        formatReader: '📖 Đọc tập trung'
      },
      en: {
        appName: 'Notebook',
        newNote: 'New Note',
        searchPlaceholder: 'Search notes...',
        allNotes: 'All Notes',
        favorites: 'Favorites',
        pinned: 'Pinned',
        lockedNotes: 'Encrypted',
        trash: 'Trash',
        emptyTrash: 'Empty Trash',
        folders: 'Folders',
        tags: 'Tags',
        addFolder: 'Add Folder',
        noNotes: 'No notes found',
        noNotesDesc: 'Click "New Note" to start.',
        noteTitlePlaceholder: 'Note title...',
        wysiwyg: 'WYSIWYG',
        markdown: 'Markdown',
        save: 'Save',
        delete: 'Delete',
        restore: 'Restore',
        deletePermanent: 'Delete Permanently',
        pin: 'Pin',
        unpin: 'Unpin',
        favorite: 'Favorite',
        lock: 'Lock with Password',
        unlock: 'Unlock',
        export: 'Export',
        import: 'Import',
        backup: 'Full Backup',
        wordCount: 'words',
        charCount: 'chars',
        readTime: 'min read',
        passwordPrompt: 'Enter password to decrypt',
        passwordMismatch: 'Incorrect password',
        cookieTitle: 'Cookie Notice',
        cookieMessage: 'This site uses local storage to keep your notes.',
        cookieAcceptAll: 'Accept',
        cookieLearnMore: 'Learn more',
        saved: 'Saved',
        saving: 'Saving...',
        print: 'Print',
        copy: 'Copy',
        pageFormat: 'Page Format',
        formatStandard: '📄 Standard',
        formatLined: '📑 Lined',
        formatGrid: '🔲 Grid',
        formatCode: '💻 Code',
        formatReader: '📖 Reader'
      }
    };

    class DB {
      constructor() {
        this.name = 'SingleNotebook_v3';
        this.version = 1;
        this.db = null;
      }
      async init() {
        if (this.db) return this.db;
        return new Promise((resolve, reject) => {
          const req = indexedDB.open(this.name, this.version);
          req.onupgradeneeded = (e) => {
            const db = e.target.result;
            if (!db.objectStoreNames.contains('notes')) db.createObjectStore('notes', { keyPath: 'id' });
            if (!db.objectStoreNames.contains('folders')) db.createObjectStore('folders', { keyPath: 'id' });
            if (!db.objectStoreNames.contains('tags')) db.createObjectStore('tags', { keyPath: 'id' });
          };
          req.onsuccess = (e) => {
            this.db = e.target.result;
            this.seed().then(() => resolve(this.db));
          };
          req.onerror = (e) => reject(e.target.error);
        });
      }
      async seed() {
        const notes = await this.getNotes();
        if (notes.length === 0) {
          const demo = {
            id: 'note-welcome',
            title: 'Chào mừng đến với Siêu Notebook 🔥',
            content: '<h1>Bản nâng cấp toàn diện!</h1><p>Ghi chú của bạn đã có <b>đầy đủ</b> mọi tính năng:</p><ul><li>Định dạng chữ (Màu sắc, kích cỡ, highlight)</li><li>5 giao diện trang (Kẻ ngang, ô vuông...)</li><li>Thư mục, Thẻ Tag, Đổi màu nhãn</li><li>Xuất/Nhập 6 chuẩn: MD, TXT, JSON, DOCX, HTML, PDF</li><li>Mã hóa mật khẩu AES-256 an toàn.</li></ul>',
            folderId: '',
            tags: ['Chào mừng', 'Hướng dẫn'],
            color: '#3b82f6',
            emoji: '🔥',
            isPinned: true,
            isFavorite: true,
            isTrashed: false,
            isLocked: false,
            passwordHash: '',
            pageFormat: 'standard',
            mode: 'wysiwyg',
            createdAt: Date.now(),
            updatedAt: Date.now()
          };
          await this.saveNote(demo);
        }
      }
      async getNotes() { await this.init(); return new Promise(res => { const req = this.db.transaction('notes', 'readonly').objectStore('notes').getAll(); req.onsuccess = () => res(req.result || []); }); }
      async saveNote(note) { await this.init(); return new Promise(res => { const tx = this.db.transaction('notes', 'readwrite'); tx.objectStore('notes').put(note); tx.oncomplete = () => res(note); }); }
      async deleteNote(id, perm = false) {
        await this.init();
        return new Promise(res => {
          const tx = this.db.transaction('notes', 'readwrite');
          const store = tx.objectStore('notes');
          if (perm) store.delete(id);
          else {
            const req = store.get(id);
            req.onsuccess = () => { if (req.result) store.put({ ...req.result, isTrashed: true }); };
          }
          tx.oncomplete = () => res(true);
        });
      }
      async emptyTrash() {
        await this.init();
        const notes = await this.getNotes();
        const tx = this.db.transaction('notes', 'readwrite');
        const store = tx.objectStore('notes');
        notes.filter(n => n.isTrashed).forEach(n => store.delete(n.id));
        return new Promise(res => tx.oncomplete = () => res(true));
      }
      async restoreNote(id) {
        await this.init();
        return new Promise(res => {
          const tx = this.db.transaction('notes', 'readwrite');
          const store = tx.objectStore('notes');
          const req = store.get(id);
          req.onsuccess = () => { if (req.result) store.put({ ...req.result, isTrashed: false }); };
          tx.oncomplete = () => res(true);
        });
      }
      async getFolders() { await this.init(); return new Promise(res => { const req = this.db.transaction('folders', 'readonly').objectStore('folders').getAll(); req.onsuccess = () => res(req.result || []); }); }
      async saveFolder(folder) { await this.init(); return new Promise(res => { const tx = this.db.transaction('folders', 'readwrite'); tx.objectStore('folders').put(folder); tx.oncomplete = () => res(folder); }); }
    }

    const db = new DB();

    function Icon({ name, className = 'w-5 h-5' }) {
      const paths = {
        plus: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />,
        search: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />,
        trash: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />,
        star: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" />,
        pin: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />,
        lock: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />,
        unlock: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z" />,
        folder: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />,
        download: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />,
        upload: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />,
        sun: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />,
        moon: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />,
        cookie: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 2a10 10 0 1010 10 4 4 0 01-5-5 4 4 0 01-5-5z" />,
        x: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />,
        check: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />,
        fileText: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />,
        tag: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />,
        layout: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />,
        refresh: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />,
        copy: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />,
        print: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4H7v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z" />
      };
      return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" className={className}>{paths[name] || paths.fileText}</svg>;
    }
    function ExportModal({ isOpen, onClose, note, allNotes, folders }) {
      const [format, setFormat] = useState('json');
      const [scope, setScope] = useState('single');
      const [isExporting, setIsExporting] = useState(false);

      if (!isOpen) return null;

      const generateContent = async (n, fmt) => {
        const filename = (n.title || 'ghi-chu').replace(/[/\\?%*:|"<>]/g, '-');
        let content = n.content || '';
        let type = 'text/plain';

        if (fmt === 'json') return { data: JSON.stringify(n, null, 2), filename: `${filename}.json`, type: 'application/json' };
        if (fmt === 'txt') return { data: n.title + '\n\n' + content.replace(/<[^>]+>/g, ''), filename: `${filename}.txt`, type };
        if (fmt === 'md') return { data: '# ' + n.title + '\n\n' + (window.TurndownService ? new TurndownService().turndown(content) : content), filename: `${filename}.md`, type: 'text/markdown' };
        if (fmt === 'html') return { data: `<!DOCTYPE html><html><head><meta charset="utf-8"><title>${n.title}</title></head><body style="font-family:sans-serif;padding:20px;"><h1>${n.title}</h1>${content}</body></html>`, filename: `${filename}.html`, type: 'text/html' };
        if (fmt === 'docx') return { data: `<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'></head><body><h2>${n.title}</h2>${content}</body></html>`, filename: `${filename}.docx`, type: 'application/msword' };
        if (fmt === 'pdf') {
          const el = document.createElement('div');
          el.style.padding = '20px'; el.style.fontFamily = 'sans-serif';
          el.innerHTML = `<h1 style="font-size:24px; font-weight:bold; margin-bottom:16px;">${n.title}</h1><div>${content}</div>`;
          if (window.html2pdf) {
            const opt = { margin: 15, filename: `${filename}.pdf`, image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2 }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } };
            const pdfBlob = await html2pdf().set(opt).from(el).output('blob');
            return { blob: pdfBlob, filename: `${filename}.pdf` };
          }
        }
      };

      const handleExport = async () => {
        const targetNotes = scope === 'single' ? (note ? [note] : []) : allNotes;
        if (targetNotes.length === 0) return alert('Không có ghi chú nào');

        setIsExporting(true);
        try {
          if (targetNotes.length === 1 && scope === 'single') {
            const res = await generateContent(targetNotes[0], format);
            saveAs(res.blob || new Blob([res.data], { type: `${res.type};charset=utf-8` }), res.filename);
          } else {
            const zip = new JSZip();
            for (const n of targetNotes) {
              const res = await generateContent(n, format);
              zip.file(res.filename, res.blob || res.data);
            }
            saveAs(await zip.generateAsync({ type: 'blob' }), `Notebook_Export_${Date.now()}.zip`);
          }
          onClose();
        } catch (err) { alert('Có lỗi xảy ra khi xuất file.'); }
        setIsExporting(false);
      };

      return (
        <div className="fixed inset-0 bg-slate-900/60 backdrop-blur-xs flex items-center justify-center p-4 z-50">
          <div className="bg-white dark:bg-slate-900 rounded-3xl p-6 max-w-md w-full shadow-2xl space-y-4">
            <div className="flex items-center justify-between"><h2 className="text-lg font-bold">Xuất dữ liệu</h2><button onClick={onClose}><Icon name="x" /></button></div>
            <div>
              <label className="text-xs font-semibold text-slate-500 uppercase block mb-2">Phạm vi xuất</label>
              <div className="grid grid-cols-2 gap-2 text-xs">
                <button onClick={() => setScope('single')} className={`p-2.5 rounded-xl border ${scope === 'single' ? 'bg-blue-50 border-blue-500 text-blue-600 font-bold' : 'border-slate-200'}`}>Ghi chú hiện tại</button>
                <button onClick={() => setScope('all')} className={`p-2.5 rounded-xl border ${scope === 'all' ? 'bg-blue-50 border-blue-500 text-blue-600 font-bold' : 'border-slate-200'}`}>Tất cả ({allNotes.length})</button>
              </div>
            </div>
            <div>
              <label className="text-xs font-semibold text-slate-500 uppercase block mb-2">Định dạng file</label>
              <div className="grid grid-cols-3 gap-2 text-xs">
                {['json', 'txt', 'docx', 'md', 'html', 'pdf'].map(f => (
                  <button key={f} onClick={() => setFormat(f)} className={`p-2.5 rounded-xl border uppercase font-semibold ${format === f ? 'bg-blue-600 text-white border-blue-600' : 'border-slate-200 hover:border-blue-400'}`}>.{f}</button>
                ))}
              </div>
            </div>
            <div className="flex justify-end gap-2 pt-2"><button onClick={onClose} className="px-4 py-2 text-xs font-semibold">Hủy</button><button onClick={handleExport} disabled={isExporting} className="px-5 py-2.5 bg-blue-600 text-white rounded-xl text-xs font-bold">{isExporting ? 'Đang xuất...' : 'Tải xuống'}</button></div>
          </div>
        </div>
      );
    }
    function ImportModal({ isOpen, onClose, onImport }) {
      const [isLoading, setIsLoading] = useState(false);
      if (!isOpen) return null;

      const handleFile = async (e) => {
        const file = e.target.files && e.target.files[0];
        if (!file) return;
        setIsLoading(true);
        const ext = file.name.split('.').pop().toLowerCase();
        const title = file.name.replace(/\.[^/.]+$/, '');

        try {
          if (ext === 'json') {
            const data = JSON.parse(await file.text());
            (Array.isArray(data) ? data : [data]).forEach(n => onImport(n));
          } else if (['txt', 'md', 'html', 'docx', 'doc'].includes(ext)) {
            const text = await file.text();
            let content = ext === 'md' && window.marked ? marked.parse(text) : (ext === 'txt' ? `<p>${text.replace(/\n/g, '<br/>')}</p>` : text);
            onImport({ id: `import-${Date.now()}`, title, content, createdAt: Date.now(), updatedAt: Date.now(), mode: 'wysiwyg', pageFormat: 'standard' });
          } else if (ext === 'pdf' && window.pdfjsLib) {
            pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
            const pdf = await pdfjsLib.getDocument({ data: await file.arrayBuffer() }).promise;
            let fullText = '';
            for (let i = 1; i <= pdf.numPages; i++) {
              const textContent = await (await pdf.getPage(i)).getTextContent();
              fullText += `<p>${textContent.items.map(item => item.str).join(' ')}</p>`;
            }
            onImport({ id: `import-${Date.now()}`, title, content: fullText || '<p>PDF trống</p>', createdAt: Date.now(), updatedAt: Date.now(), pageFormat: 'standard', mode: 'wysiwyg' });
          }
          onClose();
        } catch (err) { alert('Lỗi khi đọc file!'); }
        setIsLoading(false);
      };

      return (
        <div className="fixed inset-0 bg-slate-900/60 backdrop-blur-xs flex items-center justify-center p-4 z-50">
          <div className="bg-white dark:bg-slate-900 rounded-3xl p-6 max-w-md w-full shadow-2xl space-y-4">
            <div className="flex justify-between items-center"><h2 className="text-lg font-bold">Nhập tập tin</h2><button onClick={onClose}><Icon name="x" /></button></div>
            <div className="border-2 border-dashed border-slate-300 dark:border-slate-700 rounded-2xl p-8 text-center cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800" onClick={() => document.getElementById('importInp').click()}>
              <Icon name="upload" className="w-10 h-10 mx-auto text-slate-400 mb-2" />
              <p className="text-sm font-semibold">{isLoading ? 'Đang đọc...' : 'Chọn file từ máy tính'}</p>
              <p className="text-xs text-slate-400 mt-1">Hỗ trợ: MD, TXT, JSON, DOCX, PDF, HTML</p>
              <input id="importInp" type="file" accept=".json,.txt,.docx,.doc,.md,.html,.pdf" className="hidden" onChange={handleFile} />
            </div>
          </div>
        </div>
      );
    }
    function LockModal({ isOpen, onClose, onConfirm, isSetting }) {
      const [pwd, setPwd] = useState('');
      if (!isOpen) return null;
      return (
        <div className="fixed inset-0 bg-slate-900/60 backdrop-blur-xs flex items-center justify-center p-4 z-50">
          <div className="bg-white dark:bg-slate-900 rounded-3xl p-6 max-w-sm w-full shadow-2xl space-y-4">
            <h3 className="font-bold">{isSetting ? 'Đặt mật khẩu khóa ghi chú' : 'Nhập mật khẩu mở khóa'}</h3>
            <input type="password" placeholder="Nhập mật khẩu..." value={pwd} onChange={e => setPwd(e.target.value)} className="w-full px-3 py-2 border rounded-xl dark:bg-slate-800 border-slate-200 outline-none text-sm" />
            <div className="flex justify-end gap-2"><button onClick={onClose} className="px-3 py-1.5 text-xs">Hủy</button><button onClick={() => { onConfirm(pwd); setPwd(''); }} className="px-4 py-1.5 bg-blue-600 text-white rounded-xl text-xs font-bold">Xác nhận</button></div>
          </div>
        </div>
      );
    }

    function App() {
      const [notes, setNotes] = useState([]);
      const [folders, setFolders] = useState([]);
      const [activeNoteId, setActiveNoteId] = useState(null);
      const [activeView, setActiveView] = useState('all');
      const [activeFolder, setActiveFolder] = useState(null);
      const [activeTag, setActiveTag] = useState(null);
      const [searchQuery, setSearchQuery] = useState('');
      const [theme, setTheme] = useState('light');
      const [lang, setLang] = useState('vi');
      const [showCookie, setShowCookie] = useState(() => localStorage.getItem('notebook_cookie_consent') !== 'true');
      
      const [unlocked, setUnlocked] = useState({});
      const [showExport, setShowExport] = useState(false);
      const [showImport, setShowImport] = useState(false);
      const [showLock, setShowLock] = useState(false);
      const [lockAction, setLockAction] = useState('unlock');
      const [isSaving, setIsSaving] = useState(false);
      const editorRef = useRef(null);

      const t = translations[lang] || translations.vi;

      useEffect(() => {
        async function load() {
          const n = await db.getNotes();
          const f = await db.getFolders();
          setNotes(n); setFolders(f);
          if (n.length > 0) setActiveNoteId(n[0].id);
        }
        load();
      }, []);

      const activeNote = notes.find(n => n.id === activeNoteId);

      const handleCreate = async () => {
        const newN = {
          id: `note-${Date.now()}`,
          title: t.noteTitlePlaceholder,
          content: '<p></p>',
          folderId: activeFolder || '',
          tags: activeTag ? [activeTag] : [],
          color: '#3b82f6', emoji: '📝',
          isPinned: false, isFavorite: false, isTrashed: false, isLocked: false, passwordHash: '',
          pageFormat: 'standard', mode: 'wysiwyg',
          createdAt: Date.now(), updatedAt: Date.now()
        };
        await db.saveNote(newN);
        setNotes([newN, ...notes]);
        setActiveNoteId(newN.id);
      };

      const handleSave = async (updated) => {
        setIsSaving(true);
        const n = { ...updated, updatedAt: Date.now() };
        await db.saveNote(n);
        setNotes(prev => prev.map(item => item.id === n.id ? n : item));
        setTimeout(() => setIsSaving(false), 300);
      };

      const handleDelete = async (id, perm = false) => {
        await db.deleteNote(id, perm);
        setNotes(prev => perm ? prev.filter(n => n.id !== id) : prev.map(n => n.id === id ? { ...n, isTrashed: true } : n));
      };

      const execCmd = (cmd, val = null) => {
        document.execCommand(cmd, false, val);
        if (editorRef.current && activeNote) handleSave({ ...activeNote, content: editorRef.current.innerHTML });
      };

      const allTags = useMemo(() => Array.from(new Set(notes.flatMap(n => n.tags || []))), [notes]);
      
      const filtered = useMemo(() => notes.filter(n => {
        if (activeView === 'trash') return n.isTrashed;
        if (n.isTrashed) return false;
        if (activeView === 'favorites') return n.isFavorite;
        if (activeView === 'pinned') return n.isPinned;
        if (activeView === 'locked') return n.isLocked;
        if (activeFolder && n.folderId !== activeFolder) return false;
        if (activeTag && !n.tags?.includes(activeTag)) return false;
        if (searchQuery.trim()) {
          const q = searchQuery.toLowerCase();
          return (n.title || '').toLowerCase().includes(q) || (n.content || '').toLowerCase().includes(q);
        }
        return true;
      }), [notes, activeView, searchQuery, activeFolder, activeTag]);

      const stats = useMemo(() => {
        if (!activeNote) return { words: 0, chars: 0 };
        const text = activeNote.content.replace(/<[^>]+>/g, ' ').trim();
        return { chars: text.length, words: text ? text.split(/\s+/).length : 0 };
      }, [activeNote]);

      return (
        <div className={`flex flex-col h-screen overflow-hidden ${theme === 'dark' ? 'dark bg-slate-900 text-white' : 'bg-slate-50 text-slate-800'}`}>
          {}
          <header className="h-14 border-b border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 px-4 flex items-center justify-between z-10 shrink-0">
            <div className="flex items-center gap-2"><span className="text-xl">📝</span><span className="font-bold">{t.appName}</span></div>
            <div className="flex-1 max-w-md mx-4 relative">
              <Icon name="search" className="w-4 h-4 absolute left-3 top-2.5 text-slate-400" />
              <input type="text" placeholder={t.searchPlaceholder} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} className="w-full bg-slate-100 dark:bg-slate-800 rounded-xl pl-9 pr-4 py-1.5 text-sm outline-none" />
            </div>
            <div className="flex items-center gap-2">
              <button onClick={handleCreate} className="flex items-center gap-1 bg-blue-600 text-white px-3 py-1.5 rounded-xl text-sm font-semibold hover:bg-blue-700"><Icon name="plus" className="w-4 h-4" /><span>{t.newNote}</span></button>
              <button onClick={() => setShowImport(true)} className="p-2 rounded-xl text-slate-600 hover:bg-slate-100 dark:hover:bg-slate-800" title={t.import}><Icon name="upload" className="w-4 h-4" /></button>
              <button onClick={() => setShowExport(true)} className="p-2 rounded-xl text-slate-600 hover:bg-slate-100 dark:hover:bg-slate-800" title={t.export}><Icon name="download" className="w-4 h-4" /></button>
              <button onClick={() => setLang(l => l === 'vi' ? 'en' : 'vi')} className="p-2 rounded-xl text-slate-600 font-bold text-xs hover:bg-slate-100 dark:hover:bg-slate-800">{lang.toUpperCase()}</button>
              <button onClick={() => setTheme(t => t === 'dark' ? 'light' : 'dark')} className="p-2 rounded-xl text-slate-600 hover:bg-slate-100 dark:hover:bg-slate-800"><Icon name={theme === 'dark' ? 'sun' : 'moon'} className="w-4 h-4" /></button>
            </div>
          </header>

          <div className="flex-1 flex overflow-hidden">
            {}
            <aside className="w-64 border-r border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 p-3 space-y-4 overflow-y-auto shrink-0">
              <div className="space-y-1">
                {[{ id: 'all', icon: 'fileText', label: t.allNotes }, { id: 'favorites', icon: 'star', label: t.favorites }, { id: 'pinned', icon: 'pin', label: t.pinned }, { id: 'locked', icon: 'lock', label: t.lockedNotes }, { id: 'trash', icon: 'trash', label: t.trash }].map(item => (
                  <button key={item.id} onClick={() => { setActiveView(item.id); setActiveFolder(null); setActiveTag(null); }} className={`w-full flex items-center justify-between px-3 py-2 rounded-xl text-sm font-medium ${activeView === item.id && !activeFolder && !activeTag ? 'bg-blue-50 text-blue-600 font-bold' : 'text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800'}`}>
                    <div className="flex items-center gap-2.5"><Icon name={item.icon} className="w-4 h-4" /><span>{item.label}</span></div>
                    {item.id === 'trash' && notes.some(n => n.isTrashed) && <span onClick={e => { e.stopPropagation(); db.emptyTrash().then(() => setNotes(notes.filter(x => !x.isTrashed))); }} className="text-[10px] text-red-500 hover:underline">{t.emptyTrash}</span>}
                  </button>
                ))}
              </div>
              
              <div className="pt-2 border-t border-slate-100 dark:border-slate-800">
                <div className="flex justify-between px-2 mb-1"><span className="text-xs font-bold text-slate-400 uppercase">{t.folders}</span><button onClick={() => { const name = prompt('Tên thư mục:'); if(name) { const f = {id:`folder-${Date.now()}`, name}; db.saveFolder(f); setFolders([...folders, f]); } }} className="hover:bg-slate-100 rounded p-1"><Icon name="plus" className="w-3.5 h-3.5" /></button></div>
                {folders.map(f => <button key={f.id} onClick={() => { setActiveFolder(f.id); setActiveTag(null); }} className={`w-full flex items-center gap-2 px-3 py-1.5 rounded-xl text-xs font-medium ${activeFolder === f.id ? 'bg-blue-50 text-blue-600 font-bold' : 'text-slate-600 hover:bg-slate-100'}`}><Icon name="folder" className="w-3.5 h-3.5" />{f.name}</button>)}
              </div>

              <div className="pt-2 border-t border-slate-100 dark:border-slate-800">
                <span className="text-xs font-bold text-slate-400 uppercase px-2 mb-1 block">{t.tags}</span>
                <div className="flex flex-wrap gap-1 px-1">
                  {allTags.map(tag => <button key={tag} onClick={() => { setActiveTag(tag); setActiveFolder(null); }} className={`px-2 py-0.5 rounded-md text-xs border ${activeTag === tag ? 'bg-blue-600 text-white border-blue-600' : 'border-slate-200 text-slate-600'}`}>#{tag}</button>)}
                </div>
              </div>
            </aside>

            {}
            <div className="w-80 border-r border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 p-2 space-y-2 overflow-y-auto shrink-0">
              {filtered.map(n => (
                <div key={n.id} onClick={() => setActiveNoteId(n.id)} style={{ borderLeftColor: n.color || '#3b82f6' }} className={`p-3 rounded-2xl cursor-pointer border-l-4 border-y border-r transition ${n.id === activeNoteId ? 'bg-white dark:bg-slate-800 border-y-slate-200 shadow-sm' : 'bg-white/60 border-transparent hover:bg-white'}`}>
                  <div className="flex items-center justify-between">
                    <h3 className="font-semibold text-sm truncate flex-1">{n.emoji} {n.title}</h3>
                    <div className="flex gap-1 shrink-0">
                      {n.isPinned && <Icon name="pin" className="w-3 h-3 text-blue-500 fill-blue-500" />}
                      {n.isFavorite && <Icon name="star" className="w-3 h-3 text-yellow-500 fill-yellow-500" />}
                      {n.isLocked && <Icon name="lock" className="w-3 h-3 text-red-500" />}
                    </div>
                  </div>
                  <p className="text-xs text-slate-500 line-clamp-2 mt-1">{n.isLocked && !unlocked[n.id] ? '🔒 [Đã mã hóa]' : (n.content.replace(/<[^>]+>/g, '') || 'Trống')}</p>
                </div>
              ))}
            </div>

            {}
            <main className="flex-1 bg-white dark:bg-slate-900 flex flex-col p-6 overflow-y-auto relative">
              {activeNote ? (
                activeNote.isLocked && !unlocked[activeNote.id] ? (
                  <div className="m-auto text-center space-y-3"><Icon name="lock" className="w-12 h-12 mx-auto text-slate-400" /><p className="text-sm font-semibold">{t.passwordPrompt}</p><button onClick={() => { setLockAction('unlock'); setShowLock(true); }} className="px-4 py-2 bg-blue-600 text-white rounded-xl text-xs font-bold">Mở khóa ngay</button></div>
                ) : (
                  <div className={`w-full transition-all duration-200 ${activeNote.pageFormat === 'reader' ? '' : 'max-w-3xl mx-auto'} ${activeNote.pageFormat !== 'standard' ? `p-6 ${activeNote.pageFormat === 'lined' ? 'page-format-lined' : activeNote.pageFormat === 'grid' ? 'page-format-grid' : activeNote.pageFormat === 'code' ? 'page-format-code' : 'page-format-reader'}` : 'space-y-4'}`}>
                    
                    {}
                    <div className="flex items-center justify-between border-b border-slate-100 dark:border-slate-800 pb-3 gap-2 flex-wrap">
                      <div className="flex items-center gap-2 flex-1 min-w-[200px]">
                        <input type="text" value={activeNote.emoji} onChange={e => handleSave({ ...activeNote, emoji: e.target.value })} className="w-8 text-xl bg-transparent outline-none text-center" />
                        <input type="text" value={activeNote.title} onChange={e => handleSave({ ...activeNote, title: e.target.value })} placeholder={t.noteTitlePlaceholder} className="text-2xl font-bold bg-transparent outline-none flex-1" />
                      </div>
                      
                      <div className="flex items-center gap-1 shrink-0">
                        {}
                        <div className="flex items-center bg-slate-100 dark:bg-slate-800 p-1 rounded-xl border border-slate-200 mr-2">
                          <Icon name="layout" className="w-4 h-4 text-slate-500 ml-1.5 mr-1" />
                          <select value={activeNote.pageFormat || 'standard'} onChange={e => handleSave({ ...activeNote, pageFormat: e.target.value })} className="bg-transparent text-xs font-semibold py-1 outline-none cursor-pointer">
                            <option value="standard">{t.formatStandard}</option>
                            <option value="lined">{t.formatLined}</option>
                            <option value="grid">{t.formatGrid}</option>
                            <option value="code">{t.formatCode}</option>
                            <option value="reader">{t.formatReader}</option>
                          </select>
                        </div>
                        <button onClick={() => handleSave({...activeNote, isPinned: !activeNote.isPinned})} className={`p-2 rounded-xl hover:bg-slate-100 ${activeNote.isPinned ? 'text-blue-600' : 'text-slate-400'}`}><Icon name="pin" /></button>
                        <button onClick={() => handleSave({...activeNote, isFavorite: !activeNote.isFavorite})} className={`p-2 rounded-xl hover:bg-slate-100 ${activeNote.isFavorite ? 'text-yellow-500' : 'text-slate-400'}`}><Icon name="star" /></button>
                        <button onClick={() => { setLockAction(activeNote.isLocked ? 'remove' : 'set'); setShowLock(true); }} className={`p-2 rounded-xl hover:bg-slate-100 ${activeNote.isLocked ? 'text-red-500' : 'text-slate-400'}`}><Icon name={activeNote.isLocked ? 'lock' : 'unlock'} /></button>
                        <button onClick={() => { const win = window.open('',''); win.document.write(`<h1>${activeNote.title}</h1>${activeNote.content}`); win.print(); win.close(); }} className="p-2 text-slate-400 hover:bg-slate-100 rounded-xl" title={t.print}><Icon name="print" /></button>
                        {activeNote.isTrashed ? (
                          <><button onClick={() => db.restoreNote(activeNote.id).then(()=>setNotes(notes.map(n=>n.id===activeNote.id?{...n, isTrashed:false}:n)))} className="px-3 py-1 bg-green-600 text-white rounded-xl text-xs font-bold">{t.restore}</button>
                          <button onClick={() => handleDelete(activeNote.id, true)} className="px-3 py-1 bg-red-600 text-white rounded-xl text-xs font-bold">{t.deletePermanent}</button></>
                        ) : <button onClick={() => handleDelete(activeNote.id)} className="p-2 text-red-500 hover:bg-red-50 rounded-xl"><Icon name="trash" /></button>}
                      </div>
                    </div>

                    {}
                    <div className="flex items-center justify-between text-xs text-slate-400 py-2">
                      <div className="flex items-center gap-2">
                        {['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6'].map(c => <button key={c} onClick={() => handleSave({ ...activeNote, color: c })} className="w-4 h-4 rounded-full" style={{ backgroundColor: c }} />)}
                        <button onClick={() => { const tag = prompt('Tên thẻ tag:'); if (tag && !activeNote.tags?.includes(tag)) handleSave({ ...activeNote, tags: [...(activeNote.tags||[]), tag] }); }} className="hover:underline flex items-center gap-1 ml-2"><Icon name="tag" className="w-3 h-3" /><span>+ Tag</span></button>
                      </div>
                      <div className="flex items-center gap-2">
                        <span>{isSaving ? t.saving : t.saved}</span>
                        <div className="border-l pl-2 border-slate-200 flex gap-2">
                          <button onClick={() => handleSave({...activeNote, mode:'wysiwyg'})} className={`px-2 py-0.5 rounded ${activeNote.mode === 'wysiwyg' ? 'bg-blue-100 text-blue-600 font-bold' : ''}`}>{t.wysiwyg}</button>
                          <button onClick={() => handleSave({...activeNote, mode:'markdown'})} className={`px-2 py-0.5 rounded ${activeNote.mode === 'markdown' ? 'bg-blue-100 text-blue-600 font-bold' : ''}`}>{t.markdown}</button>
                        </div>
                      </div>
                    </div>

                    {}
                    {activeNote.mode === 'wysiwyg' && (
                      <div className="flex flex-wrap items-center gap-1.5 border-b border-slate-200 dark:border-slate-800 pb-2 mb-2 text-xs text-slate-700 dark:text-slate-200 bg-slate-50/80 dark:bg-slate-800/40 p-2 rounded-xl">
                        <select onChange={e => execCmd('fontName', e.target.value)} className="px-2 py-1 bg-white dark:bg-slate-700 border border-slate-200 rounded text-xs outline-none">
                          <option value="Plus Jakarta Sans">Jakarta</option><option value="Arial">Arial</option><option value="Georgia">Georgia</option><option value="Fira Code">Fira Code</option>
                        </select>
                        <select onChange={e => execCmd('fontSize', e.target.value)} className="px-2 py-1 bg-white dark:bg-slate-700 border border-slate-200 rounded text-xs outline-none">
                          <option value="3">16px</option><option value="1">12px</option><option value="5">24px</option><option value="7">48px</option>
                        </select>
                        <div className="h-4 w-px bg-slate-300 mx-1" />
                        <button onClick={() => execCmd('bold')} className="px-2 py-1 font-bold hover:bg-slate-200 dark:hover:bg-slate-700 rounded">B</button>
                        <button onClick={() => execCmd('italic')} className="px-2 py-1 italic hover:bg-slate-200 dark:hover:bg-slate-700 rounded">I</button>
                        <button onClick={() => execCmd('underline')} className="px-2 py-1 underline hover:bg-slate-200 dark:hover:bg-slate-700 rounded">U</button>
                        <div className="h-4 w-px bg-slate-300 mx-1" />
                        <label className="flex items-center cursor-pointer hover:bg-slate-200 p-1 rounded" title="Màu chữ"><span className="font-bold text-red-500">A</span><input type="color" onChange={e => execCmd('foreColor', e.target.value)} className="w-0 h-0 opacity-0 absolute"/></label>
                        <label className="flex items-center cursor-pointer hover:bg-slate-200 p-1 rounded" title="Highlight"><span className="bg-yellow-300 text-black px-1 rounded font-bold text-[10px]">HL</span><input type="color" defaultValue="#fef08a" onChange={e => execCmd('hiliteColor', e.target.value)} className="w-0 h-0 opacity-0 absolute"/></label>
                        <div className="h-4 w-px bg-slate-300 mx-1" />
                        <button onClick={() => execCmd('justifyLeft')} className="px-1.5 py-1 hover:bg-slate-200 rounded">⬅️</button>
                        <button onClick={() => execCmd('justifyCenter')} className="px-1.5 py-1 hover:bg-slate-200 rounded">↔️</button>
                        <button onClick={() => execCmd('justifyRight')} className="px-1.5 py-1 hover:bg-slate-200 rounded">➡️</button>
                        <button onClick={() => execCmd('insertUnorderedList')} className="px-2 py-1 hover:bg-slate-200 rounded">• List</button>
                      </div>
                    )}

                    {}
                    {activeNote.mode === 'wysiwyg' ? (
                      <div ref={editorRef} contentEditable suppressContentEditableWarning onBlur={e => handleSave({ ...activeNote, content: e.target.innerHTML })} dangerouslySetInnerHTML={{ __html: activeNote.content || '' }} className="min-h-[400px] outline-none editor-content leading-relaxed" />
                    ) : (
                      <textarea value={activeNote.content || ''} onChange={e => handleSave({ ...activeNote, content: e.target.value })} className="w-full min-h-[400px] bg-slate-50 dark:bg-slate-800/50 p-4 font-mono text-sm rounded-xl outline-none border border-slate-200 dark:border-slate-700" />
                    )}

                    {}
                    <div className="border-t border-slate-100 dark:border-slate-800 pt-3 flex items-center justify-between text-xs text-slate-400">
                      <div>{stats.words} {t.wordCount} | {stats.chars} {t.charCount}</div>
                      <div>Cập nhật: {new Date(activeNote.updatedAt).toLocaleTimeString()}</div>
                    </div>
                  </div>
                )
              ) : (
                <div className="m-auto text-center text-slate-400"><p className="font-semibold">{t.noNotes}</p></div>
              )}
            </main>
          </div>

          <LockModal isOpen={showLock} onClose={() => setShowLock(false)} isSetting={lockAction==='set'} onConfirm={pwd => {
            if(!pwd) return;
            const hash = CryptoJS.SHA256(pwd).toString();
            if(lockAction === 'unlock') {
              if(hash === activeNote.passwordHash) setUnlocked({...unlocked, [activeNote.id]: true}); else alert(t.passwordMismatch);
            } else if(lockAction === 'set') {
              handleSave({...activeNote, isLocked: true, passwordHash: hash}); setUnlocked({...unlocked, [activeNote.id]: true});
            } else if(lockAction === 'remove') {
              if(hash === activeNote.passwordHash) handleSave({...activeNote, isLocked: false, passwordHash: ''}); else alert(t.passwordMismatch);
            }
            setShowLock(false);
          }}/>
          <ExportModal isOpen={showExport} onClose={() => setShowExport(false)} note={activeNote} allNotes={notes} />
          <ImportModal isOpen={showImport} onClose={() => setShowImport(false)} onImport={n => { handleSave(n); setNotes(p => [n, ...p]); }} />

          <footer className="notebook-footer shrink-0 border-t border-slate-200 dark:border-slate-800 bg-white/95 dark:bg-slate-900/95 px-4 py-2 text-center">
            <div className="text-xs font-semibold text-slate-600 dark:text-slate-300">👨‍💻 Người thực hiện: ATCX</div>
            <div className="text-[11px] text-slate-400">© 2026 | © Copyright ATCX. All rights reserved.</div>
          </footer>

          {showCookie && (
            <div className="cookie-banner fixed inset-x-0 bottom-0 z-[60] p-3 sm:p-4">
              <div className="max-w-3xl mx-auto rounded-2xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-2xl px-4 py-3 sm:px-5 sm:py-4">
                <div className="flex flex-col sm:flex-row sm:items-center gap-3">
                  <div className="flex-1">
                    <div className="font-bold text-sm text-slate-800 dark:text-white">{t.cookieTitle}</div>
                    <div className="text-xs text-slate-500 dark:text-slate-400 mt-1">{t.cookieMessage}</div>
                    <a href="cookie.html" className="inline-block mt-1.5 text-xs font-semibold text-blue-600 hover:text-blue-700 hover:underline">{t.cookieLearnMore} →</a>
                  </div>
                  <button onClick={() => { localStorage.setItem('notebook_cookie_consent', 'true'); setShowCookie(false); }} className="self-start sm:self-center px-4 py-2 rounded-xl bg-blue-600 text-white text-xs font-bold hover:bg-blue-700 transition">{t.cookieAcceptAll}</button>
                </div>
              </div>
            </div>
          )}
        </div>
      );
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<App />);
