// Theme store — persists theme selection via settings bridge

import { getSetting, setSetting } from '../adapters/settings-bridge';
import { handleInfraError } from '../utils/handle-error';
import {
  type ThemeId,
  type ThemePalette,
  type CatppuccinFlavor,
  ALL_THEME_IDS,
  buildXtermTheme,
  buildXtermThemeFromPalette,
  applyCssVariables,
  applyPaletteDirect,
  type XtermTheme,
} from '../styles/themes';

let currentTheme = $state<ThemeId>('mocha');
let customPalette = $state<ThemePalette | null>(null);

/** Registered theme-change listeners */
const themeChangeCallbacks = new Set<() => void>();

/** Register a callback invoked after every theme change. Returns an unsubscribe function. */
export function onThemeChange(callback: () => void): () => void {
  themeChangeCallbacks.add(callback);
  return () => {
    themeChangeCallbacks.delete(callback);
  };
}

export function getCurrentTheme(): ThemeId {
  return currentTheme;
}

/** @deprecated Use getCurrentTheme() */
export function getCurrentFlavor(): CatppuccinFlavor {
  // Return valid CatppuccinFlavor or default to 'mocha'
  const catFlavors: string[] = ['latte', 'frappe', 'macchiato', 'mocha'];
  return catFlavors.includes(currentTheme) ? currentTheme as CatppuccinFlavor : 'mocha';
}

export function getXtermTheme(): XtermTheme {
  if (customPalette) return buildXtermThemeFromPalette(customPalette);
  return buildXtermTheme(currentTheme);
}

/** Apply an arbitrary palette for live preview (does NOT persist) */
export function previewPalette(palette: ThemePalette): void {
  customPalette = palette;
  applyPaletteDirect(palette);
  for (const cb of themeChangeCallbacks) {
    try { cb(); } catch (e) { handleInfraError(e, 'theme.previewCallback'); }
  }
}

/** Clear custom palette preview, revert to current built-in theme */
export function clearPreview(): void {
  customPalette = null;
  applyCssVariables(currentTheme);
  for (const cb of themeChangeCallbacks) {
    try { cb(); } catch (e) { handleInfraError(e, 'theme.clearPreviewCallback'); }
  }
}

/** Set a custom theme as active (persists the custom theme ID) */
export async function setCustomTheme(id: string, palette: ThemePalette): Promise<void> {
  customPalette = palette;
  applyPaletteDirect(palette);
  for (const cb of themeChangeCallbacks) {
    try { cb(); } catch (e) { handleInfraError(e, 'theme.customCallback'); }
  }
  try {
    await setSetting('theme', id);
  } catch (e) {
    handleInfraError(e, 'theme.persistCustom');
  }
}

/** Check if current theme is a custom theme */
export function isCustomThemeActive(): boolean {
  return customPalette !== null;
}

/** Change theme, apply CSS variables, and persist to settings DB */
export async function setTheme(theme: ThemeId): Promise<void> {
  currentTheme = theme;
  applyCssVariables(theme);
  // Notify all listeners (e.g. open xterm.js terminals)
  for (const cb of themeChangeCallbacks) {
    try {
      cb();
    } catch (e) {
      handleInfraError(e, 'theme.changeCallback');
    }
  }

  try {
    await setSetting('theme', theme);
  } catch (e) {
    handleInfraError(e, 'theme.persistSetting');
  }
}

/** @deprecated Use setTheme() */
export async function setFlavor(flavor: CatppuccinFlavor): Promise<void> {
  return setTheme(flavor);
}

/** Load saved theme from settings DB and apply. Call once on app startup. */
export async function initTheme(): Promise<void> {
  try {
    const saved = await getSetting('theme');
    if (saved) {
      if (saved.startsWith('custom:')) {
        // Custom theme — load palette from custom_themes storage
        const { loadCustomThemes } = await import('../styles/custom-themes');
        const customs = await loadCustomThemes();
        const match = customs.find(c => c.id === saved);
        if (match) {
          customPalette = match.palette;
          applyPaletteDirect(match.palette);
        }
      } else if (ALL_THEME_IDS.includes(saved as ThemeId)) {
        currentTheme = saved as ThemeId;
      }
    }
  } catch {
    // Fall back to default (mocha) — catppuccin.css provides Mocha defaults
  }
  // Always apply to sync CSS vars with current theme (skip if custom already applied)
  if (!customPalette && currentTheme !== 'mocha') {
    applyCssVariables(currentTheme);
  }

  // Apply saved font settings
  try {
    const [uiFont, uiSize, termFont, termSize] = await Promise.all([
      getSetting('ui_font_family'),
      getSetting('ui_font_size'),
      getSetting('term_font_family'),
      getSetting('term_font_size'),
    ]);
    const root = document.documentElement.style;
    if (uiFont) root.setProperty('--ui-font-family', `'${uiFont}', sans-serif`);
    if (uiSize) root.setProperty('--ui-font-size', `${uiSize}px`);
    if (termFont) root.setProperty('--term-font-family', `'${termFont}', monospace`);
    if (termSize) root.setProperty('--term-font-size', `${termSize}px`);
  } catch {
    // Font settings are optional — defaults from catppuccin.css apply
  }
}
