<script lang="ts">
  import { onMount } from 'svelte';
  import { getCurrentTheme, setTheme, setCustomTheme } from '../../stores/theme.svelte';
  import { THEME_LIST, getPalette, type ThemeId } from '../../styles/themes';
  import { getSetting, setSetting } from '../../adapters/settings-bridge';
  import { handleError } from '../../utils/handle-error';
  import { type CustomTheme, loadCustomThemes, deleteCustomTheme as deleteCustom, saveCustomThemes } from '../../styles/custom-themes';
  import ThemeEditor from '../ThemeEditor.svelte';

  const UI_FONTS = [
    { value: '', label: 'System Default' },
    { value: 'Inter', label: 'Inter' },
    { value: 'IBM Plex Sans', label: 'IBM Plex Sans' },
    { value: 'Noto Sans', label: 'Noto Sans' },
    { value: 'Roboto', label: 'Roboto' },
    { value: 'Source Sans 3', label: 'Source Sans 3' },
    { value: 'Ubuntu', label: 'Ubuntu' },
    { value: 'JetBrains Mono', label: 'JetBrains Mono' },
    { value: 'Fira Code', label: 'Fira Code' },
  ];
  const TERM_FONTS = [
    { value: '', label: 'Default (JetBrains Mono)' },
    { value: 'JetBrains Mono', label: 'JetBrains Mono' },
    { value: 'Fira Code', label: 'Fira Code' },
    { value: 'Cascadia Code', label: 'Cascadia Code' },
    { value: 'Source Code Pro', label: 'Source Code Pro' },
    { value: 'IBM Plex Mono', label: 'IBM Plex Mono' },
    { value: 'Hack', label: 'Hack' },
    { value: 'Inconsolata', label: 'Inconsolata' },
    { value: 'Ubuntu Mono', label: 'Ubuntu Mono' },
    { value: 'monospace', label: 'monospace' },
  ];

  let selectedTheme = $state<ThemeId>(getCurrentTheme());
  let uiFont = $state('');
  let uiFontSize = $state('14');
  let termFont = $state('');
  let termFontSize = $state('14');
  let cursorStyle = $state('block');
  let cursorBlink = $state(true);
  let scrollbackLines = $state('1000');
  let loadError = $state('');
  let themeOpen = $state(false);
  let uiFontOpen = $state(false);
  let termFontOpen = $state(false);
  let customThemes = $state<CustomTheme[]>([]);
  let editorOpen = $state(false);
  let editingTheme = $state<CustomTheme | null>(null);

  let themeGroups = $derived.by(() => {
    const map = new Map<string, typeof THEME_LIST>();
    for (const t of THEME_LIST) {
      if (!map.has(t.group)) map.set(t.group, []);
      map.get(t.group)!.push(t);
    }
    return [...map.entries()];
  });
  let themeLabel = $derived(THEME_LIST.find(t => t.id === selectedTheme)?.label ?? selectedTheme);
  let uiFontLabel = $derived(UI_FONTS.find(f => f.value === uiFont)?.label ?? 'System Default');
  let termFontLabel = $derived(TERM_FONTS.find(f => f.value === termFont)?.label ?? 'Default (JetBrains Mono)');

  function css(prop: string, val: string) { document.documentElement.style.setProperty(prop, val); }

  onMount(async () => {
    const results = await Promise.allSettled([
      getSetting('ui_font_family'), getSetting('ui_font_size'),
      getSetting('term_font_family'), getSetting('term_font_size'),
      getSetting('term_cursor_style'), getSetting('term_cursor_blink'),
      getSetting('term_scrollback'),
    ]);
    let failCount = 0;
    if (results[0].status === 'fulfilled' && results[0].value) uiFont = results[0].value; else failCount++;
    if (results[1].status === 'fulfilled' && results[1].value) uiFontSize = results[1].value; else failCount++;
    if (results[2].status === 'fulfilled' && results[2].value) termFont = results[2].value; else failCount++;
    if (results[3].status === 'fulfilled' && results[3].value) termFontSize = results[3].value; else failCount++;
    if (results[4].status === 'fulfilled' && results[4].value) cursorStyle = results[4].value; else failCount++;
    if (results[5].status === 'fulfilled') cursorBlink = results[5].value !== 'false'; else failCount++;
    if (results[6].status === 'fulfilled' && results[6].value) scrollbackLines = results[6].value; else failCount++;
    if (failCount === results.length) loadError = 'Could not load settings. Displaying defaults.';
    customThemes = await loadCustomThemes();
  });

  function pickTheme(id: ThemeId) { selectedTheme = id; themeOpen = false; setTheme(id); }
  function pickCustomTheme(ct: CustomTheme) { themeOpen = false; setCustomTheme(ct.id, ct.palette); }
  function startNewTheme() { editingTheme = null; editorOpen = true; closeDropdowns(); }
  function startEditTheme(ct: CustomTheme) { editingTheme = ct; editorOpen = true; closeDropdowns(); }
  async function removeCustomTheme(id: string) {
    customThemes = await deleteCustom(customThemes, id);
  }
  async function closeEditor() { editorOpen = false; customThemes = await loadCustomThemes(); }
  async function save(key: string, value: string) {
    try { await setSetting(key, value); } catch (e) { handleError(e, `settings.save.${key}`, 'save your settings'); }
  }
  function pickUiFont(val: string) {
    uiFont = val; uiFontOpen = false;
    css('--ui-font-family', val ? `'${val}', sans-serif` : 'system-ui, sans-serif');
    save('ui_font_family', val);
  }
  function pickTermFont(val: string) {
    termFont = val; termFontOpen = false;
    css('--term-font-family', val ? `'${val}', monospace` : `'JetBrains Mono', monospace`);
    save('term_font_family', val);
  }
  function stepUiSize(delta: number) {
    const n = parseInt(uiFontSize, 10) + delta;
    if (n < 8 || n > 24) return;
    uiFontSize = String(n); css('--ui-font-size', `${n}px`); save('ui_font_size', String(n));
  }
  function stepTermSize(delta: number) {
    const n = parseInt(termFontSize, 10) + delta;
    if (n < 8 || n > 24) return;
    termFontSize = String(n); css('--term-font-size', `${n}px`); save('term_font_size', String(n));
  }
  function setCursor(style: string) { cursorStyle = style; save('term_cursor_style', style); }
  function toggleBlink() { cursorBlink = !cursorBlink; save('term_cursor_blink', String(cursorBlink)); }
  function setScrollback(val: string) {
    const n = parseInt(val, 10);
    if (isNaN(n) || n < 100 || n > 100000) return;
    scrollbackLines = val; save('term_scrollback', val);
  }

  function closeDropdowns() { themeOpen = false; uiFontOpen = false; termFontOpen = false; }

  function handleClick(e: MouseEvent) {
    const target = e.target as HTMLElement;
    if (!target.closest('.custom-dropdown')) closeDropdowns();
  }

  function handleKey(e: KeyboardEvent) {
    if (e.key === 'Escape') closeDropdowns();
  }
</script>

<div class="appearance" onclick={handleClick} onkeydown={handleKey}>
  {#if loadError}<p class="load-error">{loadError}</p>{/if}
  <h3>Theme</h3>
  <div class="field" id="setting-theme">
    <div class="custom-dropdown">
      <button class="dropdown-btn" onclick={() => { uiFontOpen = false; termFontOpen = false; themeOpen = !themeOpen; }}
        aria-haspopup="listbox" aria-expanded={themeOpen}>
        <span class="theme-colors">
          <span class="color-dot" style="background: {getPalette(selectedTheme).red};"></span>
          <span class="color-dot" style="background: {getPalette(selectedTheme).green};"></span>
          <span class="color-dot" style="background: {getPalette(selectedTheme).blue};"></span>
          <span class="color-dot" style="background: {getPalette(selectedTheme).yellow};"></span>
        </span>
        {themeLabel}
      </button>
      {#if themeOpen}
        <div class="dropdown-menu theme-menu" role="listbox">
          {#each themeGroups as [group, themes]}
            <div class="group-label">{group}</div>
            {#each themes as t}
              <button class="dropdown-item" class:active={t.id === selectedTheme} onclick={() => pickTheme(t.id)}>
                <span class="theme-colors">
                  <span class="color-dot" style="background: {getPalette(t.id).red};"></span>
                  <span class="color-dot" style="background: {getPalette(t.id).green};"></span>
                  <span class="color-dot" style="background: {getPalette(t.id).blue};"></span>
                  <span class="color-dot" style="background: {getPalette(t.id).yellow};"></span>
                </span>
                {t.label}
              </button>
            {/each}
          {/each}
        </div>
      {/if}
    </div>
  </div>

  {#if editorOpen}
    <ThemeEditor bind:editingTheme onclose={closeEditor} />
  {:else}
    {#if customThemes.length > 0}
      <div class="custom-themes">
        {#each customThemes as ct}
          <div class="custom-theme-row">
            <button class="custom-theme-btn" onclick={() => pickCustomTheme(ct)}>
              <span class="color-dot" style="background: {ct.palette.blue};"></span>
              <span class="color-dot" style="background: {ct.palette.green};"></span>
              {ct.label}
            </button>
            <button class="icon-btn" onclick={() => startEditTheme(ct)} aria-label="Edit {ct.label}">✎</button>
            <button class="icon-btn danger" onclick={() => removeCustomTheme(ct.id)} aria-label="Delete {ct.label}">✕</button>
          </div>
        {/each}
      </div>
    {/if}
    <button class="new-theme-btn" onclick={startNewTheme}>+ New Custom Theme</button>
  {/if}

  <h3>UI Font</h3>
  <div class="field row" id="setting-ui-font">
    <div class="custom-dropdown flex1">
      <button class="dropdown-btn" onclick={() => { themeOpen = false; termFontOpen = false; uiFontOpen = !uiFontOpen; }}>{uiFontLabel}</button>
      {#if uiFontOpen}
        <div class="dropdown-menu">
          {#each UI_FONTS as f}
            <button class="dropdown-item" class:active={f.value === uiFont} onclick={() => pickUiFont(f.value)}>{f.label}</button>
          {/each}
        </div>
      {/if}
    </div>
    <div class="stepper" id="setting-ui-font-size">
      <button onclick={() => stepUiSize(-1)} aria-label="Decrease UI font size">-</button>
      <span>{uiFontSize}px</span>
      <button onclick={() => stepUiSize(1)} aria-label="Increase UI font size">+</button>
    </div>
  </div>

  <h3>Terminal Font</h3>
  <div class="field row" id="setting-term-font">
    <div class="custom-dropdown flex1">
      <button class="dropdown-btn" onclick={() => { themeOpen = false; uiFontOpen = false; termFontOpen = !termFontOpen; }}>{termFontLabel}</button>
      {#if termFontOpen}
        <div class="dropdown-menu">
          {#each TERM_FONTS as f}
            <button class="dropdown-item" class:active={f.value === termFont} onclick={() => pickTermFont(f.value)}>{f.label}</button>
          {/each}
        </div>
      {/if}
    </div>
    <div class="stepper" id="setting-term-font-size">
      <button onclick={() => stepTermSize(-1)} aria-label="Decrease terminal font size">-</button>
      <span>{termFontSize}px</span>
      <button onclick={() => stepTermSize(1)} aria-label="Increase terminal font size">+</button>
    </div>
  </div>

  <h3>Terminal Cursor</h3>
  <div class="field row" id="setting-cursor-style">
    <div class="segmented">
      {#each ['block', 'line', 'underline'] as s}
        <button class:active={cursorStyle === s} onclick={() => setCursor(s)}>{s[0].toUpperCase() + s.slice(1)}</button>
      {/each}
    </div>
    <label class="toggle-label" id="setting-cursor-blink">
      <span>Blink</span>
      <button class="toggle" class:on={cursorBlink} onclick={toggleBlink} aria-label="Toggle cursor blink">{cursorBlink ? 'On' : 'Off'}</button>
    </label>
  </div>

  <h3>Scrollback</h3>
  <div class="field" id="setting-scrollback">
    <input type="number" min="100" max="100000" step="100" bind:value={scrollbackLines}
      onchange={() => setScrollback(scrollbackLines)} aria-label="Scrollback lines" />
    <span class="hint">lines (100–100,000)</span>
  </div>
</div>

<style>
  .load-error { font-size: 0.75rem; color: var(--ctp-peach); margin: 0 0 0.25rem; }
  .appearance { display: flex; flex-direction: column; gap: 0.75rem; }
  h3 { font-size: 0.75rem; font-weight: 600; color: var(--ctp-subtext0); text-transform: uppercase; letter-spacing: 0.05em; margin: 0.5rem 0 0.125rem; }
  .field { position: relative; }
  .row { display: flex; align-items: center; gap: 0.5rem; }
  .flex1 { flex: 1; }
  .custom-dropdown { position: relative; }
  .dropdown-btn { width: 100%; padding: 0.375rem 0.625rem; background: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 0.25rem; color: var(--ctp-text); font-size: 0.8125rem; text-align: left; cursor: pointer; display: flex; align-items: center; gap: 0.375rem; }
  .dropdown-btn:hover { border-color: var(--ctp-surface1); }
  .dropdown-menu { position: absolute; top: 100%; left: 0; right: 0; z-index: 50; background: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 0.25rem; max-height: 16rem; overflow-y: auto; margin-top: 0.125rem; }
  .theme-menu { min-width: 14rem; }
  .dropdown-item { display: flex; align-items: center; gap: 0.375rem; width: 100%; padding: 0.3125rem 0.625rem; background: none; border: none; color: var(--ctp-text); font-size: 0.8125rem; cursor: pointer; text-align: left; }
  .dropdown-item:hover { background: var(--ctp-surface0); }
  .dropdown-item.active { color: var(--ctp-blue); }
  .group-label { padding: 0.25rem 0.625rem; font-size: 0.6875rem; color: var(--ctp-overlay0); font-weight: 600; text-transform: uppercase; }
  .color-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; }
  .theme-colors { display: flex; gap: 0.1875rem; }
  .stepper { display: flex; align-items: center; gap: 0.25rem; }
  .stepper button { width: 1.5rem; height: 1.5rem; background: var(--ctp-surface0); border: none; border-radius: 0.1875rem; color: var(--ctp-text); cursor: pointer; font-size: 0.875rem; display: flex; align-items: center; justify-content: center; }
  .stepper button:hover { background: var(--ctp-surface1); }
  .stepper span { font-size: 0.8125rem; min-width: 2.5rem; text-align: center; color: var(--ctp-subtext0); }
  .segmented { display: flex; gap: 1px; background: var(--ctp-surface0); border-radius: 0.25rem; overflow: hidden; }
  .segmented button { flex: 1; padding: 0.3125rem 0.5rem; background: var(--ctp-mantle); border: none; color: var(--ctp-subtext0); font-size: 0.75rem; cursor: pointer; }
  .segmented button:hover { background: var(--ctp-surface0); }
  .segmented button.active { background: var(--ctp-blue); color: var(--ctp-base); }
  .toggle-label { display: flex; align-items: center; gap: 0.375rem; font-size: 0.8125rem; color: var(--ctp-subtext0); }
  .toggle { padding: 0.1875rem 0.5rem; background: var(--ctp-surface0); border: none; border-radius: 0.1875rem; color: var(--ctp-subtext0); cursor: pointer; font-size: 0.75rem; }
  .toggle.on { background: var(--ctp-green); color: var(--ctp-base); }
  input[type="number"] { width: 5rem; padding: 0.375rem 0.5rem; background: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 0.25rem; color: var(--ctp-text); font-size: 0.8125rem; }
  input[type="number"]:focus { border-color: var(--ctp-blue); outline: none; }
  .hint { font-size: 0.6875rem; color: var(--ctp-overlay0); margin-left: 0.5rem; }
  .custom-themes { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.25rem; }
  .custom-theme-row { display: flex; align-items: center; gap: 0.25rem; }
  .custom-theme-btn { flex: 1; display: flex; align-items: center; gap: 0.375rem; padding: 0.3rem 0.5rem;
    background: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 0.25rem;
    color: var(--ctp-text); font-size: 0.8rem; cursor: pointer; text-align: left; }
  .custom-theme-btn:hover { border-color: var(--ctp-surface1); }
  .icon-btn { background: none; border: none; color: var(--ctp-overlay0); cursor: pointer; font-size: 0.85rem;
    padding: 0.2rem; border-radius: 0.15rem; }
  .icon-btn:hover { color: var(--ctp-text); background: var(--ctp-surface0); }
  .icon-btn.danger:hover { color: var(--ctp-red); }
  .new-theme-btn { margin-top: 0.25rem; padding: 0.3rem 0.5rem; background: none;
    border: 1px dashed var(--ctp-surface1); border-radius: 0.25rem; color: var(--ctp-overlay1);
    font-size: 0.8rem; cursor: pointer; }
  .new-theme-btn:hover { border-color: var(--ctp-blue); color: var(--ctp-blue); }
</style>
