import { useState, useEffect, useCallback, useRef } from 'react';
import { EnabledThemes, DEFAULT_ENABLED_THEMES } from '../types/theme';
import { themeColorsApi } from '../api/themeColors';
import { STORAGE_KEYS } from '../config/constants';
import { getTelegramColorScheme } from './useTelegramSDK';

type Theme = 'dark' | 'light';

const THEME_KEY = STORAGE_KEYS.THEME;
const ENABLED_THEMES_KEY = STORAGE_KEYS.ENABLED_THEMES;

// Fetch enabled themes from API
async function fetchEnabledThemes(): Promise<EnabledThemes> {
  try {
    const data = await themeColorsApi.getEnabledThemes();
    // Cache in localStorage for faster subsequent loads
    localStorage.setItem(ENABLED_THEMES_KEY, JSON.stringify(data));
    return data;
  } catch {
    // Ignore errors, use cached or default
  }
  // Try to get from cache
  const cached = localStorage.getItem(ENABLED_THEMES_KEY);
  if (cached) {
    try {
      return JSON.parse(cached);
    } catch {
      // Ignore parse errors
    }
  }
  return DEFAULT_ENABLED_THEMES;
}

// Get cached enabled themes synchronously
function getCachedEnabledThemes(): EnabledThemes {
  const cached = localStorage.getItem(ENABLED_THEMES_KEY);
  if (cached) {
    try {
      return JSON.parse(cached);
    } catch {
      // Ignore parse errors
    }
  }
  return DEFAULT_ENABLED_THEMES;
}

// Custom events for same-tab updates
const ENABLED_THEMES_CHANGED_EVENT = 'enabledThemesChanged';
const THEME_CHANGED_EVENT = 'themeChanged';

// Update cache (called from admin settings)
export function updateEnabledThemesCache(themes: EnabledThemes) {
  localStorage.setItem(ENABLED_THEMES_KEY, JSON.stringify(themes));
  // Dispatch custom event for same-tab updates
  window.dispatchEvent(new CustomEvent(ENABLED_THEMES_CHANGED_EVENT, { detail: themes }));
}

export function useTheme() {
  const [enabledThemes, setEnabledThemes] = useState<EnabledThemes>(getCachedEnabledThemes);
  const [isLoading, setIsLoading] = useState(true);

  const [theme, setThemeState] = useState<Theme>(() => {
    const enabled = getCachedEnabledThemes();

    // Check localStorage first
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(THEME_KEY) as Theme | null;
      if (stored === 'light' && enabled.light) {
        return 'light';
      }
      if (stored === 'dark' && enabled.dark) {
        return 'dark';
      }
      // If stored theme is disabled, use the enabled one
      if (stored && !enabled[stored]) {
        return enabled.dark ? 'dark' : 'light';
      }
      // No stored preference: follow the Telegram client's color scheme in a Mini App.
      if (!stored) {
        const tgScheme = getTelegramColorScheme();
        if (tgScheme && enabled[tgScheme]) {
          return tgScheme;
        }
      }
      // Check system preference
      if (window.matchMedia('(prefers-color-scheme: light)').matches && enabled.light) {
        return 'light';
      }
    }
    // Default to dark if enabled, otherwise light
    return enabled.dark ? 'dark' : 'light';
  });

  const themeRef = useRef(theme);
  themeRef.current = theme;

  // Fetch enabled themes on mount
  useEffect(() => {
    fetchEnabledThemes().then((data) => {
      setEnabledThemes(data);
      setIsLoading(false);
      // If current theme is disabled, switch to enabled one
      if (!data[themeRef.current]) {
        const newTheme = data.dark ? 'dark' : 'light';
        setThemeState(newTheme);
      }
    });
  }, []);

  // Listen for localStorage changes (when admin updates enabled themes from other tabs)
  useEffect(() => {
    const handleStorageChange = (e: StorageEvent) => {
      if (e.key === ENABLED_THEMES_KEY && e.newValue) {
        try {
          const data = JSON.parse(e.newValue) as EnabledThemes;
          setEnabledThemes(data);
          // If current theme is now disabled, switch to enabled one
          if (!data[theme]) {
            const newTheme = data.dark ? 'dark' : 'light';
            setThemeState(newTheme);
          }
        } catch {
          // Ignore parse errors
        }
      }
    };

    window.addEventListener('storage', handleStorageChange);
    return () => window.removeEventListener('storage', handleStorageChange);
  }, [theme]);

  // Listen for same-tab enabled themes changes (from admin settings)
  useEffect(() => {
    const handleEnabledThemesChange = (e: CustomEvent<EnabledThemes>) => {
      const data = e.detail;
      setEnabledThemes(data);
      // If current theme is now disabled, switch to enabled one
      if (!data[theme]) {
        const newTheme = data.dark ? 'dark' : 'light';
        setThemeState(newTheme);
      }
    };

    window.addEventListener(
      ENABLED_THEMES_CHANGED_EVENT,
      handleEnabledThemesChange as EventListener,
    );
    return () =>
      window.removeEventListener(
        ENABLED_THEMES_CHANGED_EVENT,
        handleEnabledThemesChange as EventListener,
      );
  }, [theme]);

  // Apply theme to document - also check if theme is disabled and switch
  useEffect(() => {
    const root = document.documentElement;

    // If current theme is disabled, switch to the enabled one
    if (!enabledThemes[theme]) {
      const newTheme = enabledThemes.dark ? 'dark' : 'light';
      if (newTheme !== theme) {
        setThemeState(newTheme);
        return; // Will re-run with correct theme
      }
    }

    if (theme === 'light') {
      root.classList.remove('dark');
      root.classList.add('light');
    } else {
      root.classList.remove('light');
      root.classList.add('dark');
    }

    localStorage.setItem(THEME_KEY, theme);
    // Notify other useTheme() instances in the same tab
    window.dispatchEvent(new CustomEvent(THEME_CHANGED_EVENT, { detail: theme }));
  }, [theme, enabledThemes]);

  // Listen for same-tab theme changes (from other useTheme() instances)
  useEffect(() => {
    const handleThemeChange = (e: CustomEvent<Theme>) => {
      setThemeState(e.detail);
    };

    window.addEventListener(THEME_CHANGED_EVENT, handleThemeChange as EventListener);
    return () =>
      window.removeEventListener(THEME_CHANGED_EVENT, handleThemeChange as EventListener);
  }, []);

  // Listen for system theme changes
  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-color-scheme: light)');

    const handleChange = (e: MediaQueryListEvent) => {
      const stored = localStorage.getItem(THEME_KEY);
      // Only auto-switch if user hasn't set a preference and theme is enabled
      if (!stored) {
        const newTheme = e.matches ? 'light' : 'dark';
        if (enabledThemes[newTheme]) {
          setThemeState(newTheme);
        }
      }
    };

    mediaQuery.addEventListener('change', handleChange);
    return () => mediaQuery.removeEventListener('change', handleChange);
  }, [enabledThemes]);

  const setTheme = useCallback(
    (newTheme: Theme) => {
      // Only allow setting if theme is enabled
      if (enabledThemes[newTheme]) {
        setThemeState(newTheme);
      }
    },
    [enabledThemes],
  );

  const toggleTheme = useCallback(() => {
    setThemeState((prev) => {
      const newTheme = prev === 'dark' ? 'light' : 'dark';
      // Only toggle if the new theme is enabled
      if (enabledThemes[newTheme]) {
        return newTheme;
      }
      return prev;
    });
  }, [enabledThemes]);

  const isDark = theme === 'dark';
  const isLight = theme === 'light';

  // Check if theme switching is available (both themes enabled and loaded)
  const canToggle = !isLoading && enabledThemes.dark && enabledThemes.light;

  // Refresh enabled themes from API
  const refreshEnabledThemes = useCallback(() => {
    fetchEnabledThemes().then((data) => {
      setEnabledThemes(data);
      if (!data[theme]) {
        const newTheme = data.dark ? 'dark' : 'light';
        setThemeState(newTheme);
      }
    });
  }, [theme]);

  return {
    theme,
    setTheme,
    toggleTheme,
    isDark,
    isLight,
    enabledThemes,
    canToggle,
    isLoading,
    refreshEnabledThemes,
  };
}
