/**
 * Theme switcher component.
 * Applies theme (light, dark, latte, frappe, macchiato, mocha) to a root element.
 * Use global (root = document.documentElement) or namespaced (root = .color-punch-root).
 *
 * Pass a container (selector or element); the script builds the trigger button and
 * dropdown panel inside it. Optional statusLabelId for an external "Current theme" label.
 *
 * @example
 * const sw = new ThemeSwitcher({
 *   container: '#theme-switcher',
 *   root: document.documentElement,
 *   storageKey: 'my-theme',
 *   statusLabelId: 'current-theme'
 * });
 * sw.init();
 */

const THEMES = {
  light: { name: 'Light', dark: false },
  dark: { name: 'Dark', dark: true },
  latte: { name: 'Latte', dark: false },
  frappe: { name: 'Frappé', dark: true },
  macchiato: { name: 'Macchiato', dark: true },
  mocha: { name: 'Mocha', dark: true }
};

const THEME_IDS = Object.keys(THEMES);

function getPreferred() {
  return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

function isDarkTheme(theme) {
  return THEMES[theme]?.dark === true;
}

function getRoot(option) {
  if (option === undefined || option === null) return document.documentElement;
  if (typeof option === 'string') return document.querySelector(option) ?? document.documentElement;
  if (option?.nodeType === 1) return option;
  return document.documentElement;
}

function applyThemeToRoot(rootEl, theme) {
  rootEl.classList.toggle('dark', isDarkTheme(theme));
  rootEl.setAttribute('data-theme', theme);
}

class ThemeSwitcher {
  constructor(options = {}) {
    this.container = options.container;
    this.root = options.root;
    this.storageKey = options.storageKey ?? 'framework-theme';
    this.statusLabelId = options.statusLabelId ?? null;

    this.rootEl = getRoot(this.root);
    this.containerEl = typeof this.container === 'string'
      ? document.querySelector(this.container)
      : this.container;

    if (this.containerEl && !this.root && this.containerEl.closest('.color-punch-root')) {
      this.rootEl = this.containerEl.closest('.color-punch-root');
    }

    this.trigger = null;
    this.triggerLabel = null;
    this.panel = null;
    this.statusLabel = this.statusLabelId ? document.getElementById(this.statusLabelId) : null;
  }

  apply(theme) {
    const id = THEME_IDS.includes(theme) ? theme : 'light';
    applyThemeToRoot(this.rootEl, id);
    if (this.triggerLabel) this.triggerLabel.firstChild.textContent = THEMES[id].name;
    if (this.statusLabel) this.statusLabel.textContent = `${THEMES[id].name} theme`;
    if (this.panel) {
      this.panel.querySelectorAll('[data-theme]').forEach((btn) => {
        btn.setAttribute('aria-selected', btn.getAttribute('data-theme') === id ? 'true' : 'false');
      });
    }
    return id;
  }

  render() {
    if (!this.containerEl) return;

    const lightThemes = ['light'];
    const darkThemes = ['dark'];
    const catppuccinThemes = ['latte', 'frappe', 'macchiato', 'mocha'];
    const colorPunchThemes = ['light', 'dark'];

    const dropdown = document.createElement('div');
    dropdown.className = 'theme-dropdown';

    const trigger = document.createElement('button');
    trigger.type = 'button';
    trigger.className = 'theme-toggle btn btn--ghost no-lift hover:text-primary ';
    trigger.setAttribute('aria-expanded', 'false');
    trigger.setAttribute('aria-haspopup', 'menu');
    trigger.setAttribute('aria-label', 'Select theme');
    const iconSpan = document.createElement('span');
    iconSpan.className = 'theme-toggle-icon icon icon--lg';
    iconSpan.innerHTML = '<i class="fa-solid fa-palette"></i>';
    trigger.appendChild(iconSpan);
    const labelSpan = document.createElement('span');
    labelSpan.className = 'theme-trigger-label';
    const labelText = document.createTextNode('');
    labelSpan.appendChild(labelText);
    const arrowText = document.createTextNode(' \u25BC');
    labelSpan.appendChild(arrowText);
    trigger.appendChild(labelSpan);
    dropdown.appendChild(trigger);

    const panel = document.createElement('div');
    panel.className = 'theme-dropdown-panel';
    panel.setAttribute('role', 'menu');
    panel.setAttribute('aria-label', 'Theme');
    panel.hidden = true;

    const group = (title, ids) => {
      const g = document.createElement('div');
      g.className = 'theme-dropdown-group';
      g.setAttribute('role', 'presentation');
      g.textContent = title;
      panel.appendChild(g);
      ids.forEach((id) => {
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.setAttribute('role', 'menuitem');
        btn.setAttribute('data-theme', id);
        btn.textContent = THEMES[id].name;
        panel.appendChild(btn);
      });
    };

    group('Color Punch', colorPunchThemes);
    group('Catppuccin', catppuccinThemes);

    dropdown.appendChild(panel);
    this.containerEl.replaceChildren(dropdown);

    this.trigger = trigger;
    this.triggerLabel = labelSpan;
    this.panel = panel;
  }

  init() {
    this.render();
    if (!this.trigger || !this.panel) return;

    const stored = localStorage.getItem(this.storageKey);
    const theme = (stored && THEME_IDS.includes(stored)) ? stored : getPreferred();
    this.apply(theme);

    this.trigger.addEventListener('click', (e) => {
      e.stopPropagation();
      const open = !this.panel.hidden;
      this.panel.hidden = open;
      this.trigger.setAttribute('aria-expanded', !open);
    });

    this.panel.querySelectorAll('[data-theme]').forEach((btn) => {
      btn.addEventListener('click', () => {
        const themeId = btn.getAttribute('data-theme');
        localStorage.setItem(this.storageKey, themeId);
        this.apply(themeId);
        this.panel.hidden = true;
        this.trigger.setAttribute('aria-expanded', 'false');
      });
    });

    document.addEventListener('click', () => {
      this.panel.hidden = true;
      this.trigger.setAttribute('aria-expanded', 'false');
    });

    if (window.matchMedia) {
      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
        if (localStorage.getItem(this.storageKey)) return;
        this.apply(e.matches ? 'dark' : 'light');
      });
    }
  }
}

window.ThemeSwitcher = ThemeSwitcher;
