<script lang="ts">
  import { appRpc } from '../rpc.ts';
  import { themeStore } from '../theme-store.svelte.ts';
  import { CSS_VAR_MAP, getPalette, applyCssVars, type ThemePalette, type ThemeId } from '../themes.ts';

  interface Props {
    baseThemeId: ThemeId;
    /** Seed palette — passed from parent so $state init avoids a reactive read. */
    initialPalette: ThemePalette;
    onSave: (id: string, name: string) => void;
    onCancel: () => void;
  }

  let { baseThemeId, initialPalette, onSave, onCancel }: Props = $props();

  // ── Palette color keys in two groups ──────────────────────────────────────

  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',
  ];

  // ── State ─────────────────────────────────────────────────────────────────

  // initialPalette is passed by value from the parent — safe to spread here.
  let palette = $state<ThemePalette>({ ...initialPalette });
  let themeName = $state('My Custom Theme');
  let saving = $state(false);
  let nameError = $state('');

  // ── Apply live preview as colors change ───────────────────────────────────

  function applyPreview() {
    const style = document.documentElement.style;
    for (const [varName, key] of CSS_VAR_MAP) {
      style.setProperty(varName, palette[key]);
    }
  }

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

  function resetToBase() {
    palette = { ...initialPalette };
    applyPreview();
  }

  async function handleSave() {
    if (!themeName.trim()) { nameError = 'Theme name is required'; return; }
    nameError = '';
    saving = true;
    const id = `custom-${Date.now()}`;
    const palObj: Record<string, string> = {};
    for (const [, key] of CSS_VAR_MAP) palObj[key] = palette[key];
    try {
      await appRpc?.request['themes.saveCustom']({ id, name: themeName.trim(), palette: palObj });
      onSave(id, themeName.trim());
    } catch (err) {
      console.error('[ThemeEditor] save failed:', err);
    } finally {
      saving = false;
    }
  }

  function handleCancel() {
    // Revert CSS vars to previous theme
    applyCssVars(themeStore.currentTheme);
    onCancel();
  }

  function exportTheme() {
    const palObj: Record<string, string> = {};
    for (const [, key] of CSS_VAR_MAP) palObj[key] = palette[key];
    const data = JSON.stringify({ name: themeName, palette: palObj }, null, 2);
    const blob = new Blob([data], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = `${themeName.replace(/\s+/g, '-').toLowerCase()}.json`; a.click();
    URL.revokeObjectURL(url);
  }

  function importTheme() {
    const input = document.createElement('input');
    input.type = 'file'; input.accept = '.json,application/json';
    input.onchange = async () => {
      const file = input.files?.[0];
      if (!file) return;
      try {
        const text = await file.text();
        const parsed = JSON.parse(text);
        if (parsed.name) themeName = parsed.name;
        if (parsed.palette && typeof parsed.palette === 'object') {
          palette = { ...initialPalette };
          for (const [k, v] of Object.entries(parsed.palette)) {
            if (k in palette && typeof v === 'string') {
              (palette as unknown as Record<string, string>)[k] = v;
            }
          }
          palette = { ...palette };
          applyPreview();
        }
      } catch { /* ignore */ }
    };
    input.click();
  }

  function capitalize(s: string) { return s[0].toUpperCase() + s.slice(1); }
</script>

<div class="editor">
  <div class="editor-toolbar">
    <input class="name-in" bind:value={themeName} placeholder="Theme name" aria-label="Theme name" />
    <button class="tool-btn" onclick={exportTheme} title="Export theme JSON">Export</button>
    <button class="tool-btn" onclick={importTheme} title="Import theme JSON">Import</button>
    <button class="tool-btn" onclick={resetToBase} title="Reset to base palette">Reset</button>
  </div>
  {#if nameError}
    <p class="name-err">{nameError}</p>
  {/if}

  <div class="group-label">Accents</div>
  <div class="color-grid">
    {#each ACCENT_KEYS as key}
      <div class="color-row">
        <label class="color-lbl" for="cp-{key}">{capitalize(key)}</label>
        <div class="color-ctrl">
          <input id="cp-{key}" type="color" class="color-swatch" value={palette[key]}
            oninput={e => setColor(key, (e.target as HTMLInputElement).value)} />
          <input type="text" class="hex-in" value={palette[key]}
            onchange={e => {
              const v = (e.target as HTMLInputElement).value.trim();
              if (/^#[0-9a-fA-F]{6}$/.test(v)) setColor(key, v);
            }}
          />
        </div>
      </div>
    {/each}
  </div>

  <div class="group-label" style="margin-top: 0.625rem;">Neutrals</div>
  <div class="color-grid">
    {#each NEUTRAL_KEYS as key}
      <div class="color-row">
        <label class="color-lbl" for="cp-{key}">{capitalize(key)}</label>
        <div class="color-ctrl">
          <input id="cp-{key}" type="color" class="color-swatch" value={palette[key]}
            oninput={e => setColor(key, (e.target as HTMLInputElement).value)} />
          <input type="text" class="hex-in" value={palette[key]}
            onchange={e => {
              const v = (e.target as HTMLInputElement).value.trim();
              if (/^#[0-9a-fA-F]{6}$/.test(v)) setColor(key, v);
            }}
          />
        </div>
      </div>
    {/each}
  </div>

  <div class="editor-actions">
    <button class="save-btn" onclick={handleSave} disabled={saving}>
      {saving ? 'Saving…' : 'Save as Custom Theme'}
    </button>
    <button class="cancel-btn" onclick={handleCancel}>Cancel</button>
  </div>
</div>

<style>
  .editor { display: flex; flex-direction: column; gap: 0.5rem; }

  .editor-toolbar { display: flex; align-items: center; gap: 0.375rem; }
  .name-in {
    flex: 1; padding: 0.3rem 0.5rem; background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
    color: var(--ctp-text); font-size: 0.8125rem; font-family: var(--ui-font-family);
  }
  .name-in:focus { outline: none; border-color: var(--ctp-blue); }
  .name-err { font-size: 0.75rem; color: var(--ctp-red); margin: 0; }

  .tool-btn {
    padding: 0.25rem 0.5rem; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1);
    border-radius: 0.25rem; color: var(--ctp-subtext1); font-size: 0.75rem; cursor: pointer;
    font-family: var(--ui-font-family); white-space: nowrap;
  }
  .tool-btn:hover { background: var(--ctp-surface1); color: var(--ctp-text); }

  .group-label {
    font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--ctp-overlay0); margin-bottom: 0.125rem;
  }

  .color-grid { display: flex; flex-direction: column; gap: 0.25rem; }

  .color-row { display: flex; align-items: center; gap: 0.5rem; }
  .color-lbl { font-size: 0.75rem; color: var(--ctp-subtext0); width: 5rem; flex-shrink: 0; }

  .color-ctrl { display: flex; align-items: center; gap: 0.375rem; flex: 1; }

  .color-swatch {
    width: 1.75rem; height: 1.75rem; padding: 0.125rem; border: 1px solid var(--ctp-surface1);
    border-radius: 0.2rem; background: var(--ctp-surface0); cursor: pointer; flex-shrink: 0;
  }
  .color-swatch::-webkit-color-swatch-wrapper { padding: 0; }
  .color-swatch::-webkit-color-swatch { border: none; border-radius: 0.125rem; }

  .hex-in {
    flex: 1; padding: 0.2rem 0.375rem; background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1); border-radius: 0.2rem;
    color: var(--ctp-text); font-size: 0.75rem; font-family: var(--term-font-family, monospace);
  }
  .hex-in:focus { outline: none; border-color: var(--ctp-blue); }

  .editor-actions { display: flex; gap: 0.5rem; margin-top: 0.375rem; padding-top: 0.5rem; border-top: 1px solid var(--ctp-surface1); }

  .save-btn {
    flex: 1; padding: 0.35rem 0.75rem; background: var(--ctp-blue); border: none;
    border-radius: 0.25rem; color: var(--ctp-base); font-size: 0.8rem; font-weight: 600;
    cursor: pointer; font-family: var(--ui-font-family);
  }
  .save-btn:hover:not(:disabled) { filter: brightness(1.1); }
  .save-btn:disabled { opacity: 0.4; cursor: not-allowed; }

  .cancel-btn {
    padding: 0.35rem 0.75rem; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1);
    border-radius: 0.25rem; color: var(--ctp-subtext1); font-size: 0.8rem; cursor: pointer;
    font-family: var(--ui-font-family);
  }
  .cancel-btn:hover { background: var(--ctp-surface1); color: var(--ctp-text); }
</style>
