/**
 * Theme switcher — preset selection + custom token editor.
 *
 * Presets:
 *   Default  — Linear / Vercel dual-color (index.css :root / .dark)
 *   Custom   — user-editable palette, stored in localStorage
 *
 * The panel is opened via the sidebar "Theme" button and presented as a Sheet.
 */

import { useCallback, useEffect, useState } from 'react';
import {
  applyPaletteToDOM,
  clearCustomPalette,
  loadActivePresetId,
  loadCustomPalette,
  resetDOMFromPalette,
  saveActivePresetId,
  saveCustomPalette,
  THEME_PRESETS,
} from './design-system';
import type { PaletteEntry, ThemePresetId } from './design-system';
import { Button } from '@/components/ui/button';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { cn } from '@/lib/utils';
import { useTheme } from '@/contexts';
import { Check, RotateCcw, Sliders } from 'lucide-react';

// ─── Token definitions ───────────────────────────────────────────────────────

interface TokenDef {
  key: keyof PaletteEntry;
  label: string;
  group: 'surface' | 'text' | 'accent' | 'border' | 'status' | 'message';
  type: 'color';
}

const TOKEN_DEFS: TokenDef[] = [
  // Surface
  { key: 'bg',         label: 'Background',      group: 'surface', type: 'color' },
  { key: 'bgSubtle',   label: 'Subtle',           group: 'surface', type: 'color' },
  { key: 'bgHover',    label: 'Hover',            group: 'surface', type: 'color' },
  { key: 'bgActive',   label: 'Active',           group: 'surface', type: 'color' },
  { key: 'surface',    label: 'Surface (card)',   group: 'surface', type: 'color' },
  { key: 'surface2',   label: 'Surface 2',        group: 'surface', type: 'color' },
  { key: 'panelBg',    label: 'Panel / Sidebar',  group: 'surface', type: 'color' },
  // Text
  { key: 'text',       label: 'Text',             group: 'text', type: 'color' },
  { key: 'textMuted',  label: 'Text Muted',       group: 'text', type: 'color' },
  { key: 'textSubtle', label: 'Text Subtle',      group: 'text', type: 'color' },
  { key: 'icon',       label: 'Icon',            group: 'text', type: 'color' },
  { key: 'iconHover',  label: 'Icon Hover',       group: 'text', type: 'color' },
  // Accent
  { key: 'accent',      label: 'Accent',          group: 'accent', type: 'color' },
  { key: 'accentHover', label: 'Accent Hover',    group: 'accent', type: 'color' },
  { key: 'accentText',  label: 'Accent Text',     group: 'accent', type: 'color' },
  { key: 'mentionBg',   label: 'Mention BG',      group: 'accent', type: 'color' },
  { key: 'mentionText', label: 'Mention Text',    group: 'accent', type: 'color' },
  // Border
  { key: 'border',      label: 'Border',          group: 'border', type: 'color' },
  { key: 'borderFocus', label: 'Border Focus',    group: 'border', type: 'color' },
  { key: 'borderMuted', label: 'Border Muted',    group: 'border', type: 'color' },
  // Status
  { key: 'online',  label: 'Online',   group: 'status', type: 'color' },
  { key: 'away',    label: 'Away',     group: 'status', type: 'color' },
  { key: 'offline', label: 'Offline',  group: 'status', type: 'color' },
  // Message
  { key: 'msgBg',    label: 'Message BG',    group: 'message', type: 'color' },
  { key: 'msgOwnBg', label: 'Own Message BG', group: 'message', type: 'color' },
];

const GROUP_LABELS: Record<TokenDef['group'], string> = {
  surface: 'Surface',
  text: 'Text & Icon',
  accent: 'Accent',
  border: 'Border',
  status: 'Status',
  message: 'Message',
};

// ─── Preset Card ─────────────────────────────────────────────────────────────

function PresetCard({
  preset,
  active,
  onClick,
}: {
  preset: (typeof THEME_PRESETS)[number];
  active: boolean;
  onClick: () => void;
}) {
  const { resolvedTheme } = useTheme();

  const previewPalette = preset.palette ?? buildDefaultPreview(resolvedTheme);

  const swatches = [
    previewPalette.bg,
    previewPalette.surface,
    previewPalette.border,
    previewPalette.text,
    previewPalette.textMuted,
    previewPalette.accent,
    previewPalette.accentText,
  ];

  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        'flex flex-col gap-2 rounded-lg border p-3 text-left transition-all w-full',
        'hover:border-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
        active ? 'border-primary ring-1 ring-primary' : 'border-border',
      )}
    >
      {/* Color swatches */}
      <div className="flex gap-1">
        {swatches.map((color, i) => (
          <div
            key={i}
            className="h-6 flex-1 rounded-sm"
            style={{ background: color }}
          />
        ))}
      </div>
      {/* Label */}
      <div className="flex items-center justify-between">
        <span className="text-xs font-medium">{preset.label}</span>
        {active && <Check className="h-3.5 w-3.5 text-primary" />}
      </div>
      <p className="text-[10px] text-muted-foreground leading-tight">
        {preset.description}
      </p>
    </button>
  );
}

function buildDefaultPreview(theme: 'light' | 'dark'): PaletteEntry {
  if (theme === 'dark') {
    return {
      bg: '#1a1a1e', bgSubtle: '#1e1e23', bgHover: '#222228', bgActive: '#2a2a30',
      border: '#2e2e35', borderFocus: '#4a9eff', borderMuted: '#252528',
      text: '#ececf1', textMuted: '#8a8a92', textSubtle: '#5c5c65',
      accent: '#4a9eff', accentHover: '#6aafff', accentText: '#ffffff',
      icon: '#7a7a84', iconHover: '#b0b0ba',
      surface: '#222228', surface2: '#2a2a30',
      online: '#34d399', away: '#fbbf24', offline: '#6b7280',
      mentionBg: 'rgba(74,158,255,0.12)', mentionText: '#4a9eff',
      msgBg: '#1e1e23', msgOwnBg: '#1a2a3a', panelBg: '#161619',
      badgeAi: '', badgeRole: '',
    };
  }
  return {
    bg: '#ffffff', bgSubtle: '#f9f9fa', bgHover: '#f3f3f5', bgActive: '#ebebef',
    border: '#e4e4e8', borderFocus: '#1c7ded', borderMuted: '#eeeeef',
    text: '#1f1f1f', textMuted: '#8a8a8f', textSubtle: '#b8b8bd',
    accent: '#1c7ded', accentHover: '#1a73d4', accentText: '#ffffff',
    icon: '#8a8a8f', iconHover: '#5c5c62',
    surface: '#f7f7f8', surface2: '#eeeeef',
    online: '#22c55e', away: '#f59e0b', offline: '#d1d1d6',
    mentionBg: 'rgba(28,125,237,0.08)', mentionText: '#1c7ded',
    msgBg: '#f9f9fb', msgOwnBg: '#e8f0fe', panelBg: '#f9f9fa',
    badgeAi: '', badgeRole: '',
  };
}

// ─── Token Editor ─────────────────────────────────────────────────────────────

function TokenEditor({
  value,
  onChange,
}: {
  value: PaletteEntry;
  onChange: (v: PaletteEntry) => void;
}) {
  const groups = (['surface', 'text', 'accent', 'border', 'status', 'message'] as const);

  return (
    <div className="space-y-4">
      {groups.map((group) => {
        const defs = TOKEN_DEFS.filter((d) => d.group === group);
        return (
          <div key={group}>
            <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground mb-2">
              {GROUP_LABELS[group]}
            </p>
            <div className="grid grid-cols-2 gap-x-4 gap-y-2">
              {defs.map((def) => (
                <div key={def.key} className="flex items-center gap-2">
                  {/* Swatch + native color picker */}
                  <div className="relative shrink-0">
                    <div
                      className="h-7 w-7 rounded border cursor-pointer overflow-hidden"
                      style={{ background: value[def.key] as string }}
                    >
                      <input
                        type="color"
                        value={(value[def.key] as string).startsWith('#')
                          ? (value[def.key] as string)
                          : '#888888'}
                        onChange={(e) =>
                          onChange({ ...value, [def.key]: e.target.value })
                        }
                        className="absolute inset-0 opacity-0 cursor-pointer w-full h-full"
                        title={def.label}
                      />
                    </div>
                  </div>
                  <div className="flex-1 min-w-0">
                    <p className="text-xs font-medium truncate">{def.label}</p>
                    <input
                      type="text"
                      value={value[def.key] as string}
                      onChange={(e) =>
                        onChange({ ...value, [def.key]: e.target.value })
                      }
                      className="w-full bg-transparent border-0 p-0 text-[10px] text-muted-foreground focus:outline-none focus:ring-0 font-mono"
                      spellCheck={false}
                    />
                  </div>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─── Main component ───────────────────────────────────────────────────────────

interface ThemeSwitcherProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
}

export function ThemeSwitcher({ open, onOpenChange }: ThemeSwitcherProps) {
  const { resolvedTheme } = useTheme();

  const [activePresetId, setActivePresetId] = useState<ThemePresetId>(loadActivePresetId);
  const [customPalette, setCustomPalette] = useState<PaletteEntry | null>(
    loadCustomPalette,
  );
  // Working copy being edited
  const [draft, setDraft] = useState<PaletteEntry | null>(null);
  const [isDirty, setIsDirty] = useState(false);

  // Reset when panel opens
  useEffect(() => {
    if (open) {
      const id = loadActivePresetId();
      setActivePresetId(id);
      setCustomPalette(loadCustomPalette());
      setDraft(id === 'custom' && loadCustomPalette() ? { ...loadCustomPalette()! } : null);
      setIsDirty(false);
    }
  }, [open]);

  const applyPreset = useCallback(
    (presetId: ThemePresetId) => {
      setActivePresetId(presetId);
      saveActivePresetId(presetId);
      if (presetId === 'custom') {
        const stored = loadCustomPalette();
        setCustomPalette(stored);
        setDraft(stored ? { ...stored } : null);
        if (stored) applyPaletteToDOM(stored);
      } else {
        clearCustomPalette();
        setCustomPalette(null);
        setDraft(null);
        resetDOMFromPalette();
      }
      setIsDirty(false);
    },
    [],
  );

  const handleDraftChange = useCallback((next: PaletteEntry) => {
    setDraft(next);
    setIsDirty(true);
  }, []);

  const handleApplyCustom = useCallback(() => {
    if (!draft) return;
    saveCustomPalette(draft);
    setCustomPalette(draft);
    applyPaletteToDOM(draft);
    setActivePresetId('custom');
    saveActivePresetId('custom');
    setIsDirty(false);
  }, [draft]);

  const handleReset = useCallback(() => {
    applyPreset('default');
  }, [applyPreset]);

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="flex flex-col overflow-y-auto w-[360px] sm:max-w-[360px]">
        <SheetHeader>
          <SheetTitle className="flex items-center gap-2">
            <Sliders className="h-4 w-4" />
            Theme Settings
          </SheetTitle>
        </SheetHeader>

        {/* ── Scrollable content with padding ─────────────────────────────── */}
        <div className="flex flex-col gap-5 px-5 pb-5 overflow-y-auto">

        {/* ── Preset grid ─────────────────────────────────────────────────── */}
        <div className="mt-6">
          <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground mb-3">
            Presets
          </p>
          <div className="grid grid-cols-1 gap-2">
            {THEME_PRESETS.map((preset) => (
              <PresetCard
                key={preset.id}
                preset={preset}
                active={activePresetId === preset.id}
                onClick={() => applyPreset(preset.id as ThemePresetId)}
              />
            ))}
            {/* Custom preset card — always shown */}
            <button
              type="button"
              onClick={() => {
                // Switch to custom, seed draft from current effective palette
                const seed = activePresetId === 'custom' && customPalette
                  ? { ...customPalette }
                  : { ...buildDefaultPreview(resolvedTheme) };
                setDraft(seed);
                setActivePresetId('custom');
                setIsDirty(false);
                if (activePresetId !== 'custom') {
                  saveActivePresetId('custom');
                }
              }}
              className={cn(
                'flex flex-col gap-2 rounded-lg border p-3 text-left transition-all',
                'hover:border-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
                activePresetId === 'custom'
                  ? 'border-primary ring-1 ring-primary'
                  : 'border-border border-dashed',
              )}
            >
              {/* Mini palette swatches */}
              <div className="flex gap-1">
                {['#ffffff', '#f9f9fa', '#e4e4e8', '#1f1f1f', '#8a8a8f', '#1c7ded', '#ffffff'].map(
                  (c, i) => (
                    <div key={i} className="h-6 flex-1 rounded-sm" style={{ background: c }} />
                  ),
                )}
              </div>
              <div className="flex items-center justify-between">
                <span className="text-xs font-medium">Custom</span>
                {activePresetId === 'custom' && (
                  <Check className="h-3.5 w-3.5 text-primary" />
                )}
              </div>
              <p className="text-[10px] text-muted-foreground leading-tight">
                Define your own colors
              </p>
            </button>
          </div>
        </div>

        {/* ── Custom token editor ─────────────────────────────────────────── */}
        {activePresetId === 'custom' && draft && (
          <div className="border-t pt-5">
            <div className="flex items-center justify-between mb-4">
              <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                Token Editor
              </p>
              <div className="flex gap-1">
                <Button
                  variant="outline"
                  size="sm"
                  className="h-7 gap-1 text-xs"
                  onClick={handleReset}
                >
                  <RotateCcw className="h-3 w-3" />
                  Reset
                </Button>
                <Button
                  size="sm"
                  className="h-7 gap-1 text-xs"
                  onClick={handleApplyCustom}
                  disabled={!isDirty}
                >
                  Apply
                </Button>
              </div>
            </div>
            <TokenEditor value={draft} onChange={handleDraftChange} />
          </div>
        )}
        </div>
      </SheetContent>
    </Sheet>
  );
}
