'use client';

import { persistTheme, themePreferenceEvent } from '@/lib/theme/client';
import { themePreferences, themeStorageKey, type ThemePreference } from '@/lib/theme/config';
import { useEffect, useId, useState } from 'react';
import styles from './Controls.module.css';

interface ThemeSelectorProps {
  initialPreference: ThemePreference;
  label: string;
  statusTemplate: string;
  optionLabels: Record<ThemePreference, string>;
  compact?: boolean;
}

export function ThemeSelector({
  initialPreference,
  label,
  statusTemplate,
  optionLabels,
  compact = false,
}: ThemeSelectorProps) {
  const [preference, setPreference] = useState<ThemePreference>(initialPreference);
  const statusId = useId();

  useEffect(() => {
    const handleStorage = (event: StorageEvent) => {
      if (
        event.key === themeStorageKey &&
        (event.newValue === 'light' || event.newValue === 'dark' || event.newValue === 'system')
      ) {
        setPreference(event.newValue);
      }
    };
    const handlePreference = (event: Event) => {
      const preferenceEvent = event as CustomEvent<ThemePreference>;
      setPreference(preferenceEvent.detail);
    };
    window.addEventListener('storage', handleStorage);
    window.addEventListener(themePreferenceEvent, handlePreference);
    return () => {
      window.removeEventListener('storage', handleStorage);
      window.removeEventListener(themePreferenceEvent, handlePreference);
    };
  }, []);

  const status = statusTemplate.replace('{value}', optionLabels[preference]);

  return (
    <label className={styles.field}>
      <span className={compact ? styles.compactLabel : styles.label}>{label}</span>
      <select
        className={styles.select}
        aria-label={label}
        aria-describedby={statusId}
        value={preference}
        onChange={(event) => {
          const nextPreference = event.target.value as ThemePreference;
          setPreference(nextPreference);
          persistTheme(nextPreference);
        }}
      >
        {themePreferences.map((option) => (
          <option key={option} value={option}>
            {optionLabels[option]}
          </option>
        ))}
      </select>
      <span id={statusId} className="visually-hidden" aria-live="polite">
        {status}
      </span>
    </label>
  );
}
