import { useEffect, useRef, useState } from 'react';
import type { PresetName, ThemeTokenKey, ThemeTokenMap } from '@/lib/themePresets';
import { THEME_PRESET_NAMES, THEME_PRESETS, THEME_TOKEN_LABELS } from '@/lib/themePresets';

import { ColorSwatch } from './primitives';

interface ThemeCustomizerProps {
  presetName: PresetName;
  isDark: boolean;
  overrides: Partial<ThemeTokenMap>;
  onApplyPreset: (name: PresetName) => void;
  onSetToken: (key: ThemeTokenKey, value: string) => void;
  onResetTheme: () => void;
}

const PRESET_OPTIONS: { value: PresetName; label: string; description: string }[] = [
  ...THEME_PRESET_NAMES.map((name) => ({
    value: name,
    label: THEME_PRESETS[name].name,
    description: THEME_PRESETS[name].description,
  })),
  { value: 'custom', label: 'Custom', description: 'Override individual color tokens below.' },
];

const TOKEN_GROUPED = [
  {
    label: 'Surface',
    tokens: [
      '--background',
      '--foreground',
      '--card',
      '--card-foreground',
      '--popover',
      '--popover-foreground',
      '--muted',
      '--muted-foreground',
    ] as ThemeTokenKey[],
  },
  {
    label: 'Brand',
    tokens: [
      '--primary',
      '--primary-foreground',
      '--secondary',
      '--secondary-foreground',
      '--accent',
      '--accent-foreground',
      '--destructive',
    ] as ThemeTokenKey[],
  },
  {
    label: 'Chrome',
    tokens: ['--border', '--input', '--ring'] as ThemeTokenKey[],
  },
  {
    label: 'Charts',
    tokens: ['--chart-1', '--chart-2', '--chart-3', '--chart-4', '--chart-5'] as ThemeTokenKey[],
  },
  {
    label: 'Sidebar',
    tokens: [
      '--sidebar',
      '--sidebar-foreground',
      '--sidebar-primary',
      '--sidebar-primary-foreground',
      '--sidebar-accent',
      '--sidebar-accent-foreground',
      '--sidebar-border',
      '--sidebar-ring',
    ] as ThemeTokenKey[],
  },
];

const TOKEN_LABEL_MAP = Object.fromEntries(
  THEME_TOKEN_LABELS.map(({ key, label }) => [key, label]),
);

export function ThemeCustomizer({
  presetName,
  isDark,
  overrides,
  onApplyPreset,
  onSetToken,
  onResetTheme,
}: ThemeCustomizerProps) {
  const [editingToken, setEditingToken] = useState<ThemeTokenKey | null>(null);
  const [draftValue, setDraftValue] = useState('');
  const editInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (editingToken) {
      editInputRef.current?.focus();
    }
  }, [editingToken]);

  function startEditing(key: ThemeTokenKey, currentValue: string) {
    setEditingToken(key);
    setDraftValue(currentValue);
  }

  function saveEditing() {
    if (editingToken && draftValue.trim()) {
      onSetToken(editingToken, draftValue.trim());
    }
    setEditingToken(null);
    setDraftValue('');
  }

  function cancelEditing() {
    setEditingToken(null);
    setDraftValue('');
  }

  return (
    <div className="mb-8">
      {/* Preset selector */}
      <div className="mb-6">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Preset</h3>
        <div className="grid grid-cols-2 gap-2">
          {PRESET_OPTIONS.map((opt) => (
            <button
              key={opt.value}
              type="button"
              onClick={() => onApplyPreset(opt.value)}
              className={`flex items-center gap-3 rounded-lg border px-3 py-2.5 text-left transition-all ${
                presetName === opt.value
                  ? 'border-primary bg-accent/50 ring-2 ring-ring/20'
                  : 'border-border hover:bg-muted'
              }`}
            >
              <ColorSwatch preset={opt.value} isDark={isDark} />
              <div className="min-w-0">
                <p className="text-[13px] font-medium text-foreground">{opt.label}</p>
                <p className="mt-0.5 truncate text-[11px] text-muted-foreground">
                  {opt.description}
                </p>
              </div>
            </button>
          ))}
        </div>
      </div>

      {/* Token editor for custom preset */}
      {presetName === 'custom' && (
        <div className="mb-6">
          <h3 className="mb-2 text-[13px] font-semibold text-foreground">Custom tokens</h3>
          <p className="mb-4 text-[12px] text-muted-foreground">
            Click any token to edit its colour. Use oklch, hex, hsl, or any valid CSS colour.
          </p>

          {editingToken && (
            <div className="mb-4 flex items-center gap-3 rounded-lg border border-primary bg-accent/30 px-4 py-3">
              <span className="shrink-0 text-[13px] font-medium text-foreground">
                {TOKEN_LABEL_MAP[editingToken]}
              </span>
              <span className="text-[11px] text-muted-foreground">{editingToken}</span>
              <input
                type="text"
                value={draftValue}
                onChange={(e) => setDraftValue(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') saveEditing();
                  if (e.key === 'Escape') cancelEditing();
                }}
                placeholder="oklch(…)"
                className="flex-1 rounded-md border border-border bg-card px-3 py-[5px] text-[13px] text-foreground placeholder:text-muted-foreground/60 outline-none focus:ring-2 focus:ring-ring/30"
                ref={editInputRef}
              />
              <div
                className="size-7 shrink-0 rounded-md border border-border"
                style={{ backgroundColor: draftValue }}
              />
              <button
                type="button"
                onClick={saveEditing}
                className="shrink-0 rounded-md bg-primary px-3 py-[5px] text-[12px] font-medium text-white hover:bg-primary/85"
              >
                Save
              </button>
              <button
                type="button"
                onClick={cancelEditing}
                className="shrink-0 rounded-md px-3 py-[5px] text-[12px] text-muted-foreground hover:bg-muted"
              >
                Cancel
              </button>
            </div>
          )}

          {TOKEN_GROUPED.map((group) => (
            <div key={group.label} className="mb-4">
              <h4 className="mb-2 text-[11px] font-semibold uppercase tracking-[0.03em] text-muted-foreground">
                {group.label}
              </h4>
              <div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2">
                {group.tokens.map((key) => {
                  const value = overrides[key] ?? '';
                  const isEditing = editingToken === key;

                  return (
                    <button
                      key={key}
                      type="button"
                      onClick={() => startEditing(key, value)}
                      className={`flex items-center gap-3 rounded-md border px-3 py-2 text-left transition-colors hover:bg-muted ${
                        isEditing
                          ? 'border-primary bg-accent/30'
                          : value
                            ? 'border-border bg-card'
                            : 'border-dashed border-border bg-muted'
                      }`}
                    >
                      <div
                        className="size-6 shrink-0 rounded border border-border/60"
                        style={{ backgroundColor: value || 'transparent' }}
                      />
                      <div className="min-w-0 flex-1">
                        <p className="text-[13px] font-medium text-foreground">
                          {TOKEN_LABEL_MAP[key] ?? key}
                        </p>
                        <p className="mt-0.5 truncate text-[11px] text-muted-foreground">
                          {value || 'Unset'}
                        </p>
                      </div>
                    </button>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Reset */}
      <div className="flex items-center gap-3 border-t border-border pt-4">
        <button
          type="button"
          onClick={onResetTheme}
          className="inline-flex items-center gap-2 rounded-md bg-destructive px-4 py-[5px] text-[13px] font-medium text-white transition-colors hover:bg-destructive/80"
        >
          Reset to defaults
        </button>
        <span className="text-[12px] text-muted-foreground">
          Reverts all colour tokens and resets to system default.
        </span>
      </div>
    </div>
  );
}
