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

// ============================================================
// Theme presets — { id, name, primary, primaryLight, primaryDark }
// ============================================================
const THEME_PRESETS = [
  { id: 'violet', name: 'Violet',  primary: '#7f0df2', primaryLight: '#9b3ff7', primaryDark: '#5a06b0' },
  { id: 'blue',   name: 'Ocean',   primary: '#2563eb', primaryLight: '#3b82f6', primaryDark: '#1d4ed8' },
  { id: 'teal',   name: 'Teal',    primary: '#0d9488', primaryLight: '#14b8a6', primaryDark: '#0f766e' },
  { id: 'green',  name: 'Forest',  primary: '#16a34a', primaryLight: '#22c55e', primaryDark: '#15803d' },
  { id: 'amber',  name: 'Amber',   primary: '#d97706', primaryLight: '#f59e0b', primaryDark: '#b45309' },
  { id: 'rose',   name: 'Rose',    primary: '#e11d48', primaryLight: '#f43f5e', primaryDark: '#be123c' },
  { id: 'slate',  name: 'Graphite',primary: '#475569', primaryLight: '#64748b', primaryDark: '#334155' },
  { id: 'pink',   name: 'Magenta', primary: '#c026d3', primaryLight: '#d946ef', primaryDark: '#a21caf' },
];

const DEFAULT_SETTINGS = {
  appTitle: 'Toolio',
  brandSplit: 4, // index where the accent color starts in the title
  brandIcon: 'grid_view',
  themeId: 'violet',
  customPrimary: null, // hex when user picked custom
  mode: 'dark', // 'dark' | 'light'
  disabledTools: [], // tool ids that are turned off
};

// Tools the user can toggle on/off (Home is always on)
const TOGGLEABLE_TOOLS = [
  { id: 'todo',     label: 'Todo',        icon: 'check_box',    category: 'Productivity', desc: 'Tasks, subtasks, projects, natural-language quick-add' },
  { id: 'note',     label: 'Notes',       icon: 'description',  category: 'Productivity', desc: 'Markdown editor with backlinks and folders' },
  { id: 'bookmark', label: 'Bookmarks',   icon: 'bookmark',     category: 'Productivity', desc: 'Quick links with folders and tags' },
  { id: 'json',     label: 'JSON viewer', icon: 'data_object',  category: 'Developer',    desc: 'Tree, JSONPath, format, search' },
  { id: 'diff',     label: 'Diff viewer', icon: 'difference',   category: 'Developer',    desc: 'Compare two texts side-by-side' },
  { id: 'encode',   label: 'Encode/Decode', icon: 'enhanced_encryption', category: 'Developer', desc: 'JWT decoder, Base64 and URL encode/decode' },
  { id: 'totp',     label: '2FA codes', icon: 'lock_clock', category: 'Developer', desc: 'Generate TOTP one-time codes from 2FA keys, with a local key vault' },
  { id: 'regex',    label: 'Regex tester', icon: 'pattern',     category: 'Developer',    desc: 'Live match highlighting, capture groups, replace' },
  { id: 'cron',     label: 'Cron builder', icon: 'schedule',    category: 'Developer',    desc: 'Visual cron builder with plain-language translation' },
  { id: 'color',    label: 'Color picker', icon: 'palette',     category: 'Developer',    desc: 'HEX/RGB/HSL converter, contrast checker, palettes' },
  { id: 'convert',  label: 'Quick converter', icon: 'sync_alt', category: 'Developer',    desc: 'JSON ↔ YAML ↔ CSV, timestamps, units' },
  { id: 'journal',  label: 'Daily journal', icon: 'auto_stories', category: 'Productivity', desc: 'Date-keyed entries with prompts and auto-summary' },
  { id: 'flashcard',label: 'Flashcards',    icon: 'style',        category: 'Productivity', desc: 'Spaced-repetition study with custom card schemas' },
  { id: 'password', label: 'Passwords',   icon: 'key',          category: 'Security',     desc: 'Generator and local vault' },
  { id: 'tetris',   label: 'Block Classic', icon: 'grid_view',  category: 'Games',        desc: 'Falling-block puzzle game with hold, ghost piece, and resume' },
  { id: 'pomodoro', label: 'Pomodoro',      icon: 'timer',       category: 'Productivity', desc: 'Focus timer with break cycles, session log, and gentle audio chimes' },
  { id: 'timetracker', label: 'Time Tracker', icon: 'timelapse',  category: 'Productivity', desc: 'Track time with a one-click timer or manual entries — projects, tags, todo links, calendar and summaries' },
  { id: 'calculator', label: 'Calculator',  icon: 'calculate',   category: 'Utility',      desc: 'Arithmetic with memory, percent, history, and keyboard support' },
  { id: 'scratchpad', label: 'Scratch pad', icon: 'edit_note',   category: 'Utility',      desc: 'A single always-saved textarea for fleeting thoughts and snippets' },
  { id: 'worldclock', label: 'World clock', icon: 'public',      category: 'Utility',      desc: 'Analog + digital clocks across timezones with offset from your home zone' },
  { id: 'qr',       label: 'QR generator',  icon: 'qr_code_2',   category: 'Utility',      desc: 'Generate QR codes for text, URLs, Wi-Fi networks, contact cards, email and SMS' },
  { id: 'image',    label: 'Image tools',   icon: 'image',       category: 'Utility',      desc: 'Convert between WEBP/PNG/JPG/GIF/AVIF/SVG, resize, rotate & flip, crop, compress, BASE64, invert and black-and-white — all locally' },
  { id: 'habits',   label: 'Habits',        icon: 'check_circle', category: 'Productivity', desc: 'Track daily habits with streak counters and a 4-week grid view' },
  { id: 'mood',     label: 'Mood',          icon: 'mood',        category: 'Productivity', desc: 'One-tap daily mood check-in with a 12-week heatmap and tag-based context' },
  { id: 'breathing', label: 'Breathing',    icon: 'air',         category: 'Wellness',     desc: 'Guided breath patterns (box, 4-7-8, coherent) with an animated circle and chosen cycle counts' },
  { id: 'g2048',    label: '2048',          icon: 'grid_4x4',    category: 'Games',        desc: 'Slide and merge tiles to reach 2048. Persisted best score, undo, and touch swipe.' },
  { id: 'minesweeper', label: 'Minesweeper', icon: 'grid_on',    category: 'Games',        desc: 'The classic — three difficulties, best-time tracking, long-press to flag on mobile' },
  { id: 'reading', label: 'Reading',        icon: 'auto_stories', category: 'Productivity', desc: 'A small library: want-to-read queue, reading progress, ratings and notes' },
  { id: 'writer',  label: 'Writer',         icon: 'edit',         category: 'Productivity', desc: 'Distraction-free writing with word-count targets and session history' },
  { id: 'wordsearch', label: 'Word search', icon: 'search',       category: 'Games',        desc: 'Hunt themed words on a 12\u00d712 grid \u2014 diagonals, reversed words, timed' },
  { id: 'sudoku',  label: 'Sudoku',         icon: 'apps',         category: 'Games',        desc: 'Classic 9\u00d79 sudoku with pencil-mark notes and conflict highlighting' },
  { id: 'solitaire', label: 'Solitaire',    icon: 'style',        category: 'Games',        desc: 'Klondike solitaire, draw-one. Click to select, click a pile to move, undo, persist' },
  { id: 'ambient', label: 'Ambient',        icon: 'graphic_eq',   category: 'Wellness',     desc: 'Layered ambient sound generator (rain, ocean, fire, caf\u00e9) with a sleep timer' },
  { id: 'keytest', label: 'Keyboard test',  icon: 'keyboard',     category: 'Hardware',     desc: 'Press-test every key on a Mac or Windows layout; tested keys stay marked so you can spot a dead or sticky switch' },
  { id: 'mictest', label: 'Mic test',       icon: 'mic',          category: 'Hardware',     desc: 'Live microphone waveform and input-level meter to confirm the right input works and levels are healthy' },
  { id: 'camtest', label: 'Camera test',    icon: 'videocam',     category: 'Hardware',     desc: 'Live webcam preview with resolution, frame rate, device switching, mirror toggle and snapshot' },
  { id: 'refreshrate', label: 'Refresh rate', icon: 'speed',      category: 'Hardware',     desc: 'Measure the display\u2019s real refresh rate with a frame-time graph and a motion-smoothness sweep' },
];

// ------------------------------------------------------------
// Apply settings to :root
// ------------------------------------------------------------
function applyTheme(s) {
  const root = document.documentElement;
  const preset = THEME_PRESETS.find(p => p.id === s.themeId) || THEME_PRESETS[0];
  const primary = s.customPrimary || preset.primary;
  const lighten = shiftColor(primary, 0.18);
  const darken = shiftColor(primary, -0.22);

  root.style.setProperty('--color-primary', primary);
  root.style.setProperty('--color-primary-light', s.customPrimary ? lighten : preset.primaryLight);
  root.style.setProperty('--color-primary-dark',  s.customPrimary ? darken  : preset.primaryDark);

  // Derived primary tints — these are used in many tints across the app
  const rgb = hexToRgb(primary);
  if (rgb) {
    root.style.setProperty('--primary-rgb', `${rgb.r}, ${rgb.g}, ${rgb.b}`);
  }

  if (s.mode === 'light') {
    root.classList.remove('dark');
    root.classList.add('light');
  } else {
    root.classList.remove('light');
    root.classList.add('dark');
  }

  document.title = (s.appTitle || 'Toolio') + ' — utilities';
}

function hexToRgb(hex) {
  const m = hex.replace('#','').match(/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
  if (!m) return null;
  return { r: parseInt(m[1],16), g: parseInt(m[2],16), b: parseInt(m[3],16) };
}
function rgbToHex(r,g,b) {
  return '#' + [r,g,b].map(v => Math.max(0,Math.min(255,Math.round(v))).toString(16).padStart(2,'0')).join('');
}
function shiftColor(hex, amount) {
  const rgb = hexToRgb(hex); if (!rgb) return hex;
  // amount > 0 lightens, < 0 darkens, by mixing with white/black
  const t = Math.abs(amount);
  if (amount > 0) return rgbToHex(rgb.r + (255 - rgb.r) * t, rgb.g + (255 - rgb.g) * t, rgb.b + (255 - rgb.b) * t);
  return rgbToHex(rgb.r * (1 - t), rgb.g * (1 - t), rgb.b * (1 - t));
}

// ------------------------------------------------------------
// Hook — returns [settings, setSettings] persisted in db.kv
// ------------------------------------------------------------
function useSettings() {
  const [settings, setLocal] = useState(DEFAULT_SETTINGS);
  const [loaded, setLoaded] = useState(false);

  // Load + subscribe — re-read whenever the settings record changes
  // (e.g. catalog page writing to db.kv directly)
  useEffect(() => {
    let mounted = true;
    const load = () => db.kv.get('settings').then(rec => {
      if (!mounted) return;
      const s = { ...DEFAULT_SETTINGS, ...(rec?.v || {}) };
      setLocal(s);
      applyTheme(s);
      setLoaded(true);
    });
    load();
    const unsub = db.subscribe(({ store, kind, value }) => {
      if (store !== 'kv') return;
      // value carries the kv record on put; on clear or unknown, just reload
      if (!value || value.k === 'settings') load();
    });
    return () => { mounted = false; unsub(); };
  }, []);

  const update = useCallback((patch) => {
    setLocal(prev => {
      const next = { ...prev, ...patch };
      db.kv.put({ k: 'settings', v: next });
      applyTheme(next);
      return next;
    });
  }, []);

  return [settings, update, loaded];
}

// ============================================================
// Settings modal
// ============================================================
function SettingsModal({ open, onClose, settings, update }) {
  if (!open) return null;
  const preset = THEME_PRESETS.find(p => p.id === settings.themeId) || THEME_PRESETS[0];
  const currentColor = settings.customPrimary || preset.primary;

  const ICONS = ['grid_view','dashboard','widgets','category','workspaces','hub','space_dashboard','apps','toys','rocket_launch','flare','bolt','psychology','auto_awesome'];

  const reset = async () => {
    const ok = await window.lhDialog.confirm({
      title: 'Reset appearance?',
      message: 'Your theme, mode, branding, and tool toggles will return to defaults. Your data is not affected.',
      confirmLabel: 'Reset',
      icon: 'restart_alt',
    });
    if (!ok) return;
    update(DEFAULT_SETTINGS);
  };

  return (
    <div className="settings-overlay" onClick={onClose}>
      <div className="settings-modal" onClick={e => e.stopPropagation()}>
        <div className="settings-head">
          <Icon name="settings" />
          <h2>Settings</h2>
          <div style={{ flex: 1 }} />
          <IconBtn name="close" onClick={onClose} />
        </div>

        <div className="settings-body">
          {/* APPEARANCE MODE */}
          <SettingsSection title="Appearance" sub="How the app feels">
            <div className="settings-mode-pick">
              <button
                className={`settings-mode ${settings.mode === 'dark' ? 'is-active' : ''}`}
                onClick={() => update({ mode: 'dark' })}
              >
                <div className="settings-mode-preview is-dark">
                  <span className="dot" /><span className="bar" /><span className="bar2" />
                </div>
                <Icon name="dark_mode" />
                <span>Dark</span>
              </button>
              <button
                className={`settings-mode ${settings.mode === 'light' ? 'is-active' : ''}`}
                onClick={() => update({ mode: 'light' })}
              >
                <div className="settings-mode-preview is-light">
                  <span className="dot" /><span className="bar" /><span className="bar2" />
                </div>
                <Icon name="light_mode" />
                <span>Light</span>
              </button>
            </div>
          </SettingsSection>

          {/* ACCENT COLOR */}
          <SettingsSection title="Accent color" sub="Used for buttons, highlights, active states">
            <div className="settings-swatches">
              {THEME_PRESETS.map(t => (
                <button
                  key={t.id}
                  className={`settings-swatch ${!settings.customPrimary && settings.themeId === t.id ? 'is-active' : ''}`}
                  style={{ background: t.primary }}
                  onClick={() => update({ themeId: t.id, customPrimary: null })}
                  title={t.name}
                >
                  {!settings.customPrimary && settings.themeId === t.id && <Icon name="check" />}
                </button>
              ))}
              <label className={`settings-swatch is-custom ${settings.customPrimary ? 'is-active' : ''}`} title="Custom">
                <input
                  type="color"
                  value={currentColor}
                  onChange={e => update({ customPrimary: e.target.value })}
                />
                <Icon name="colorize" />
              </label>
            </div>
            <div className="settings-color-meta">
              <code>{currentColor.toUpperCase()}</code>
              {settings.customPrimary && (
                <button className="lh-chip" onClick={() => update({ customPrimary: null })}>
                  <Icon name="restart_alt" />Use preset
                </button>
              )}
            </div>
          </SettingsSection>

          {/* BRAND */}
          <SettingsSection title="Branding" sub="App name and icon">
            <div className="settings-row">
              <label>App title</label>
              <input
                className="lh-input"
                value={settings.appTitle}
                maxLength={24}
                onChange={e => update({ appTitle: e.target.value })}
                placeholder="Toolio"
              />
            </div>
            <div className="settings-row">
              <label>Accent split</label>
              <div className="settings-split-control">
                <input
                  type="range"
                  min="0"
                  max={(settings.appTitle || '').length}
                  value={Math.min(settings.brandSplit, (settings.appTitle || '').length)}
                  onChange={e => update({ brandSplit: parseInt(e.target.value, 10) })}
                />
                <div className="settings-split-preview">
                  <span style={{ color: 'var(--text-hi)' }}>
                    {(settings.appTitle || '').slice(0, settings.brandSplit)}
                  </span>
                  <span style={{ color: 'var(--color-primary)' }}>
                    {(settings.appTitle || '').slice(settings.brandSplit)}
                  </span>
                </div>
              </div>
            </div>
            <div className="settings-row">
              <label>Brand icon</label>
              <div className="settings-icons">
                {ICONS.map(ic => (
                  <button
                    key={ic}
                    className={`settings-icon-btn ${settings.brandIcon === ic ? 'is-active' : ''}`}
                    onClick={() => update({ brandIcon: ic })}
                  >
                    <Icon name={ic} />
                  </button>
                ))}
              </div>
            </div>
          </SettingsSection>

          {/* TOOLS */}
          <SettingsSection title="Tools" sub="Manage which tools appear in the app. Disabled tools and their data are hidden from navigation, search, home, and send-to.">
            <ToolsManager settings={settings} update={update} />
          </SettingsSection>

          {/* DATA */}
          <SettingsSection title="Data" sub="Backup, import, or wipe your local data">
            {window.DataPanel && <window.DataPanel />}
            <div className="settings-actions" style={{ marginTop: 16, paddingTop: 16, borderTop: '1px solid var(--color-border)' }}>
              <button className="lh-btn ghost" onClick={reset}>
                <Icon name="restart_alt" />Reset appearance
              </button>
              <button
                className="lh-btn danger"
                onClick={async () => {
                  const ok = await window.lhDialog.confirm({
                    title: 'Wipe all data?',
                    message: 'This permanently deletes every todo, note, JSON document, bookmark, password and setting stored in this browser. This action cannot be undone.',
                    confirmLabel: 'Wipe everything',
                    danger: true,
                    icon: 'delete_forever',
                  });
                  if (!ok) return;
                  for (const s of ['todos','notes','jsonDocs','bookmarks','diffs','passwords','links','kv']) {
                    await db[s].clear();
                  }
                  location.reload();
                }}
              >
                <Icon name="delete_forever" />Wipe all data
              </button>
            </div>
          </SettingsSection>
        </div>
      </div>
    </div>
  );
}

function SettingsSection({ title, sub, children }) {
  return (
    <section className="settings-section">
      <header>
        <h3>{title}</h3>
        {sub && <p>{sub}</p>}
      </header>
      <div className="settings-section-body">{children}</div>
    </section>
  );
}

// ============================================================
// Tools manager — scalable to 100+ tools
// Compact list · search · category groups · per-tool detail panel
// ============================================================
function ToolsManager({ settings, update }) {
  const [search, setSearch] = useState('');
  const [expandedId, setExpandedId] = useState(null);

  const disabled = settings.disabledTools || [];
  const isOn = (id) => !disabled.includes(id);
  const toggle = (id) => {
    const next = isOn(id) ? [...disabled, id] : disabled.filter(x => x !== id);
    update({ disabledTools: next });
  };

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return TOGGLEABLE_TOOLS;
    return TOGGLEABLE_TOOLS.filter(t =>
      t.label.toLowerCase().includes(q) ||
      t.desc.toLowerCase().includes(q) ||
      t.category.toLowerCase().includes(q)
    );
  }, [search]);

  const grouped = useMemo(() => {
    const map = new Map();
    for (const t of filtered) {
      if (!map.has(t.category)) map.set(t.category, []);
      map.get(t.category).push(t);
    }
    return Array.from(map.entries());
  }, [filtered]);

  const onCount = TOGGLEABLE_TOOLS.length - disabled.length;
  const totalCount = TOGGLEABLE_TOOLS.length;

  const runSetupAgain = async () => {
    const ok = await window.lhDialog.confirm({
      title: 'Run setup again?',
      message: 'You\'ll see the welcome flow and can re-pick which tools are enabled. Your data is not affected.',
      confirmLabel: 'Run setup',
      icon: 'restart_alt',
    });
    if (!ok) return;
    await db.kv.delete('onboardingComplete');
    location.reload();
  };

  return (
    <div className="tools-mgr">
      <div className="tools-mgr-head">
        <div className="tools-mgr-search">
          <Icon name="search" />
          <input
            placeholder="Search tools…"
            value={search}
            onChange={e => setSearch(e.target.value)}
          />
          {search && <button className="tools-mgr-clear" onClick={() => setSearch('')}><Icon name="close" /></button>}
        </div>
        <div className="tools-mgr-summary">
          <strong>{onCount}</strong> of {totalCount} enabled
        </div>
        <button className="lh-btn ghost tools-mgr-rerun" onClick={runSetupAgain} title="Re-run the welcome flow">
          <Icon name="restart_alt" />
          Run setup again
        </button>
      </div>

      <div className="tools-mgr-list">
        {grouped.length === 0 ? (
          <div className="tools-mgr-empty">
            <Icon name="search_off" />
            <span>No tools match "{search}"</span>
          </div>
        ) : grouped.map(([cat, tools]) => (
          <div key={cat} className="tools-mgr-group">
            <div className="tools-mgr-group-label">{cat}</div>
            {tools.map(t => (
              <ToolRow
                key={t.id}
                tool={t}
                on={isOn(t.id)}
                expanded={expandedId === t.id}
                onToggle={() => toggle(t.id)}
                onExpand={() => setExpandedId(expandedId === t.id ? null : t.id)}
              />
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

function ToolRow({ tool, on, expanded, onToggle, onExpand }) {
  return (
    <div className={`tool-row-card ${on ? 'is-on' : 'is-off'} ${expanded ? 'is-expanded' : ''}`}>
      <button className="tool-row-main" onClick={onExpand}>
        <div className="tool-row-icon">
          <Icon name={tool.icon} />
        </div>
        <div className="tool-row-meta">
          <div className="tool-row-label">{tool.label}</div>
          <div className="tool-row-desc">{tool.desc}</div>
        </div>
        <div
          className={`tool-row-toggle ${on ? 'is-on' : ''}`}
          onClick={(e) => { e.stopPropagation(); onToggle(); }}
          role="switch"
          aria-checked={on}
        >
          <span className="tool-row-toggle-dot" />
        </div>
        <Icon name={expanded ? 'expand_less' : 'expand_more'} className="tool-row-chevron" />
      </button>
      {expanded && (
        <div className="tool-row-detail">
          {window.toolSettingsRegistry?.[tool.id] ? (
            React.createElement(window.toolSettingsRegistry[tool.id])
          ) : (
            <div className="tool-row-detail-empty">
              <Icon name="tune" />
              <div>
                <div className="title">No additional settings yet</div>
                <div className="sub">Tool-specific configuration will appear here in a future update.</div>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { useSettings, SettingsModal, applyTheme, DEFAULT_SETTINGS, TOGGLEABLE_TOOLS });
