import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useEffect, useRef, useState } from 'react';

import { UserService } from '@/client/services/UserService';
import { type ThemeMode, useThemeManager } from '@/hooks/user/useThemeManager';
import { useUserAppearance } from '@/hooks/user/useUserAppearance';

import { RadioOption, SectionHeading, Toggle } from './primitives';
import { ThemeCustomizer } from './ThemeCustomizer';

const COLOR_SCHEME_OPTIONS = [
  { value: 'system', label: 'System', description: 'Follow system color scheme.' },
  { value: 'light', label: 'Light', description: 'Always use light colors.' },
  { value: 'dark', label: 'Dark', description: 'Always use dark colors.' },
];

const EDITOR_THEMES = [
  { value: '', label: 'Default' },
  { value: 'github-light', label: 'GitHub Light' },
  { value: 'github-dark', label: 'GitHub Dark' },
  { value: 'monokai', label: 'Monokai' },
  { value: 'dracula', label: 'Dracula' },
  { value: 'one-dark-pro', label: 'One Dark Pro' },
  { value: 'solarized-light', label: 'Solarized Light' },
  { value: 'solarized-dark', label: 'Solarized Dark' },
  { value: 'cobalt2', label: 'Cobalt2' },
];

export function AppearanceTab() {
  const { data: appearance, isLoading, error } = useUserAppearance();
  const queryClient = useQueryClient();

  const [density, setDensity] = useState('comfortable');
  const [fontSize, setFontSize] = useState('medium');
  const [msgPreview, setMsgPreview] = useState(true);
  const [reducedMotion, setReducedMotion] = useState(false);
  const [colorScheme, setColorScheme] = useState('system');
  const [editorTheme, setEditorTheme] = useState('');

  const { presetName, mode, isDark, overrides, applyPreset, setToken, setMode, resetTheme } =
    useThemeManager();

  const updateMutation = useMutation({
    mutationFn: (body: Record<string, string | boolean | undefined>) =>
      UserService.userUpdateAppearance({ requestBody: body }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['user', 'appearance'] });
    },
  });

  const isInitialized = useRef(false);
  useEffect(() => {
    if (appearance && !isInitialized.current) {
      isInitialized.current = true;
      setDensity(appearance.density?.toLowerCase() ?? 'comfortable');
      setFontSize(appearance.font_size?.toLowerCase() ?? 'medium');
      setMsgPreview(appearance.markdown_preview);
      setReducedMotion(appearance.reduced_motion);
      setColorScheme(appearance.color_scheme?.toLowerCase() ?? 'system');
      setEditorTheme(appearance.editor_theme ?? '');

      const serverTheme = appearance.theme?.toLowerCase();
      if (serverTheme === 'light' || serverTheme === 'dark' || serverTheme === 'system') {
        setMode(serverTheme);
      }
    }
  }, [appearance, setMode]);

  function update(key: string, value: string | boolean) {
    updateMutation.mutate({ [key]: value === 'system' ? undefined : value });
  }

  function handleModeChange(nextMode: ThemeMode) {
    setMode(nextMode);
    update('theme', nextMode);
  }

  if (isLoading) {
    return (
      <div className="flex items-center gap-2 p-8 text-[14px] text-muted-foreground">
        <span className="inline-block size-4 animate-spin rounded-full border-2 border-border border-t-muted-foreground" />
        Loading…
      </div>
    );
  }

  if (error) {
    return (
      <div className="p-8">
        <div className="rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-[14px] text-destructive">
          Failed to load appearance settings.
        </div>
      </div>
    );
  }

  return (
    <div className="px-8 pt-10 pb-8 max-w-[520px]">
      <SectionHeading
        title="Theme preferences"
        description="Changes apply immediately and are saved to your account."
      />

      {/* Color theme */}
      <ThemeCustomizer
        presetName={presetName}
        isDark={isDark}
        overrides={overrides}
        onApplyPreset={applyPreset}
        onSetToken={setToken}
        onResetTheme={resetTheme}
      />

      {/* Mode selector */}
      <div className="mb-8">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Appearance</h3>
        <div className="space-y-2">
          <RadioOption
            value="system"
            label="Sync with system"
            description="Automatically switch between light and dark based on your OS setting."
            selected={mode === 'system'}
            onChange={() => handleModeChange('system')}
          />
          <RadioOption
            value="light"
            label="Light"
            description="Always use light appearance."
            selected={mode === 'light'}
            onChange={() => handleModeChange('light')}
          />
          <RadioOption
            value="dark"
            label="Dark"
            description="Always use dark appearance."
            selected={mode === 'dark'}
            onChange={() => handleModeChange('dark')}
          />
        </div>
      </div>

      {/* Color scheme */}
      <div className="mb-8">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Color scheme</h3>
        <div className="space-y-2">
          {COLOR_SCHEME_OPTIONS.map((opt) => (
            <RadioOption
              key={opt.value}
              value={opt.value}
              label={opt.label}
              description={opt.description}
              selected={colorScheme === opt.value}
              onChange={() => {
                setColorScheme(opt.value);
                update('color_scheme', opt.value);
              }}
            />
          ))}
        </div>
      </div>

      {/* Editor theme */}
      <div className="mb-8">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Editor theme</h3>
        <div className="relative">
          <select
            id="appearance-editor-theme"
            value={editorTheme}
            onChange={(e) => {
              setEditorTheme(e.target.value);
              update('editor_theme', e.target.value);
            }}
            className="w-full rounded-md border border-border bg-card px-3 py-[7px] text-[14px] leading-[20px] text-foreground outline-none transition-shadow focus:shadow-[inset_0_0_0_2px_var(--ring)] focus:border-transparent"
          >
            {EDITOR_THEMES.map((t) => (
              <option key={t.value} value={t.value}>
                {t.label}
              </option>
            ))}
          </select>
        </div>
      </div>

      {/* Density */}
      <div className="mb-8">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Interface density</h3>
        <div className="space-y-2">
          <RadioOption
            value="comfortable"
            label="Default"
            description="More whitespace between elements."
            selected={density === 'comfortable'}
            onChange={() => {
              setDensity('comfortable');
              update('density', 'comfortable');
            }}
          />
          <RadioOption
            value="compact"
            label="Compact"
            description="Tighter spacing for more information on screen."
            selected={density === 'compact'}
            onChange={() => {
              setDensity('compact');
              update('density', 'compact');
            }}
          />
        </div>
      </div>

      {/* Font size */}
      <div className="mb-8">
        <h3 className="mb-3 text-[13px] font-semibold text-foreground">Font size</h3>
        <div className="space-y-2">
          {[
            { value: 'small', label: 'Small' },
            { value: 'medium', label: 'Medium' },
            { value: 'large', label: 'Large' },
          ].map((opt) => (
            <RadioOption
              key={opt.value}
              value={opt.value}
              label={opt.label}
              selected={fontSize === opt.value}
              onChange={() => {
                setFontSize(opt.value);
                update('font_size', opt.value);
              }}
            />
          ))}
        </div>
      </div>

      {/* Accessibility */}
      <div>
        <h3 className="mb-2 text-[13px] font-semibold text-foreground">Accessibility</h3>
        <div className="divide-y divide-border/60">
          <Toggle
            label="Show message preview in markdown"
            checked={msgPreview}
            onChange={(v) => {
              setMsgPreview(v);
              update('markdown_preview', v);
            }}
          />
          <Toggle
            label="Reduce motion"
            description="Minimize the amount of non-essential animations."
            checked={reducedMotion}
            onChange={(v) => {
              setReducedMotion(v);
              update('reduced_motion', v);
            }}
          />
        </div>
      </div>
    </div>
  );
}
