import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';

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

type AppearanceContextValue = {
  appearance: Appearance;
  resolved: 'light' | 'dark';
  updateAppearance: (mode: Appearance) => void;
};

const AppearanceContext = createContext<AppearanceContextValue>({
  appearance: 'system',
  resolved: 'light',
  updateAppearance: () => {},
});

function resolveTheme(mode: Appearance): 'light' | 'dark' {
  if (mode === 'dark') return 'dark';
  if (mode === 'light') return 'light';
  return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

function applyDocumentClass(theme: 'light' | 'dark') {
  if (theme === 'dark') {
    document.documentElement.classList.add('dark');
  } else {
    document.documentElement.classList.remove('dark');
  }
}

export function AppearanceProvider({ children }: { children: React.ReactNode }) {
  const [appearance, setAppearance] = useState<Appearance>(() => {
    const stored = localStorage.getItem('theme') as Appearance | null;
    return stored ?? 'system';
  });
  const [resolved, setResolved] = useState<'light' | 'dark'>(() => resolveTheme(appearance));

  useEffect(() => {
    const nextResolved = resolveTheme(appearance);
    setResolved(nextResolved);
    applyDocumentClass(nextResolved);

    if (appearance === 'system') {
      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
      const listener = () => {
        const resolvedTheme = mediaQuery.matches ? 'dark' : 'light';
        setResolved(resolvedTheme);
        applyDocumentClass(resolvedTheme);
      };
      mediaQuery.addEventListener('change', listener);
      return () => mediaQuery.removeEventListener('change', listener);
    }

    return undefined;
  }, [appearance]);

  const updateAppearance = (mode: Appearance) => {
    setAppearance(mode);
    localStorage.setItem('theme', mode);
  };

  const value = useMemo(
    () => ({
      appearance,
      resolved,
      updateAppearance,
    }),
    [appearance, resolved]
  );

  return React.createElement(AppearanceContext.Provider, { value }, children);
}

export function useAppearance(): AppearanceContextValue {
  return useContext(AppearanceContext);
}

export function initializeTheme() {
  const stored = localStorage.getItem('theme') as Appearance | null;
  const mode = stored ?? 'system';
  const resolved = resolveTheme(mode);
  applyDocumentClass(resolved);
}
