/* global React, Icon, IconBtn, copyText, db */
const { useState, useEffect, useCallback } = React;

// ============================================================
// Data export / import
// Exports every store (except links/kv if not selected) as JSON.
// Re-imports merge or replace.
// ============================================================

const EXPORTABLE_STORES = [
  { id: 'todos',     label: 'Todos',      icon: 'check_box' },
  { id: 'notes',     label: 'Notes',      icon: 'description' },
  { id: 'jsonDocs',  label: 'JSON docs',  icon: 'data_object' },
  { id: 'bookmarks', label: 'Bookmarks',  icon: 'bookmark' },
  { id: 'passwords', label: 'Passwords',  icon: 'key' },
  { id: 'flashcardCollections', label: 'Flashcard collections', icon: 'style' },
  { id: 'flashcardCards',       label: 'Flashcards',            icon: 'layers' },
  { id: 'links',     label: 'Cross-tool links', icon: 'link' },
  { id: 'kv',        label: 'Settings & prefs', icon: 'tune' },
];

async function exportAll(stores) {
  const out = { version: 1, exportedAt: Date.now(), stores: {} };
  for (const s of stores) {
    out.stores[s] = await db[s].list();
  }
  return out;
}

function downloadJson(obj, filename) {
  const blob = new Blob([JSON.stringify(obj, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

function DataPanel() {
  const [selected, setSelected] = useState(() => new Set(EXPORTABLE_STORES.map(s => s.id)));
  const [counts, setCounts] = useState({});
  const [importPreview, setImportPreview] = useState(null);
  const [importMode, setImportMode] = useState('merge'); // 'merge' | 'replace'
  const [busy, setBusy] = useState(false);
  const [status, setStatus] = useState(null);

  // Load counts
  useEffect(() => {
    let mounted = true;
    Promise.all(EXPORTABLE_STORES.map(s => db[s.id].list())).then(results => {
      if (!mounted) return;
      const c = {};
      EXPORTABLE_STORES.forEach((s, i) => { c[s.id] = results[i].length; });
      setCounts(c);
    });
    return () => { mounted = false; };
  }, []);

  const toggle = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };

  const handleExport = async () => {
    setBusy(true); setStatus(null);
    try {
      const data = await exportAll([...selected]);
      const stamp = new Date().toISOString().slice(0, 10);
      downloadJson(data, `lifehub-backup-${stamp}.json`);
      setStatus({ kind: 'ok', msg: `Exported ${Object.values(data.stores).reduce((a, b) => a + b.length, 0)} records.` });
    } catch (e) {
      setStatus({ kind: 'err', msg: e.message });
    }
    setBusy(false);
  };

  const handleCopy = async () => {
    setBusy(true);
    try {
      const data = await exportAll([...selected]);
      const ok = await copyText(JSON.stringify(data, null, 2));
      setStatus(ok ? { kind: 'ok', msg: 'Copied JSON to clipboard.' } : { kind: 'err', msg: 'Copy failed.' });
    } catch (e) {
      setStatus({ kind: 'err', msg: e.message });
    }
    setBusy(false);
  };

  const onFileChosen = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    try {
      const text = await file.text();
      const parsed = JSON.parse(text);
      if (!parsed.stores || typeof parsed.stores !== 'object') throw new Error('Not a Lifehub backup file');
      const summary = Object.entries(parsed.stores).map(([k, v]) => ({ store: k, count: Array.isArray(v) ? v.length : 0 }));
      setImportPreview({ data: parsed, summary, filename: file.name });
      setStatus(null);
    } catch (err) {
      setStatus({ kind: 'err', msg: 'Invalid backup file: ' + err.message });
    }
    e.target.value = '';
  };

  const handleImport = async () => {
    if (!importPreview) return;
    const ok = await window.lhDialog.confirm({
      title: importMode === 'replace' ? 'Replace existing data?' : 'Merge backup?',
      message: importMode === 'replace'
        ? 'All current data in the selected stores will be deleted, then replaced with the backup. This cannot be undone.'
        : 'Records from the backup will be added; if an ID already exists, the backup version wins. Items not in the backup are kept.',
      confirmLabel: importMode === 'replace' ? 'Replace' : 'Merge',
      danger: importMode === 'replace',
      icon: importMode === 'replace' ? 'warning' : 'merge_type',
    });
    if (!ok) return;
    setBusy(true);
    try {
      let put = 0;
      for (const [store, items] of Object.entries(importPreview.data.stores)) {
        if (!db[store]) continue;
        if (importMode === 'replace') await db[store].clear();
        for (const item of items) {
          await db[store].put(item);
          put++;
        }
      }
      setStatus({ kind: 'ok', msg: `Imported ${put} records. Reloading…` });
      setTimeout(() => location.reload(), 1200);
    } catch (e) {
      setStatus({ kind: 'err', msg: e.message });
      setBusy(false);
    }
  };

  return (
    <div className="data-panel">
      <div className="data-section">
        <div className="data-section-head">
          <Icon name="archive" />
          <div>
            <div className="title">Export your data</div>
            <div className="sub">Download a JSON snapshot of everything in this browser. Use it as a backup or to migrate to another device.</div>
          </div>
        </div>
        <div className="data-store-list">
          {EXPORTABLE_STORES.map(s => (
            <button
              key={s.id}
              className={`data-store ${selected.has(s.id) ? 'is-on' : ''}`}
              onClick={() => toggle(s.id)}
            >
              <Icon name={s.icon} />
              <div className="data-store-body">
                <div className="data-store-label">{s.label}</div>
                <div className="data-store-count">{counts[s.id] ?? '…'} records</div>
              </div>
              <Icon name={selected.has(s.id) ? 'check_box' : 'check_box_outline_blank'} className="data-store-check" />
            </button>
          ))}
        </div>
        <div className="data-actions">
          <button className="lh-btn primary" onClick={handleExport} disabled={busy || selected.size === 0}>
            <Icon name="download" />Download .json
          </button>
          <button className="lh-btn" onClick={handleCopy} disabled={busy || selected.size === 0}>
            <Icon name="content_copy" />Copy JSON
          </button>
        </div>
      </div>

      <div className="data-section">
        <div className="data-section-head">
          <Icon name="cloud_upload" />
          <div>
            <div className="title">Import a backup</div>
            <div className="sub">Restore from a previously exported file. Merge keeps current data; replace wipes selected stores first.</div>
          </div>
        </div>
        <div className="data-import-row">
          <label className="lh-btn primary">
            <Icon name="upload_file" />Choose file
            <input type="file" accept=".json,application/json" onChange={onFileChosen} style={{ display: 'none' }} />
          </label>
          <div className="data-mode-pick">
            <button className={`enc-mode-btn ${importMode === 'merge' ? 'is-active' : ''}`} onClick={() => setImportMode('merge')}>
              <Icon name="merge_type" />Merge
            </button>
            <button className={`enc-mode-btn ${importMode === 'replace' ? 'is-active' : ''}`} onClick={() => setImportMode('replace')}>
              <Icon name="swap_horiz" />Replace
            </button>
          </div>
        </div>

        {importPreview && (
          <div className="data-preview">
            <div className="data-preview-head">
              <Icon name="description" />
              <strong>{importPreview.filename}</strong>
              <IconBtn name="close" onClick={() => setImportPreview(null)} />
            </div>
            <ul className="data-preview-list">
              {importPreview.summary.map(s => (
                <li key={s.store}>
                  <span>{s.store}</span>
                  <strong>{s.count}</strong>
                </li>
              ))}
            </ul>
            <button className="lh-btn primary" onClick={handleImport} disabled={busy}>
              <Icon name="cloud_download" />
              {importMode === 'replace' ? 'Replace selected stores' : 'Merge into current data'}
            </button>
          </div>
        )}
      </div>

      {status && (
        <div className={`data-status ${status.kind}`}>
          <Icon name={status.kind === 'ok' ? 'check_circle' : 'error'} />
          <span>{status.msg}</span>
        </div>
      )}
    </div>
  );
}

window.DataPanel = DataPanel;
