import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { usePublicSettings } from '../hooks/usePublicSettings';
import { facrApi } from '../services/facr/facrApi';
import { extractPalette, pickTextColor, isContrastAccessible } from '../utils/colors';
import { fetchLogoFromLogoAPI } from '../utils/sportLogosAPI';

export interface ClubTheme {
  primary: string;
  secondary: string;
  accent: string;
  textOnPrimary: string;
  textOnSecondary?: string;
  textOnAccent?: string;
  background?: string;
  text?: string;
  logoUrl?: string;
  name?: string;
}

const defaultTheme: ClubTheme = {
  primary: '#0b5cff',
  secondary: '#ffd200',
  accent: '#141414',
  textOnPrimary: '#ffffff',
};

const ClubThemeContext = createContext<ClubTheme>(defaultTheme);

export const useClubTheme = () => useContext(ClubThemeContext);

export const ClubThemeProvider: React.FC<{ children: React.ReactNode }>= ({ children }) => {
  const { data: settings } = usePublicSettings();
  const clubId = settings?.club_id;
  const clubType = settings?.club_type || 'football';

  const [theme, setTheme] = useState<ClubTheme>(defaultTheme);

  // Create a stable settings key to prevent unnecessary re-runs
  const settingsKey = useMemo(() => {
    if (!settings) return null;
    const key = JSON.stringify({
      primary_color: settings.primary_color,
      secondary_color: settings.secondary_color,
      accent_color: settings.accent_color,
      text_color: settings.text_color,
      background_color: settings.background_color,
      club_logo_url: settings.club_logo_url,
      club_id: settings.club_id,
      club_type: settings.club_type,
      club_name: settings.club_name,
    });
    return key;
  }, [settings]);

  useEffect(() => {
    if (!settingsKey) return; // Don't run if no settings available
    
    let mounted = true;
    (async () => {
      try {
        // Prefer explicit settings from Admin if available
        const explicitPrimary = settings?.primary_color && settings.primary_color.trim() !== '' ? settings.primary_color : undefined;
        const explicitSecondary = settings?.secondary_color && settings.secondary_color.trim() !== '' ? settings.secondary_color : undefined;
        const explicitAccent = settings?.accent_color && settings.accent_color.trim() !== '' ? settings.accent_color : undefined;
        const explicitText = settings?.text_color && settings.text_color.trim() !== '' ? settings.text_color : undefined;
        const explicitLogo = settings?.club_logo_url;
        const explicitName = settings?.club_name;
        const explicitBackground = settings?.background_color && settings.background_color.trim() !== '' ? settings.background_color : undefined;

        let primary = explicitPrimary;
        let secondary = explicitSecondary;
        let accent = explicitAccent;
        let textOnPrimary = explicitText;
        let textOnSecondary: string | undefined;
        let textOnAccent: string | undefined;
        let logoUrl = explicitLogo;
        let name = explicitName;
        let background = explicitBackground;
        let text = explicitText;

        // Strategy:
        // 1) If we have a logo URL, we can always extract colors from it even when clubId is missing.
        // 2) Only reach to FACR when logo or name are missing AND we do have a clubId.
        if (!primary || !secondary || !accent || !logoUrl || !name) {
          // If logo/name missing but we have clubId, fetch club basics
          if ((!logoUrl || !name) && clubId) {
            try {
              const club = await facrApi.getClub(clubId, clubType as any);
              // Prefer FACR temporarily; final preference will try logoapi below
              logoUrl = logoUrl || club.logo_url;
              name = name || club.name;
            } catch {
              // ignore fetch errors; we may still proceed with defaults/palette
            }
          }

          // If we have a logo at this point, try to extract palette regardless of clubId
          let colors: string[] = [];
          try {
            colors = logoUrl ? await extractPalette(logoUrl, 5) : [];
          } catch {
            colors = [];
          }
          primary = primary || colors[0] || defaultTheme.primary;
          secondary = secondary || colors[1] || defaultTheme.secondary;
          accent = accent || colors.find(c => pickTextColor(c) === '#ffffff') || '#1a1a1a';

          // If after all this we still lack logo/name and also have no clubId, do not hard fail; continue with colors and defaults
          if (!logoUrl && !clubId) {
            // keep logoUrl undefined; theme will still apply colors
          }
        }

        // Derive text colors for contrast
        textOnPrimary = textOnPrimary || pickTextColor(primary!);
        textOnSecondary = pickTextColor(secondary!);
        textOnAccent = pickTextColor(accent!);

        // Background/text fallbacks
        background = background || '#ffffff';
        // Choose readable text color directly based on background contrast
        // If background is light (e.g., white), this will return a dark color (e.g., black)
        // If background is dark, it will return white for readability
        text = text || pickTextColor(background!);

        // Ensure WCAG AA contrast for primary text if possible
        if (!isContrastAccessible(primary!, textOnPrimary)) {
          textOnPrimary = pickTextColor(primary!);
        }
        if (!isContrastAccessible(secondary!, textOnSecondary)) {
          textOnSecondary = pickTextColor(secondary!);
        }
        if (!isContrastAccessible(accent!, textOnAccent)) {
          textOnAccent = pickTextColor(accent!);
        }

        // Prefer logo from logoapi.sportcreative.eu when club ID is known
        if (clubId) {
          try {
            const apiLogo = await fetchLogoFromLogoAPI(String(clubId), name);
            if (apiLogo) {
              logoUrl = apiLogo;
            }
          } catch {
            // best-effort only
          }
        }

        const next: ClubTheme = {
          primary: primary!,
          secondary: secondary!,
          accent: accent!,
          textOnPrimary: textOnPrimary!,
          textOnSecondary,
          textOnAccent,
          background,
          text,
          logoUrl,
          name,
        };
        
        // Only update theme if it has actually changed
        if (mounted && (
          theme.primary !== next.primary ||
          theme.secondary !== next.secondary ||
          theme.accent !== next.accent ||
          theme.textOnPrimary !== next.textOnPrimary ||
          theme.logoUrl !== next.logoUrl ||
          theme.name !== next.name
        )) {
          setTheme(next);
          // expose CSS variables for raw CSS usage
          // NOTE: Do NOT set --club-bg or --club-text as they interfere with Chakra's dark mode
          const r = document.documentElement;
          r.style.setProperty('--club-primary', next.primary);
          r.style.setProperty('--club-secondary', next.secondary);
          r.style.setProperty('--club-accent', next.accent);
          r.style.setProperty('--club-text-on-primary', next.textOnPrimary);
          if (next.textOnSecondary) r.style.setProperty('--club-text-on-secondary', next.textOnSecondary);
          if (next.textOnAccent) r.style.setProperty('--club-text-on-accent', next.textOnAccent);
          // Only set these as fallbacks, they should not override dark mode
          r.style.setProperty('--club-bg-light', background!);
          r.style.setProperty('--club-text-light', text!);
          
          // Cache colors in localStorage for instant loading on next visit
          try {
            localStorage.setItem('club_theme_cache', JSON.stringify({
              primary: next.primary,
              secondary: next.secondary,
              accent: next.accent,
              textOnPrimary: next.textOnPrimary,
              textOnSecondary: next.textOnSecondary,
              textOnAccent: next.textOnAccent,
              background,
              text,
              timestamp: Date.now()
            }));
          } catch (e) {
            // localStorage may fail in private browsing
          }
        }
      } catch (error) {
        console.warn('ClubTheme: Error updating theme:', error);
        // Don't reset to default theme on error - keep current theme
      }
    })();
    return () => { mounted = false; };
  }, [settingsKey]);

  const value = useMemo(() => theme, [theme]);
  return (
    <ClubThemeContext.Provider value={value}>{children}</ClubThemeContext.Provider>
  );
};
