import React, { createContext, useContext, useMemo, useState, useEffect } from 'react';
import { useColorScheme, I18nManager } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import type { Locale } from '@ai-radar/shared';
import { dark, light, type Palette } from './tokens';

type ThemeChoice = 'system' | 'light' | 'dark';

interface AppTheme {
  palette: Palette;
  /** The resolved scheme, after 'system' is applied. */
  scheme: 'light' | 'dark';
  choice: ThemeChoice;
  setChoice: (c: ThemeChoice) => void;

  locale: Locale;
  setLocale: (l: Locale) => void;
  rtl: boolean;
}

const ThemeContext = createContext<AppTheme | null>(null);

const THEME_KEY = 'airadar.theme';
const LOCALE_KEY = 'airadar.locale';

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const system = useColorScheme();
  const [choice, setChoiceState] = useState<ThemeChoice>('system');
  const [locale, setLocaleState] = useState<Locale>('en');
  const [loaded, setLoaded] = useState(false);

  // Restore preferences before the first paint we care about. Rendering
  // English-light and then snapping to Arabic-dark is worse than a beat
  // of nothing.
  useEffect(() => {
    (async () => {
      try {
        const [t, l] = await AsyncStorage.multiGet([THEME_KEY, LOCALE_KEY]);
        if (t[1] === 'light' || t[1] === 'dark' || t[1] === 'system') {
          setChoiceState(t[1]);
        }
        if (l[1] === 'ar' || l[1] === 'en') setLocaleState(l[1]);
      } catch {
        // Storage unavailable is not an error worth showing: defaults
        // are correct, they just will not persist.
      } finally {
        setLoaded(true);
      }
    })();
  }, []);

  const setChoice = (c: ThemeChoice) => {
    setChoiceState(c);
    void AsyncStorage.setItem(THEME_KEY, c).catch(() => {});
  };

  const setLocale = (l: Locale) => {
    setLocaleState(l);
    void AsyncStorage.setItem(LOCALE_KEY, l).catch(() => {});
  };

  const scheme: 'light' | 'dark' =
    choice === 'system' ? (system === 'light' ? 'light' : 'dark') : choice;

  const rtl = locale === 'ar';

  // Text direction only. Deliberately NOT I18nManager.forceRTL: that
  // needs an app restart to take effect, so a language switch would
  // appear to do nothing. Screens use writingDirection and
  // start/end spacing instead, which flip immediately.
  useEffect(() => {
    I18nManager.allowRTL(true);
  }, []);

  const value = useMemo<AppTheme>(
    () => ({
      palette: scheme === 'dark' ? dark : light,
      scheme,
      choice,
      setChoice,
      locale,
      setLocale,
      rtl,
    }),
    [scheme, choice, locale, rtl],
  );

  // Hold the first render until preferences are known.
  if (!loaded) return null;

  return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
}

export function useTheme(): AppTheme {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
  return ctx;
}
