export type AsukaThemeColors = {
  surface: string;
  surfaceAlt: string;
  borderSubtle: string;
  borderStrong: string;
  textMain: string;
  textMuted: string;
  primary: string;
  primarySoft: string;
  accent: string;
};

export type AsukaTheme = {
  colors: AsukaThemeColors;
};

export type ThemeToken =
  | 'layout.appBg'
  | 'layout.shellBg'
  | 'layout.sidebarBg'
  | 'layout.sidebarItemBg'
  | 'layout.sidebarItemHoverBg'
  | 'layout.sidebarItemActiveBg'
  | 'layout.panelBg'
  | 'layout.panelHeaderBg'
  | 'layout.toolbarBg'
  | 'layout.canvasStageBg'
  | 'layout.overlayBackdrop'
  | 'thumbnail.bg'
  | 'thumbnail.activeBg'
  | 'thumbnail.activeBorder'
  | 'text.primary'
  | 'text.secondary'
  | 'text.tertiary'
  | 'text.inverse'
  | 'border.subtle'
  | 'border.default'
  | 'border.strong'
  | 'border.focus'
  | 'accent.primary'
  | 'accent.primarySoft'
  | 'accent.success'
  | 'accent.warning'
  | 'accent.danger'
  | 'button.primary.bg'
  | 'button.primary.text'
  | 'button.primary.border'
  | 'button.primary.hoverBg'
  | 'button.secondary.bg'
  | 'button.secondary.text'
  | 'button.secondary.border'
  | 'button.secondary.hoverBg'
  | 'button.ghost.text'
  | 'button.ghost.hoverBg'
  | 'button.danger.bg'
  | 'button.danger.text'
  | 'button.danger.border'
  | 'button.danger.hoverBg'
  | 'input.bg'
  | 'input.text'
  | 'input.border'
  | 'input.placeholder'
  | 'input.focusRing'
  | 'iconButton.bg'
  | 'iconButton.text'
  | 'iconButton.border'
  | 'iconButton.hoverBg';

export type ThemePresetId = 'light' | 'dark' | 'figma' | 'linear' | 'canva' | 'minimal';
export type ThemeColorMap = Record<ThemeToken, string>;
export type ThemeInit = { preset?: ThemePresetId; colors?: Partial<ThemeColorMap> };

const TOKEN_TO_CSS_VAR: Record<ThemeToken, string> = {
  'layout.appBg': '--ask-layout-app-bg',
  'layout.shellBg': '--ask-layout-shell-bg',
  'layout.sidebarBg': '--ask-layout-sidebar-bg',
  'layout.sidebarItemBg': '--ask-layout-sidebar-item-bg',
  'layout.sidebarItemHoverBg': '--ask-layout-sidebar-item-hover-bg',
  'layout.sidebarItemActiveBg': '--ask-layout-sidebar-item-active-bg',
  'layout.panelBg': '--ask-layout-panel-bg',
  'layout.panelHeaderBg': '--ask-layout-panel-header-bg',
  'layout.toolbarBg': '--ask-layout-toolbar-bg',
  'layout.canvasStageBg': '--ask-layout-canvas-stage-bg',
  'layout.overlayBackdrop': '--ask-layout-overlay-backdrop',
  'thumbnail.bg': '--ask-thumbnail-bg',
  'thumbnail.activeBg': '--ask-thumbnail-active-bg',
  'thumbnail.activeBorder': '--ask-thumbnail-active-border',
  'text.primary': '--ask-text-primary',
  'text.secondary': '--ask-text-secondary',
  'text.tertiary': '--ask-text-tertiary',
  'text.inverse': '--ask-text-inverse',
  'border.subtle': '--ask-border-subtle',
  'border.default': '--ask-border-default',
  'border.strong': '--ask-border-strong',
  'border.focus': '--ask-border-focus',
  'accent.primary': '--ask-accent-primary',
  'accent.primarySoft': '--ask-accent-primary-soft',
  'accent.success': '--ask-accent-success',
  'accent.warning': '--ask-accent-warning',
  'accent.danger': '--ask-accent-danger',
  'button.primary.bg': '--ask-button-primary-bg',
  'button.primary.text': '--ask-button-primary-text',
  'button.primary.border': '--ask-button-primary-border',
  'button.primary.hoverBg': '--ask-button-primary-hover-bg',
  'button.secondary.bg': '--ask-button-secondary-bg',
  'button.secondary.text': '--ask-button-secondary-text',
  'button.secondary.border': '--ask-button-secondary-border',
  'button.secondary.hoverBg': '--ask-button-secondary-hover-bg',
  'button.ghost.text': '--ask-button-ghost-text',
  'button.ghost.hoverBg': '--ask-button-ghost-hover-bg',
  'button.danger.bg': '--ask-button-danger-bg',
  'button.danger.text': '--ask-button-danger-text',
  'button.danger.border': '--ask-button-danger-border',
  'button.danger.hoverBg': '--ask-button-danger-hover-bg',
  'input.bg': '--ask-input-bg',
  'input.text': '--ask-input-text',
  'input.border': '--ask-input-border',
  'input.placeholder': '--ask-input-placeholder',
  'input.focusRing': '--ask-input-focus-ring',
  'iconButton.bg': '--ask-icon-button-bg',
  'iconButton.text': '--ask-icon-button-text',
  'iconButton.border': '--ask-icon-button-border',
  'iconButton.hoverBg': '--ask-icon-button-hover-bg',
};

const THEME_UTILITY_VAR_MAP: Record<keyof AsukaThemeColors, string> = {
  surface: '--ask-color-surface',
  surfaceAlt: '--ask-color-surface-alt',
  borderSubtle: '--ask-color-border-subtle',
  borderStrong: '--ask-color-border-strong',
  textMain: '--ask-color-text-main',
  textMuted: '--ask-color-text-muted',
  primary: '--ask-color-primary',
  primarySoft: '--ask-color-primary-soft',
  accent: '--ask-color-accent',
};

const DEFAULT_COLORS: ThemeColorMap = {
  'layout.appBg': '#f5f7fb',
  'layout.shellBg': '#ffffff',
  'layout.sidebarBg': '#ffffff',
  'layout.sidebarItemBg': '#ffffff',
  'layout.sidebarItemHoverBg': 'rgba(37, 99, 235, 0.05)',
  'layout.sidebarItemActiveBg': 'rgba(37, 99, 235, 0.08)',
  'layout.panelBg': '#ffffff',
  'layout.panelHeaderBg': 'rgba(248, 250, 252, 0.92)',
  'layout.toolbarBg': 'rgba(255, 255, 255, 0.96)',
  'layout.canvasStageBg': '#eef2f7',
  'layout.overlayBackdrop': 'rgba(15, 23, 42, 0.24)',
  'thumbnail.bg': '#ffffff',
  'thumbnail.activeBg': 'rgba(37, 99, 235, 0.10)',
  'thumbnail.activeBorder': '#2563eb',
  'text.primary': '#0f172a',
  'text.secondary': '#64748b',
  'text.tertiary': '#94a3b8',
  'text.inverse': '#ffffff',
  'border.subtle': '#e8edf5',
  'border.default': '#d7dfeb',
  'border.strong': '#b8c4d7',
  'border.focus': '#2563eb',
  'accent.primary': '#2563eb',
  'accent.primarySoft': 'rgba(37, 99, 235, 0.12)',
  'accent.success': '#16a34a',
  'accent.warning': '#f59e0b',
  'accent.danger': '#dc2626',
  'button.primary.bg': '#2563eb',
  'button.primary.text': '#ffffff',
  'button.primary.border': '#2563eb',
  'button.primary.hoverBg': '#1d4ed8',
  'button.secondary.bg': '#ffffff',
  'button.secondary.text': '#0f172a',
  'button.secondary.border': '#d7dfeb',
  'button.secondary.hoverBg': '#f8fafc',
  'button.ghost.text': '#334155',
  'button.ghost.hoverBg': 'rgba(15, 23, 42, 0.05)',
  'button.danger.bg': '#dc2626',
  'button.danger.text': '#ffffff',
  'button.danger.border': '#dc2626',
  'button.danger.hoverBg': '#b91c1c',
  'input.bg': '#ffffff',
  'input.text': '#0f172a',
  'input.border': '#d7dfeb',
  'input.placeholder': '#94a3b8',
  'input.focusRing': 'rgba(37, 99, 235, 0.18)',
  'iconButton.bg': '#ffffff',
  'iconButton.text': '#334155',
  'iconButton.border': '#d7dfeb',
  'iconButton.hoverBg': '#f8fafc',
};

const PRESETS: Record<ThemePresetId, Partial<ThemeColorMap>> = {
  light: {},
  dark: {
    'layout.appBg': '#07152f',
    'layout.shellBg': '#09162d',
    'layout.sidebarBg': '#081327',
    'layout.sidebarItemBg': '#0b1a33',
    'layout.sidebarItemHoverBg': 'rgba(96, 165, 250, 0.10)',
    'layout.sidebarItemActiveBg': 'rgba(59, 130, 246, 0.18)',
    'layout.panelBg': '#09162d',
    'layout.panelHeaderBg': '#0b1a33',
    'layout.toolbarBg': '#09162d',
    'layout.canvasStageBg': '#071229',
    'layout.overlayBackdrop': 'rgba(2, 6, 23, 0.58)',
    'thumbnail.bg': '#0b1a33',
    'thumbnail.activeBg': 'rgba(59, 130, 246, 0.18)',
    'thumbnail.activeBorder': '#60a5fa',
    'text.primary': '#e5eefc',
    'text.secondary': '#a9bddb',
    'text.tertiary': '#7d95b8',
    'text.inverse': '#ffffff',
    'border.subtle': '#183055',
    'border.default': '#25416a',
    'border.strong': '#36598d',
    'border.focus': '#60a5fa',
    'accent.primary': '#60a5fa',
    'accent.primarySoft': 'rgba(96, 165, 250, 0.16)',
    'accent.success': '#34d399',
    'accent.warning': '#fbbf24',
    'accent.danger': '#f87171',
    'button.primary.bg': '#3b82f6',
    'button.primary.text': '#ffffff',
    'button.primary.border': '#3b82f6',
    'button.primary.hoverBg': '#2563eb',
    'button.secondary.bg': '#0c1c37',
    'button.secondary.text': '#e5eefc',
    'button.secondary.border': '#23416a',
    'button.secondary.hoverBg': '#102243',
    'button.ghost.text': '#c6d5ee',
    'button.ghost.hoverBg': 'rgba(255, 255, 255, 0.06)',
    'button.danger.bg': '#ef4444',
    'button.danger.text': '#ffffff',
    'button.danger.border': '#ef4444',
    'button.danger.hoverBg': '#dc2626',
    'input.bg': '#0c1c37',
    'input.text': '#e5eefc',
    'input.border': '#23416a',
    'input.placeholder': '#7d95b8',
    'input.focusRing': 'rgba(96, 165, 250, 0.24)',
    'iconButton.bg': '#0c1c37',
    'iconButton.text': '#d9e7fb',
    'iconButton.border': '#23416a',
    'iconButton.hoverBg': '#102243',
  },
  figma: {
    'layout.appBg': '#f3f4f8',
    'layout.shellBg': '#ffffff',
    'layout.sidebarBg': '#ffffff',
    'layout.sidebarItemBg': 'transparent',
    'layout.sidebarItemHoverBg': 'rgba(15, 23, 42, 0.04)',
    'layout.sidebarItemActiveBg': 'rgba(13, 153, 255, 0.10)',
    'layout.panelBg': '#ffffff',
    'layout.panelHeaderBg': '#ffffff',
    'layout.toolbarBg': '#ffffff',
    'layout.canvasStageBg': '#f7f8fb',
    'thumbnail.activeBorder': '#0d99ff',
    'accent.primary': '#0d99ff',
    'accent.primarySoft': 'rgba(13, 153, 255, 0.12)',
    'border.subtle': '#eceff4',
    'border.default': '#dde3ec',
    'button.primary.bg': '#0d99ff',
    'button.primary.border': '#0d99ff',
    'button.primary.hoverBg': '#0b87e1',
    'button.secondary.bg': '#ffffff',
    'button.secondary.border': '#dde3ec',
  },
  linear: {
    'layout.appBg': '#08090d',
    'layout.shellBg': '#0c0d12',
    'layout.sidebarBg': '#0d0f14',
    'layout.sidebarItemBg': '#101218',
    'layout.sidebarItemHoverBg': 'rgba(148, 163, 184, 0.10)',
    'layout.sidebarItemActiveBg': 'rgba(94, 106, 210, 0.22)',
    'layout.panelBg': '#15171d',
    'layout.panelHeaderBg': '#1b1d24',
    'layout.toolbarBg': '#101117',
    'layout.canvasStageBg': '#050609',
    'layout.overlayBackdrop': 'rgba(0, 0, 0, 0.52)',
    'thumbnail.bg': '#101218',
    'thumbnail.activeBg': 'rgba(94, 106, 210, 0.18)',
    'thumbnail.activeBorder': '#7b83eb',
    'text.primary': '#f7f8fb',
    'text.secondary': '#c5cad6',
    'text.tertiary': '#8f96a6',
    'text.inverse': '#ffffff',
    'border.subtle': '#2a2d36',
    'border.default': '#3a3f4c',
    'border.strong': '#545b6e',
    'border.focus': '#7b83eb',
    'accent.primary': '#7b83eb',
    'accent.primarySoft': 'rgba(123, 131, 235, 0.20)',
    'accent.success': '#38d996',
    'accent.warning': '#f8c35c',
    'accent.danger': '#ff7b7b',
    'button.primary.bg': '#5e6ad2',
    'button.primary.text': '#ffffff',
    'button.primary.border': '#6f78e8',
    'button.primary.hoverBg': '#6b75e4',
    'button.secondary.bg': '#20232c',
    'button.secondary.text': '#f7f8fb',
    'button.secondary.border': '#414756',
    'button.secondary.hoverBg': '#2a2e39',
    'button.ghost.text': '#d7dbe5',
    'button.ghost.hoverBg': 'rgba(255, 255, 255, 0.08)',
    'button.danger.bg': '#d84f57',
    'button.danger.text': '#ffffff',
    'button.danger.border': '#e46b72',
    'button.danger.hoverBg': '#c74149',
    'input.bg': '#101218',
    'input.text': '#f7f8fb',
    'input.border': '#3a3f4c',
    'input.placeholder': '#8f96a6',
    'input.focusRing': 'rgba(123, 131, 235, 0.28)',
    'iconButton.bg': '#20232c',
    'iconButton.text': '#e7eaf2',
    'iconButton.border': '#414756',
    'iconButton.hoverBg': '#2a2e39',
  },
  canva: {
    'layout.appBg': '#f4f6fb', 'layout.shellBg': '#ffffff', 'layout.sidebarBg': '#ffffff', 'layout.panelBg': '#ffffff', 'layout.canvasStageBg': '#eef1f7',
    'accent.primary': '#7c3aed', 'accent.primarySoft': 'rgba(124,58,237,0.14)',
    'thumbnail.activeBorder': '#7c3aed',
    'button.primary.bg': '#7c3aed', 'button.primary.border': '#7c3aed', 'button.primary.hoverBg': '#6d28d9',
  },
  minimal: {
    'layout.appBg': '#f8fafc', 'layout.shellBg': '#ffffff', 'layout.sidebarBg': '#ffffff', 'layout.panelBg': '#ffffff', 'layout.canvasStageBg': '#f8fafc',
    'border.subtle': '#eef2f7', 'border.default': '#e5eaf2', 'border.strong': '#d6dee9',
    'button.secondary.bg': '#ffffff', 'button.secondary.hoverBg': '#f9fafb',
  },
};

const TOKEN_ALIASES: Record<string, ThemeToken> = {
  'sidebar': 'layout.sidebarBg',
  'sidebar:bg': 'layout.sidebarBg',
  'panel': 'layout.panelBg',
  'panel:bg': 'layout.panelBg',
  'toolbar': 'layout.toolbarBg',
  'app': 'layout.appBg',
  'canvas:stage': 'layout.canvasStageBg',
  'button:primary': 'button.primary.bg',
  'button:info': 'button.primary.bg',
  'button:secondary': 'button.secondary.bg',
  'button:ghost': 'button.ghost.hoverBg',
  'thumbnail:active': 'thumbnail.activeBorder',
};

function toRgbChannels(value: string | undefined, fallback = "226 232 240"): string {
  if (!value) return fallback;
  const input = String(value).trim();

  const hexMatch = input.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
  if (hexMatch) {
    let hex = hexMatch[1];
    if (hex.length === 3) hex = hex.split('').map((ch) => ch + ch).join('');
    return `${parseInt(hex.slice(0, 2), 16)} ${parseInt(hex.slice(2, 4), 16)} ${parseInt(hex.slice(4, 6), 16)}`;
  }

  const rgbMatch = input.match(/^rgba?\(\s*([0-9.]+)[,\s]+([0-9.]+)[,\s]+([0-9.]+)/i);
  if (rgbMatch) {
    return `${Math.round(Number(rgbMatch[1]))} ${Math.round(Number(rgbMatch[2]))} ${Math.round(Number(rgbMatch[3]))}`;
  }

  return fallback;
}

let currentColors: ThemeColorMap = { ...DEFAULT_COLORS };
let currentPreset: ThemePresetId = 'light';

function normalizeToken(token: string): ThemeToken | null {
  if ((TOKEN_TO_CSS_VAR as any)[token]) return token as ThemeToken;
  return TOKEN_ALIASES[token] ?? null;
}

function applyToDom(colors: ThemeColorMap): void {
  if (typeof document === 'undefined') return;
  const root = document.documentElement;
  (Object.keys(colors) as ThemeToken[]).forEach((token) => {
    root.style.setProperty(TOKEN_TO_CSS_VAR[token], colors[token]);
  });
  // Keep the utility-layer CSS variables synchronized with theme tokens.
  root.style.setProperty(THEME_UTILITY_VAR_MAP.surface, colors['layout.appBg']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.surfaceAlt, colors['layout.panelBg']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.borderSubtle, colors['border.subtle']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.borderStrong, colors['border.strong']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.textMain, colors['text.primary']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.textMuted, colors['text.secondary']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.primary, colors['accent.primary']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.primarySoft, colors['accent.primarySoft']);
  root.style.setProperty(THEME_UTILITY_VAR_MAP.accent, colors['accent.success']);

  // Additional variables used by Tailwind utilities and module styles.
  root.style.setProperty('--ask-color-background', colors['layout.appBg']);
  root.style.setProperty('--ask-color-surface-2', colors['layout.panelHeaderBg']);
  root.style.setProperty('--ask-color-border', colors['border.default']);
  root.style.setProperty('--ask-color-text', colors['text.primary']);
  root.style.setProperty('--ask-text-main', colors['text.primary']);
  root.style.setProperty('--ask-color-text-strong', colors['text.primary']);
  root.style.setProperty('--ask-text-muted', colors['text.secondary']);
  root.style.setProperty('--ask-color-text-subtle', colors['text.tertiary']);
  root.style.setProperty('--ask-color-success', colors['accent.success']);
  root.style.setProperty('--ask-color-warning', colors['accent.warning']);
  root.style.setProperty('--ask-color-danger', colors['accent.danger']);
  root.style.setProperty('--ask-surface', colors['layout.panelBg']);
  root.style.setProperty('--ask-surface-subtle', colors['layout.appBg']);

  const rgbVars: Record<string, string> = {
    '--ask-color-background-rgb': colors['layout.appBg'],
    '--ask-color-surface-rgb': colors['layout.appBg'],
    '--ask-color-surface-alt-rgb': colors['layout.panelBg'],
    '--ask-color-surface-2-rgb': colors['layout.panelHeaderBg'],
    '--ask-color-border-rgb': colors['border.default'],
    '--ask-color-border-default-rgb': colors['border.default'],
    '--ask-color-border-subtle-rgb': colors['border.subtle'],
    '--ask-color-border-strong-rgb': colors['border.strong'],
    '--ask-color-text-rgb': colors['text.primary'],
    '--ask-color-text-main-rgb': colors['text.primary'],
    '--ask-color-text-primary-rgb': colors['text.primary'],
    '--ask-color-text-muted-rgb': colors['text.secondary'],
    '--ask-color-text-secondary-rgb': colors['text.secondary'],
    '--ask-color-text-strong-rgb': colors['text.primary'],
    '--ask-color-text-subtle-rgb': colors['text.tertiary'],
    '--ask-color-primary-rgb': colors['accent.primary'],
    '--ask-color-accent-rgb': colors['accent.success'],
    '--ask-color-success-rgb': colors['accent.success'],
    '--ask-color-warning-rgb': colors['accent.warning'],
    '--ask-color-danger-rgb': colors['accent.danger'],
  };
  Object.entries(rgbVars).forEach(([name, value]) => root.style.setProperty(name, toRgbChannels(value)));
  root.style.setProperty('--ask-color-foreground-rgb', toRgbChannels(colors['text.primary']));
  root.setAttribute('data-asuka-theme-preset', currentPreset);
}

function mergeTheme(init?: Partial<ThemeInit>): ThemeColorMap {
  const preset = init?.preset ?? currentPreset;
  const presetColors = PRESETS[preset] ?? {};
  return { ...DEFAULT_COLORS, ...presetColors, ...(init?.colors ?? {}) };
}

export function applyTheme(theme: Partial<AsukaTheme> | Partial<ThemeInit> = {}): AsukaTheme {
  const hasExplicitThemeInput = !!theme && Object.keys(theme as any).length > 0;

  if (!hasExplicitThemeInput) {
    applyToDom(currentColors);
    return {
      colors: {
        surface: currentColors['layout.appBg'],
        surfaceAlt: currentColors['layout.panelBg'],
        borderSubtle: currentColors['border.subtle'],
        borderStrong: currentColors['border.strong'],
        textMain: currentColors['text.primary'],
        textMuted: currentColors['text.secondary'],
        primary: currentColors['accent.primary'],
        primarySoft: currentColors['accent.primarySoft'],
        accent: currentColors['accent.success'],
      },
    };
  }

  currentPreset = (theme as Partial<ThemeInit>)?.preset ?? currentPreset;
  currentColors = mergeTheme(theme as Partial<ThemeInit>);

  applyToDom(currentColors);

  return {
    colors: {
      surface: currentColors['layout.appBg'],
      surfaceAlt: currentColors['layout.panelBg'],
      borderSubtle: currentColors['border.subtle'],
      borderStrong: currentColors['border.strong'],
      textMain: currentColors['text.primary'],
      textMuted: currentColors['text.secondary'],
      primary: currentColors['accent.primary'],
      primarySoft: currentColors['accent.primarySoft'],
      accent: currentColors['accent.success'],
    },
  };
}

export function initTheme(input?: Partial<ThemeInit>): ThemeColorMap {
  currentPreset = input?.preset ?? currentPreset;
  currentColors = mergeTheme(input);
  applyToDom(currentColors);
  return { ...currentColors };
}

export function setThemeColor(token: string, value: string): boolean {
  const normalized = normalizeToken(token);
  if (!normalized || typeof value !== 'string' || !value.trim()) return false;
  currentColors = { ...currentColors, [normalized]: value };
  applyToDom(currentColors);
  return true;
}

export function setThemeColors(colors: Record<string, string>): string[] {
  const applied: string[] = [];
  let next = { ...currentColors };
  Object.entries(colors ?? {}).forEach(([token, value]) => {
    const normalized = normalizeToken(token);
    if (!normalized || typeof value !== 'string' || !value.trim()) return;
    next[normalized] = value;
    applied.push(normalized);
  });
  currentColors = next;
  applyToDom(currentColors);
  return applied;
}

export function getThemeColor(token: string): string | null {
  const normalized = normalizeToken(token);
  if (!normalized) return null;
  return currentColors[normalized] ?? null;
}

export function resetThemeColor(token: string): boolean {
  const normalized = normalizeToken(token);
  if (!normalized) return false;
  currentColors = { ...currentColors, [normalized]: mergeTheme({ preset: currentPreset })[normalized] };
  applyToDom(currentColors);
  return true;
}

export function resetThemeSection(section: 'layout' | 'text' | 'border' | 'accent' | 'button' | 'input' | 'iconButton' | 'thumbnail'): void {
  const base = mergeTheme({ preset: currentPreset });
  const next = { ...currentColors };
  (Object.keys(TOKEN_TO_CSS_VAR) as ThemeToken[]).forEach((token) => {
    if (token.startsWith(section + '.')) next[token] = base[token];
  });
  currentColors = next;
  applyToDom(currentColors);
}

export function resetTheme(preset?: ThemePresetId): ThemeColorMap {
  if (preset) currentPreset = preset;
  currentColors = mergeTheme({ preset: currentPreset });
  applyToDom(currentColors);
  return { ...currentColors };
}

export function applyThemePreset(preset: ThemePresetId): ThemeColorMap {
  currentPreset = preset;
  currentColors = mergeTheme({ preset });
  applyToDom(currentColors);
  return { ...currentColors };
}

export function getThemeState(): ThemeInit {
  return { preset: currentPreset, colors: { ...currentColors } };
}

export function setThemeState(theme: Partial<ThemeInit>): ThemeColorMap {
  currentPreset = theme?.preset ?? currentPreset;
  currentColors = mergeTheme(theme);
  applyToDom(currentColors);
  return { ...currentColors };
}

export function getThemePresets(): ThemePresetId[] {
  return Object.keys(PRESETS) as ThemePresetId[];
}

export function getDefaultTheme(): AsukaTheme {
  return {
    colors: {
      surface: DEFAULT_COLORS['layout.appBg'],
      surfaceAlt: DEFAULT_COLORS['layout.panelBg'],
      borderSubtle: DEFAULT_COLORS['border.subtle'],
      borderStrong: DEFAULT_COLORS['border.strong'],
      textMain: DEFAULT_COLORS['text.primary'],
      textMuted: DEFAULT_COLORS['text.secondary'],
      primary: DEFAULT_COLORS['accent.primary'],
      primarySoft: DEFAULT_COLORS['accent.primarySoft'],
      accent: DEFAULT_COLORS['accent.success'],
    },
  };
}
