/**
 * Theme Controller
 *
 * Handles dark/light mode switching and system preference detection
 */

export type Theme = 'light' | 'dark' | 'system';

export class ThemeController {
  private static readonly STORAGE_KEY = 'theme-preference';
  private static readonly DARK_CLASS = 'dark-mode';
  private static readonly LIGHT_CLASS = 'light-mode';

  private root: HTMLElement;
  private themeOptions: NodeListOf<HTMLElement>;

  constructor() {
    this.root = document.documentElement;
    this.themeOptions = document.querySelectorAll<HTMLElement>('swp-theme-option');

    this.applyTheme(this.current);
    this.updateUI();
    this.setupListeners();
  }

  /**
   * Get the current theme setting
   */
  get current(): Theme {
    const stored = localStorage.getItem(ThemeController.STORAGE_KEY) as Theme | null;
    if (stored === 'dark' || stored === 'light' || stored === 'system') {
      return stored;
    }
    return 'system';
  }

  /**
   * Check if dark mode is currently active
   */
  get isDark(): boolean {
    return this.root.classList.contains(ThemeController.DARK_CLASS) ||
      (this.systemPrefersDark && !this.root.classList.contains(ThemeController.LIGHT_CLASS));
  }

  /**
   * Check if system prefers dark mode
   */
  get systemPrefersDark(): boolean {
    return window.matchMedia('(prefers-color-scheme: dark)').matches;
  }

  /**
   * Set theme and persist preference
   */
  set(theme: Theme): void {
    localStorage.setItem(ThemeController.STORAGE_KEY, theme);
    this.applyTheme(theme);
    this.updateUI();
  }

  /**
   * Toggle between light and dark themes
   */
  toggle(): void {
    this.set(this.isDark ? 'light' : 'dark');
  }

  private applyTheme(theme: Theme): void {
    this.root.classList.remove(ThemeController.DARK_CLASS, ThemeController.LIGHT_CLASS);

    if (theme === 'dark') {
      this.root.classList.add(ThemeController.DARK_CLASS);
    } else if (theme === 'light') {
      this.root.classList.add(ThemeController.LIGHT_CLASS);
    }
    // 'system' leaves both classes off, letting CSS media query handle it
  }

  private updateUI(): void {
    if (!this.themeOptions) return;

    const darkActive = this.isDark;

    this.themeOptions.forEach(option => {
      const theme = option.dataset.theme as Theme;
      const isActive = (theme === 'dark' && darkActive) || (theme === 'light' && !darkActive);
      option.classList.toggle('active', isActive);
    });
  }

  private setupListeners(): void {
    // Theme option clicks
    this.themeOptions.forEach(option => {
      option.addEventListener('click', (e) => this.handleOptionClick(e));
    });

    // System theme changes
    window.matchMedia('(prefers-color-scheme: dark)')
      .addEventListener('change', () => this.handleSystemChange());
  }

  private handleOptionClick(e: Event): void {
    const target = e.target as HTMLElement;
    const option = target.closest<HTMLElement>('swp-theme-option');

    if (option) {
      const theme = option.dataset.theme as Theme;
      if (theme) {
        this.set(theme);
      }
    }
  }

  private handleSystemChange(): void {
    // Only react to system changes if we're using system preference
    if (this.current === 'system') {
      this.updateUI();
    }
  }
}
