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

import { BrandColors, ColorTheme, PALETTE, colorThemes } from './theme-data';
import { hexToRgb } from '../utils/color-utils';

interface BrandColorsContextType {
  colors: BrandColors;
  currentTheme: string;
  themes: ColorTheme[];
  setTheme: (themeId: string) => void;
  setBrandColor: (colorKey: keyof BrandColors, value: string) => void;
  radius: number;
  setRadius: (radius: number) => void;
}

const BrandColorsContext = createContext<BrandColorsContextType | undefined>(undefined);

interface BrandColorsProviderProps {
  children: React.ReactNode;
  defaultTheme?: string;
  primaryColor?: string;
  useCustomTokens?: boolean;
}

export const BrandColorsProvider: React.FC<BrandColorsProviderProps> = ({
  children,
  defaultTheme,
  primaryColor,
  useCustomTokens = false,
}) => {
  const [currentTheme, setCurrentTheme] = useState<string>(() => {
    // Se primaryColor for passado, ignoramos o nome do tema
    if (primaryColor) return 'custom';
    return defaultTheme || 'xertica-original';
  });

  const [radius, setRadius] = useState<number>(0.5);

  const [colors, setColors] = useState<BrandColors>(() => {
    if (primaryColor) {
      // Criar um tema sob demanda baseado na cor primária
      return {
        ...colorThemes[0].colors,
        primary: primaryColor,
        primaryDarkMode: primaryColor,
        sidebarLight: primaryColor,
        sidebarDark: primaryColor,
        chart1: primaryColor,
      };
    }
    const theme = colorThemes.find(t => t.id === currentTheme);
    return theme?.colors || colorThemes[0].colors;
  });

  useEffect(() => {
    if (primaryColor) {
      setColors({
        ...colorThemes[0].colors,
        primary: primaryColor,
        primaryDarkMode: primaryColor,
        sidebarLight: primaryColor,
        sidebarDark: primaryColor,
        chart1: primaryColor,
      });
      setCurrentTheme('custom');
      return;
    }
    const theme = colorThemes.find(t => t.id === currentTheme);
    if (theme) {
      setColors(theme.colors);
    }
  }, [currentTheme, primaryColor]);

  // Função para aplicar as cores baseadas no modo atual e tema
  const applyColors = React.useCallback(() => {
    if (useCustomTokens) return; // Skip if user wants to use local tokens.css
    if (typeof document === 'undefined') return;

    const root = document.documentElement;
    const isDark = root.classList.contains('dark');

    // --- Determine Colors based on Mode ---
    const primary = isDark ? colors.primaryDarkMode : colors.primary;
    const primaryForeground = isDark ? colors.primaryForegroundDark : colors.primaryForeground;

    // Gradient Logic
    const gradientStart = isDark ? colors.gradientStartDark : colors.gradientStart;
    const gradientEnd = isDark ? colors.gradientEndDark : colors.gradientEnd;

    // --- Semantic Colors (Fixed Standard, overridable per theme in light mode) ---
    // Success (Green), Warning (Amber/Yellow), Info (Blue), Destructive (Red)
    const semantic = {
      success: isDark ? '#4ade80' : colors.successColor || '#047857', // Green 400 / 700
      warning: isDark ? '#fbbf24' : colors.warningColor || '#b45309', // Amber 400 / 700
      info: isDark ? '#60a5fa' : colors.infoColor || '#1d4ed8', // Blue 400 / 700
      destructive: isDark ? '#f87171' : colors.destructiveColor || '#b91c1c', // Red 400 / 700
      foreground: isDark ? '#050505' : '#ffffff',
    };

    // --- Apply CSS Variables ---
    const cssVars: string[] = [];

    // 1. Core Primary Colors
    cssVars.push(`--primary: ${primary}`);
    cssVars.push(`--primary-foreground: ${primaryForeground}`);

    // 2. Semantic Colors
    cssVars.push(`--success: ${semantic.success}`);
    cssVars.push(`--success-foreground: ${semantic.foreground}`);
    cssVars.push(`--warning: ${semantic.warning}`);
    cssVars.push(`--warning-foreground: ${semantic.foreground}`);
    cssVars.push(`--info: ${semantic.info}`);
    cssVars.push(`--info-foreground: ${semantic.foreground}`);
    cssVars.push(`--destructive: ${semantic.destructive}`);
    cssVars.push(`--destructive-foreground: ${semantic.foreground}`);

    // 3. Secondary & Accents (Derived or Specific)
    const primaryRGB = hexToRgb(primary);
    if (primaryRGB) {
      cssVars.push(
        `--ring: ${isDark ? colors.primaryDarkMode : `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`}`
      );

      // Also update the Xertica specific variables
      cssVars.push(`--xertica-primary: ${primary}`);
      cssVars.push(
        `--primary-light: rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.15)`
      );
      cssVars.push(`--primary-light-foreground: ${primary}`);
    }

    // 3. Radius
    cssVars.push(`--radius: ${radius}rem`);

    // 3b. Button shape overrides (identical in both modes; theme-specific, always emitted)
    cssVars.push(`--radius-button: ${colors.buttonRadius || '12px'}`);
    cssVars.push(`--button-stroke-width: ${colors.buttonStrokeWidth || '0px'}`);
    cssVars.push(`--button-font-weight: ${colors.buttonFontWeight || '500'}`);

    // 4. Charts
    cssVars.push(`--chart-1: ${colors.chart1}`);
    cssVars.push(`--chart-2: ${colors.chart2}`);
    cssVars.push(`--chart-3: ${colors.chart3}`);
    cssVars.push(`--chart-4: ${colors.chart4}`);
    cssVars.push(`--chart-5: ${colors.chart5}`);

    // 5. Sidebar (Override)
    const sidebarBg = isDark ? colors.sidebarDark : colors.sidebarLight;
    const isSidebarLight =
      sidebarBg.toLowerCase() === '#ffffff' ||
      sidebarBg.toLowerCase() === '#f3f4f6' ||
      sidebarBg.toLowerCase() === '#fafafa';
    const sidebarFg = isSidebarLight ? '#0F172A' : '#FFFFFF';

    cssVars.push(`--sidebar: ${sidebarBg}`);
    cssVars.push(`--sidebar-foreground: ${sidebarFg}`);

    if (primaryRGB) {
      if (isSidebarLight) {
        cssVars.push(
          `--sidebar-accent: rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.1)`
        );
        cssVars.push(`--sidebar-accent-foreground: ${primary}`);
        cssVars.push(`--sidebar-border: rgba(0,0,0,0.1)`);
      } else {
        cssVars.push(`--sidebar-accent: rgba(255, 255, 255, 0.1)`);
        cssVars.push(`--sidebar-accent-foreground: #FFFFFF`);
        cssVars.push(`--sidebar-border: rgba(255,255,255,0.1)`);
      }
      cssVars.push(`--sidebar-ring: rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`);
    }

    if (!isSidebarLight) {
      cssVars.push(`--sidebar-primary: #FFFFFF`);
      cssVars.push(`--sidebar-primary-foreground: ${primary}`);
    } else {
      cssVars.push(`--sidebar-primary: ${primary}`);
      cssVars.push(`--sidebar-primary-foreground: ${primaryForeground}`);
    }

    // 6. Gradients
    cssVars.push(
      `--gradient-diagonal: linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`
    );

    // 7. Surface colors for dark mode (tinted toward the theme hue)
    //    Only applied when dark surface tokens exist on the theme.
    const darkSurfaceVars: string[] = [];
    if (colors.darkBackground) {
      darkSurfaceVars.push(`--background: ${colors.darkBackground}`);
      darkSurfaceVars.push(`--card: ${colors.darkCard}`);
      darkSurfaceVars.push(`--popover: ${colors.darkCard}`);
      darkSurfaceVars.push(`--secondary: ${colors.darkMuted}`);
      darkSurfaceVars.push(`--muted: ${colors.darkMuted}`);
      darkSurfaceVars.push(`--accent: ${colors.darkMuted}`);
      darkSurfaceVars.push(`--border: ${colors.darkBorder}`);
      darkSurfaceVars.push(`--input: ${colors.darkMuted}`);
      darkSurfaceVars.push(`--input-background: ${colors.darkMuted}`);
    }

    // 7b. Button stroke/secondary tokens + light-mode page background.
    //     Always emitted (with fallbacks matching the pre-existing look) so
    //     switching away from a theme that defines them never leaves a stale value.
    const lightModeVars: string[] = [
      `--button-stroke-color: ${colors.buttonStrokeColor || 'transparent'}`,
      `--button-secondary-bg: ${colors.buttonSecondaryBg || 'var(--secondary)'}`,
      `--button-secondary-foreground: ${colors.buttonSecondaryForeground || 'var(--secondary-foreground)'}`,
      `--button-primary-bg: ${colors.buttonPrimaryBg || 'var(--primary)'}`,
      `--button-primary-foreground: ${colors.buttonPrimaryForeground || 'var(--primary-foreground)'}`,
    ];
    if (colors.backgroundLight) {
      // The app shell backdrop (e.g. AppLayout's `bg-muted` wrapper behind the
      // sidebar/content) reads `--muted`, not `--background` — mirror the
      // override so the shell matches the page background instead of falling
      // back to the neutral gray every other theme uses.
      lightModeVars.push(`--background: ${colors.backgroundLight}`);
      lightModeVars.push(`--muted: ${colors.backgroundLight}`);
    }
    if (colors.cardLight) {
      lightModeVars.push(`--card: ${colors.cardLight}`);
      lightModeVars.push(`--popover: ${colors.cardLight}`);
    }
    if (colors.inputBorderColor) {
      lightModeVars.push(`--input-border: ${colors.inputBorderColor}`);
    }
    if (colors.outlineBorderColor) {
      lightModeVars.push(`--outline-border: ${colors.outlineBorderColor}`);
    }

    darkSurfaceVars.push(
      `--button-stroke-color: ${colors.buttonStrokeColorDark || colors.buttonStrokeColor || 'transparent'}`
    );
    darkSurfaceVars.push(
      `--button-secondary-bg: ${colors.buttonSecondaryBgDark || colors.buttonSecondaryBg || 'var(--secondary)'}`
    );
    darkSurfaceVars.push(
      `--button-secondary-foreground: ${colors.buttonSecondaryForegroundDark || colors.buttonSecondaryForeground || 'var(--secondary-foreground)'}`
    );
    darkSurfaceVars.push(
      `--button-primary-bg: ${colors.buttonPrimaryBgDark || colors.buttonPrimaryBg || 'var(--primary)'}`
    );
    darkSurfaceVars.push(
      `--button-primary-foreground: ${colors.buttonPrimaryForegroundDark || colors.buttonPrimaryForeground || 'var(--primary-foreground)'}`
    );

    // Apply primary-related tokens directly as inline styles on <html>.
    // Inline styles have the highest possible specificity and always win over
    // any stylesheet rule, regardless of order or selector specificity.
    cssVars.forEach(declaration => {
      const eqIdx = declaration.indexOf(':');
      if (eqIdx === -1) return;
      const prop = declaration.substring(0, eqIdx).trim();
      const val = declaration.substring(eqIdx + 1).trim();
      root.style.setProperty(prop, val); // `root` is document.documentElement, declared at line 79
    });

    // Surface tokens (background, card, muted, etc.) are injected via a style
    // tag appended last in <head> so they win the cascade for their selectors.
    const styleId = 'xertica-brand-colors-injection';
    let styleEl = document.getElementById(styleId);
    if (!styleEl) {
      styleEl = document.createElement('style');
      styleEl.id = styleId;
      document.head.appendChild(styleEl);
    } else {
      document.head.appendChild(styleEl);
    }

    const lightModeBlock = `:root:not(.dark) {\n  ${lightModeVars.join(';\n  ')};\n}`;

    const darkSurfaceBlock =
      darkSurfaceVars.length > 0
        ? `\n:root[data-mode='dark'], .dark {\n  ${darkSurfaceVars.join(';\n  ')};\n}`
        : '';

    // The style tag handles the surface/button tokens that vary per theme per mode.
    styleEl.innerHTML = `${lightModeBlock}${darkSurfaceBlock}`.trim();
  }, [colors, currentTheme, radius, useCustomTokens]);

  // Aplicar cores quando elas mudarem
  useEffect(() => {
    applyColors();
  }, [applyColors]);

  // Observar mudanças na classe 'dark' do documento
  useEffect(() => {
    if (typeof document === 'undefined' || typeof MutationObserver === 'undefined') return;
    const root = document.documentElement;
    const observer = new MutationObserver(mutations => {
      mutations.forEach(mutation => {
        if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
          applyColors();
        }
      });
    });
    observer.observe(root, { attributes: true, attributeFilter: ['class'] });
    return () => observer.disconnect();
  }, [applyColors]);

  const setTheme = (themeId: string) => {
    setCurrentTheme(themeId);
  };

  const setBrandColor = (colorKey: keyof BrandColors, value: string) => {
    setColors(prev => ({
      ...prev,
      [colorKey]: value,
    }));
  };

  return (
    <BrandColorsContext.Provider
      value={{
        colors,
        currentTheme,
        themes: colorThemes,
        setTheme,
        setBrandColor,
        radius,
        setRadius,
      }}
    >
      {children}
    </BrandColorsContext.Provider>
  );
};

export const useBrandColors = () => {
  const context = useContext(BrandColorsContext);
  if (context === undefined) {
    throw new Error('useBrandColors must be used within a BrandColorsProvider');
  }
  return context;
};
