<script lang="ts">
  import { onMount } from 'svelte';
  import { type ThemeId, type ThemePalette, THEME_LIST, PALETTE_KEYS } from '../styles/themes';
  import { previewPalette, clearPreview, setCustomTheme } from '../stores/theme.svelte';
  import {
    type CustomTheme, createFromBase, exportThemeJson, importThemeJson,
    loadCustomThemes, saveCustomThemes
  } from '../styles/custom-themes';
  import { handleError } from '../utils/handle-error';

  let { editingTheme = $bindable<CustomTheme | null>(null), onclose }: {
    editingTheme?: CustomTheme | null;
    onclose: () => void;
  } = $props();

  let name = $state('');
  let baseTheme = $state<ThemeId>('mocha');
  let palette = $state<ThemePalette>({} as ThemePalette);
  let baseOpen = $state(false);

  const ACCENT_KEYS: (keyof ThemePalette)[] = [
    'rosewater','flamingo','pink','mauve','red','maroon','peach',
    'yellow','green','teal','sky','sapphire','blue','lavender',
  ];
  const NEUTRAL_KEYS: (keyof ThemePalette)[] = [
    'text','subtext1','subtext0','overlay2','overlay1','overlay0',
    'surface2','surface1','surface0','base','mantle','crust',
  ];

  onMount(() => {
    if (editingTheme) {
      name = editingTheme.label;
      baseTheme = editingTheme.baseTheme;
      palette = { ...editingTheme.palette };
    } else {
      name = 'My Theme';
      palette = { ...createFromBase('', baseTheme).palette };
    }
    previewPalette(palette);
  });

  function updateColor(key: keyof ThemePalette, value: string) {
    palette[key] = value;
    previewPalette({ ...palette });
  }

  function handleHexInput(key: keyof ThemePalette, value: string) {
    const v = value.startsWith('#') ? value : `#${value}`;
    if (/^#[0-9a-fA-F]{6}$/.test(v)) updateColor(key, v);
  }

  function cloneFrom(themeId: ThemeId) {
    baseTheme = themeId;
    const fresh = createFromBase(name, themeId);
    palette = { ...fresh.palette };
    baseOpen = false;
    previewPalette({ ...palette });
  }

  async function handleSave() {
    if (!name.trim()) return;
    const customs = await loadCustomThemes();
    const theme: CustomTheme = {
      id: editingTheme?.id ?? `custom:${Date.now()}`,
      label: name.trim(),
      baseTheme,
      isDark: true,
      palette: { ...palette },
    };
    const idx = customs.findIndex(c => c.id === theme.id);
    if (idx >= 0) customs[idx] = theme; else customs.push(theme);
    await saveCustomThemes(customs);
    await setCustomTheme(theme.id, theme.palette);
    editingTheme = null;
    onclose();
  }

  function handleCancel() {
    clearPreview();
    editingTheme = null;
    onclose();
  }

  function handleExport() {
    const theme: CustomTheme = {
      id: editingTheme?.id ?? 'export',
      label: name, baseTheme, isDark: true, palette: { ...palette },
    };
    const json = exportThemeJson(theme);
    const blob = new Blob([json], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = `${name.replace(/\s+/g, '-').toLowerCase()}.json`;
    a.click();
    URL.revokeObjectURL(url);
  }

  function handleImport() {
    const input = document.createElement('input');
    input.type = 'file'; input.accept = '.json';
    input.onchange = async () => {
      const file = input.files?.[0];
      if (!file) return;
      try {
        const text = await file.text();
        const imported = importThemeJson(text);
        name = imported.label;
        palette = { ...imported.palette };
        previewPalette({ ...palette });
      } catch (e) {
        handleError(e, 'themeEditor.import', 'import the theme');
      }
    };
    input.click();
  }
</script>

<div class="editor">
  <div class="header">
    <h3>Theme Editor</h3>
    <div class="name-row">
      <label class="lbl">Name</label>
      <input type="text" class="name-input" bind:value={name} placeholder="Theme name" />
    </div>
    <div class="base-row">
      <label class="lbl">Base</label>
      <div class="dropdown" class:open={baseOpen}>
        <button class="dropdown-btn" onclick={(e) => { e.stopPropagation(); baseOpen = !baseOpen; }}>
          {THEME_LIST.find(t => t.id === baseTheme)?.label ?? baseTheme}
        </button>
        {#if baseOpen}
          <div class="dropdown-menu">
            {#each THEME_LIST as t}
              <button class="dropdown-item" onclick={() => cloneFrom(t.id)}>{t.label}</button>
            {/each}
          </div>
        {/if}
      </div>
    </div>
  </div>

  <div class="colors-scroll">
    <details class="group" open>
      <summary>Accents ({ACCENT_KEYS.length})</summary>
      <div class="color-grid">
        {#each ACCENT_KEYS as key}
          <div class="color-row">
            <label class="color-label">{key}</label>
            <input type="color" value={palette[key] ?? '#000000'}
              oninput={(e) => updateColor(key, (e.target as HTMLInputElement).value)} />
            <input type="text" class="hex-input" value={palette[key] ?? ''}
              onchange={(e) => handleHexInput(key, (e.target as HTMLInputElement).value)} />
          </div>
        {/each}
      </div>
    </details>

    <details class="group" open>
      <summary>Neutrals ({NEUTRAL_KEYS.length})</summary>
      <div class="color-grid">
        {#each NEUTRAL_KEYS as key}
          <div class="color-row">
            <label class="color-label">{key}</label>
            <input type="color" value={palette[key] ?? '#000000'}
              oninput={(e) => updateColor(key, (e.target as HTMLInputElement).value)} />
            <input type="text" class="hex-input" value={palette[key] ?? ''}
              onchange={(e) => handleHexInput(key, (e.target as HTMLInputElement).value)} />
          </div>
        {/each}
      </div>
    </details>
  </div>

  <div class="footer">
    <div class="footer-left">
      <button class="btn" onclick={handleImport}>Import</button>
      <button class="btn" onclick={handleExport}>Export</button>
    </div>
    <div class="footer-right">
      <button class="btn" onclick={handleCancel}>Cancel</button>
      <button class="btn primary" onclick={handleSave} disabled={!name.trim()}>Save</button>
    </div>
  </div>
</div>

<style>
  .editor { display: flex; flex-direction: column; height: 100%; gap: 0.75rem; }
  .header { display: flex; flex-direction: column; gap: 0.5rem; }
  h3 { margin: 0; color: var(--ctp-text); font-size: 1rem; }
  .name-row, .base-row { display: flex; align-items: center; gap: 0.5rem; }
  .lbl { color: var(--ctp-subtext0); font-size: 0.75rem; text-transform: uppercase; width: 3rem; flex-shrink: 0; }
  .name-input { flex: 1; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1);
    color: var(--ctp-text); padding: 0.35rem 0.5rem; border-radius: 0.25rem; font-size: 0.85rem; }
  .name-input:focus { outline: none; border-color: var(--ctp-blue); }
  .dropdown { position: relative; flex: 1; }
  .dropdown-btn { width: 100%; text-align: left; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1);
    color: var(--ctp-text); padding: 0.35rem 0.5rem; border-radius: 0.25rem; cursor: pointer; font-size: 0.85rem; }
  .dropdown-menu { position: absolute; top: 100%; left: 0; right: 0; z-index: 50;
    background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
    max-height: 12rem; overflow-y: auto; }
  .dropdown-item { display: block; width: 100%; text-align: left; padding: 0.3rem 0.5rem;
    background: none; border: none; color: var(--ctp-text); cursor: pointer; font-size: 0.8rem; }
  .dropdown-item:hover { background: var(--ctp-surface1); }
  .colors-scroll { flex: 1; overflow-y: auto; min-height: 0; }
  .group { margin-bottom: 0.5rem; }
  .group summary { color: var(--ctp-subtext0); font-size: 0.75rem; text-transform: uppercase;
    cursor: pointer; padding: 0.25rem 0; user-select: none; }
  .color-grid { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.25rem 0; }
  .color-row { display: flex; align-items: center; gap: 0.5rem; }
  .color-label { width: 5.5rem; color: var(--ctp-subtext1); font-size: 0.8rem; flex-shrink: 0; }
  input[type="color"] { width: 2rem; height: 1.5rem; border: 1px solid var(--ctp-surface1);
    border-radius: 0.2rem; cursor: pointer; padding: 0; background: none; }
  input[type="color"]::-webkit-color-swatch-wrapper { padding: 1px; }
  input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0.15rem; }
  .hex-input { width: 5rem; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1);
    color: var(--ctp-text); padding: 0.2rem 0.35rem; border-radius: 0.2rem; font-family: monospace; font-size: 0.8rem; }
  .hex-input:focus { outline: none; border-color: var(--ctp-blue); }
  .footer { display: flex; justify-content: space-between; gap: 0.5rem; padding-top: 0.5rem;
    border-top: 1px solid var(--ctp-surface0); }
  .footer-left, .footer-right { display: flex; gap: 0.35rem; }
  .btn { padding: 0.35rem 0.75rem; border-radius: 0.25rem; border: 1px solid var(--ctp-surface1);
    background: var(--ctp-surface0); color: var(--ctp-text); cursor: pointer; font-size: 0.8rem; }
  .btn:hover { background: var(--ctp-surface1); }
  .btn.primary { background: var(--ctp-blue); color: var(--ctp-crust); border-color: var(--ctp-blue); }
  .btn.primary:hover { opacity: 0.9; }
  .btn:disabled { opacity: 0.4; cursor: not-allowed; }
</style>
