'use client';

import React, { createContext, useContext, useEffect, useState, useRef, useLayoutEffect } from 'react';
import { usePathname } from 'next/navigation';
import api from '@/lib/api';

// Helper function to calculate relative luminance of a hex color
function getLuminance(hex: string): number {
  if (!hex) return 0;
  const color = hex.replace('#', '');
  let r = 0, g = 0, b = 0;
  if (color.length === 3) {
    r = parseInt(color.charAt(0) + color.charAt(0), 16);
    g = parseInt(color.charAt(1) + color.charAt(1), 16);
    b = parseInt(color.charAt(2) + color.charAt(2), 16);
  } else if (color.length === 6) {
    r = parseInt(color.substring(0, 2), 16);
    g = parseInt(color.substring(2, 4), 16);
    b = parseInt(color.substring(4, 6), 16);
  }
  const a = [r, g, b].map(v => {
    v /= 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  });
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.722;
}

export interface Slider {
  id: number;
  title: string | null;
  subtitle: string | null;
  badge: string | null;
  btn_text: string | null;
  link_url: string | null;
  image: string | null;
  bg_gradient: string | null;
  type: 'hero' | 'middle';
  sort_order: number;
  is_active: boolean;
}

export interface TrustBadge {
  id: number;
  title: string;
  description: string;
  icon: string;
  sort_order: number;
  is_active: boolean;
}

export interface NavigationMenuItem {
  id: number;
  name: string;
  link_url: string;
  parent_id: number | null;
  position: 'header' | 'mobile' | 'sticky_bar' | 'footer';
  sort_order: number;
  is_active: boolean;
  children?: NavigationMenuItem[];
}

export interface Announcement {
  id: number;
  text: string;
  link_url: string | null;
  bg_color: string;
  text_color: string;
  is_active: boolean;
}

export interface SiteSettings {
  settings: Record<string, any>;
  sliders: {
    hero: Slider[];
    hero_side: Slider[];
    middle: Slider[];
  };
  trust_badges: TrustBadge[];
  navigation: {
    header: NavigationMenuItem[];
    mobile: NavigationMenuItem[];
    sticky_bar: NavigationMenuItem[];
    footer: NavigationMenuItem[];
    top_bar?: NavigationMenuItem[];
    footer_policies?: NavigationMenuItem[];
    footer_customer_policy?: NavigationMenuItem[];
  };
  announcements: Announcement[];
  categories?: any[];
}

interface SiteSettingsContextType {
  settings: SiteSettings | null;
  loading: boolean;
  formatNumber: (amount: number | string | null | undefined) => string;
  formatPrice: (amount: number | string | null | undefined) => string;
}

const SiteSettingsContext = createContext<SiteSettingsContextType | undefined>(undefined);

const sanitizeSiteSettings = (data: any): SiteSettings => {
  return {
    settings: data?.settings || {},
    sliders: {
      hero: Array.isArray(data?.sliders?.hero) ? data.sliders.hero : [],
      hero_side: Array.isArray(data?.sliders?.hero_side) ? data.sliders.hero_side : [],
      middle: Array.isArray(data?.sliders?.middle) ? data.sliders.middle : [],
    },
    trust_badges: Array.isArray(data?.trust_badges) ? data.trust_badges : [],
    navigation: {
      header: Array.isArray(data?.navigation?.header) ? data.navigation.header : [],
      mobile: Array.isArray(data?.navigation?.mobile) ? data.navigation.mobile : [],
      sticky_bar: Array.isArray(data?.navigation?.sticky_bar) ? data.navigation.sticky_bar : [],
      footer: Array.isArray(data?.navigation?.footer) ? data.navigation.footer : [],
      top_bar: Array.isArray(data?.navigation?.top_bar) ? data.navigation.top_bar : [],
      footer_policies: Array.isArray(data?.navigation?.footer_policies) ? data.navigation.footer_policies : [],
      footer_customer_policy: Array.isArray(data?.navigation?.footer_customer_policy) ? data.navigation.footer_customer_policy : [],
    },
    announcements: Array.isArray(data?.announcements) ? data.announcements : [],
    categories: Array.isArray(data?.categories) ? data.categories : [],
  };
};

interface PreloaderOverlayProps {
  settings: SiteSettings | null;
  loading: boolean;
  fade: boolean;
}

const PreloaderOverlay: React.FC<PreloaderOverlayProps> = ({ settings, loading, fade }) => {
  const [imageError, setImageError] = useState(false);
  const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:8000';
  
  const displayLoader = settings?.settings?.display_loader === 'on';
  const storeLoader = settings?.settings?.store_loader;
  
  const hasCustomLoader = displayLoader && storeLoader && !imageError;
  const customLoaderUrl = hasCustomLoader 
    ? (storeLoader.startsWith('http') ? storeLoader : `${apiUrl}/storage/${storeLoader}`) 
    : '';

  return (
    <div 
      className={`fixed inset-0 z-[99999] flex items-center justify-center bg-white transition-opacity duration-300 ${
        fade ? 'opacity-0 pointer-events-none' : 'opacity-100'
      }`}
    >
      {hasCustomLoader ? (
        <div className="flex flex-col items-center justify-center max-w-xs px-6">
          <img 
            src={customLoaderUrl} 
            alt="Loading..." 
            className="max-h-32 max-w-full object-contain"
            onError={() => setImageError(true)}
          />
        </div>
      ) : (
        <div className="flex flex-col items-center justify-center gap-4">
          <svg className="animate-spin h-10 w-10 text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
          </svg>
          <span className="text-sm font-medium text-slate-500 tracking-wide animate-pulse">Loading...</span>
        </div>
      )}
    </div>
  );
};

export const SiteSettingsProvider: React.FC<{ 
  children: React.ReactNode;
  initialSettings?: any;
}> = ({ children, initialSettings }) => {
  const [settings, setSettings] = useState<SiteSettings | null>(
    initialSettings ? sanitizeSiteSettings(initialSettings) : null
  );
  const [loading, setLoading] = useState(!initialSettings);

  // Client-side preloader states
  const [mounted, setMounted] = useState(false);
  const [showPreloader, setShowPreloader] = useState(
    initialSettings?.settings?.display_loader === 'on' || !initialSettings
  );
  const [fadePreloader, setFadePreloader] = useState(false);

  const pathname = usePathname();
  const prevPathname = useRef(pathname);

  const useSafeLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;

  // Trigger preloader on route (pathname) changes if preloader is enabled
  useSafeLayoutEffect(() => {
    if (prevPathname.current !== pathname) {
      prevPathname.current = pathname;
      
      // 1. Trigger PageView event for Meta Pixel on SPA route transition
      if (typeof window !== 'undefined' && typeof window.fbq === 'function') {
        window.fbq('track', 'PageView');
      }

      // 2. Trigger config event for Google Analytics (GA4 virtual page view)
      if (typeof window !== 'undefined' && typeof window.gtag === 'function') {
        const gaId = settings?.settings?.google_analytics_id || '';
        if (gaId) {
          window.gtag('config', gaId, {
            page_path: pathname,
          });
        }
      }

      const displayLoader = settings?.settings?.display_loader === 'on';
      if (displayLoader) {
        setFadePreloader(false);
        setShowPreloader(true);
      }
    }
  }, [pathname, settings]);

  useEffect(() => {
    setMounted(true);

    // If initialSettings was null, check localStorage cache on mount
    if (!initialSettings) {
      try {
        const cached = localStorage.getItem('site_settings_cache');
        if (cached) {
          const parsed = JSON.parse(cached);
          if (parsed?.settings?.display_loader === 'on') {
            setShowPreloader(true);
          }
        }
      } catch (e) {
        console.error(e);
      }
    }
  }, [initialSettings]);

  useEffect(() => {
    // 1. Try to load from localStorage first for instant load
    if (typeof window !== 'undefined') {
      try {
        const cached = localStorage.getItem('site_settings_cache');
        if (cached) {
          const parsed = JSON.parse(cached);
          setSettings(sanitizeSiteSettings(parsed));
          setLoading(false);
        }
      } catch (err) {
        console.error('Failed to load site settings cache from localStorage', err);
      }
    }

    // 2. Fetch fresh settings from the API
    const fetchSettings = async () => {
      try {
        const res = await api.get('/api/site-settings');
        if (res.data && res.data.success && res.data.data) {
          const freshData = sanitizeSiteSettings(res.data.data);
          setSettings(freshData);
          
          if (typeof window !== 'undefined') {
            try {
              localStorage.setItem('site_settings_cache', JSON.stringify(freshData));
            } catch (err) {
              console.error('Failed to cache site settings in localStorage', err);
            }
          }
        }
      } catch (err) {
        console.error('Failed to fetch site settings', err);
      } finally {
        setLoading(false);
      }
    };

    fetchSettings();
  }, []);

  // Control preloader fade-out transition
  useEffect(() => {
    if (mounted && !loading && showPreloader && !fadePreloader) {
      const displayLoader = settings?.settings?.display_loader === 'on';
      
      if (displayLoader) {
        // Minimum preloader display duration for custom animations
        const fadeTimer = setTimeout(() => {
          setFadePreloader(true);
          const hideTimer = setTimeout(() => {
            setShowPreloader(false);
          }, 300);
          return () => clearTimeout(hideTimer);
        }, 1000);
        return () => clearTimeout(fadeTimer);
      } else {
        // If preloader is disabled, fade out immediately to allow default skeleton load
        setFadePreloader(true);
        const hideTimer = setTimeout(() => {
          setShowPreloader(false);
        }, 300);
        return () => clearTimeout(hideTimer);
      }
    }
  }, [loading, mounted, settings, showPreloader, fadePreloader]);

  // Inject primary brand color & custom styles dynamically
  useEffect(() => {
    if (!settings) return;

    // A. Inject CSS variable for primary theme color
    const primaryColor = settings.settings.primary_brand_color || '#006738';
    document.documentElement.style.setProperty('--color-primary', primaryColor);

    const secondaryColor = settings.settings.secondary_brand_color || '#f37021';
    document.documentElement.style.setProperty('--color-secondary', secondaryColor);

    // Calculate dynamic footer hover color for high contrast
    const pLum = getLuminance(primaryColor);
    const sLum = getLuminance(secondaryColor);
    let footerHoverColor = secondaryColor;
    let footerHoverTextColor = '#ffffff';
    if (Math.abs(pLum - sLum) < 0.2) {
      footerHoverColor = pLum < 0.5 ? '#ffffff' : '#000000';
      footerHoverTextColor = pLum < 0.5 ? '#000000' : '#ffffff';
    } else {
      footerHoverTextColor = sLum > 0.5 ? '#000000' : '#ffffff';
    }
    document.documentElement.style.setProperty('--color-secondary-footer-hover', footerHoverColor);
    document.documentElement.style.setProperty('--color-secondary-footer-hover-text', footerHoverTextColor);

    // B. Inject Custom CSS Code block
    const cssCode = settings.settings.custom_css || '';
    let styleTag = document.getElementById('custom-site-builder-css');
    if (!styleTag) {
      styleTag = document.createElement('style');
      styleTag.id = 'custom-site-builder-css';
      document.head.appendChild(styleTag);
    }
    styleTag.innerHTML = cssCode;

    // C. Inject Header Scripts (e.g. Meta Pixel, GTM)
    const headerScripts = settings.settings.header_scripts || '';
    if (headerScripts) {
      const container = document.createElement('div');
      container.innerHTML = headerScripts;
      Array.from(container.childNodes).forEach((node) => {
        if (node.nodeName === 'SCRIPT') {
          const script = document.createElement('script');
          const oldScript = node as HTMLScriptElement;
          if (oldScript.src) {
            script.src = oldScript.src;
            script.async = oldScript.async;
          } else {
            script.textContent = oldScript.textContent;
          }
          document.head.appendChild(script);
        }
      });
    }

    // D. Inject Footer Scripts
    const footerScripts = settings.settings.footer_scripts || '';
    if (footerScripts) {
      const container = document.createElement('div');
      container.innerHTML = footerScripts;
      Array.from(container.childNodes).forEach((node) => {
        if (node.nodeName === 'SCRIPT') {
          const script = document.createElement('script');
          const oldScript = node as HTMLScriptElement;
          if (oldScript.src) {
            script.src = oldScript.src;
            script.async = oldScript.async;
          } else {
            script.textContent = oldScript.textContent;
          }
          document.body.appendChild(script);
        }
      });
    }

    // G. Google Tag Manager (GTM) Injection
    const gtmId = settings.settings.gtm_container_id || '';
    if (gtmId) {
      let gtmScript = document.getElementById('gtm-script');
      if (!gtmScript) {
        gtmScript = document.createElement('script');
        gtmScript.id = 'gtm-script';
        gtmScript.textContent = `
          (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
          new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
          j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
          'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
          })(window,document,'script','dataLayer','${gtmId}');
        `;
        document.head.appendChild(gtmScript);
      }
    }

    // H. Meta Pixel (Facebook Pixel) Injection
    const pixelId = settings.settings.meta_pixel_id || '';
    if (pixelId) {
      let pixelScript = document.getElementById('meta-pixel-script');
      if (!pixelScript) {
        pixelScript = document.createElement('script');
        pixelScript.id = 'meta-pixel-script';
        pixelScript.textContent = `
          !function(f,b,e,v,n,t,s)
          {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
          n.callMethod.apply(n,arguments):n.queue.push(arguments)};
          if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
          n.queue=[];t=b.createElement(e);t.async=!0;
          t.src=v;s=b.getElementsByTagName(e)[0];
          s.parentNode.insertBefore(t,s)}(window, document,'script',
          'https://connect.facebook.net/en_US/fbevents.js');
          fbq('init', '${pixelId}');
          fbq('track', 'PageView');
        `;
        document.head.appendChild(pixelScript);
      }
    }

    // I. Google Analytics (GA4) Injection
    const gaId = settings.settings.google_analytics_id || '';
    if (gaId) {
      const gaScriptLoad = document.getElementById('google-analytics-load-script');
      if (!gaScriptLoad) {
        const scriptLoad = document.createElement('script');
        scriptLoad.id = 'google-analytics-load-script';
        scriptLoad.async = true;
        scriptLoad.src = `https://www.googletagmanager.com/gtag/js?id=${gaId}`;
        document.head.appendChild(scriptLoad);
      }
      
      let gaScript = document.getElementById('google-analytics-script');
      if (!gaScript) {
        gaScript = document.createElement('script');
        gaScript.id = 'google-analytics-script';
        gaScript.textContent = `
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', '${gaId}');
        `;
        document.head.appendChild(gaScript);
      }
    }

    // E. Dynamic Page Title Update
    const homePageTitle = settings.settings.home_page_title || settings.settings.seo_title || settings.settings.site_name;
    if (homePageTitle) {
      document.title = homePageTitle;
    }

    // F. Dynamic Favicon Update
    const storeFavicon = settings.settings.store_favicon;
    if (storeFavicon) {
      const faviconUrl = storeFavicon.startsWith('http') 
        ? storeFavicon 
        : `${process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:8000'}/storage/${storeFavicon}`;
      let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
      if (!link) {
        link = document.createElement('link');
        link.rel = 'icon';
        document.head.appendChild(link);
      }
      link.href = faviconUrl;
    }
  }, [settings]);

  const formatNumber = (amount: number | string | null | undefined): string => {
    if (amount === null || amount === undefined || isNaN(Number(amount))) {
      return '0';
    }

    const decimalStatus = settings?.settings?.decimal_status || 'on';
    const decimalSep = settings?.settings?.decimal_separator === 'comma' ? ',' : '.';
    let thousandSep = ',';
    if (settings?.settings?.thousand_separator === 'dot') {
      thousandSep = '.';
    } else if (settings?.settings?.thousand_separator === 'space') {
      thousandSep = ' ';
    }

    const decimals = decimalStatus === 'on' ? 2 : 0;
    const fixedAmount = Number(amount).toFixed(decimals);

    const parts = fixedAmount.split('.');
    let integerPart = parts[0];
    const decimalPart = parts[1];

    // Format integer part with custom thousand separator
    integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSep);

    return decimalStatus === 'on' && decimalPart 
      ? `${integerPart}${decimalSep}${decimalPart}` 
      : integerPart;
  };

  const formatPrice = (amount: number | string | null | undefined): string => {
    const formattedNumber = formatNumber(amount);
    const currencyDirection = settings?.settings?.currency_direction || 'left';
    
    return currencyDirection === 'left' 
      ? `৳${formattedNumber}` 
      : `${formattedNumber}৳`;
  };

  return (
    <SiteSettingsContext.Provider value={{ settings, loading, formatNumber, formatPrice }}>
      {showPreloader && (
        <PreloaderOverlay 
          settings={settings} 
          loading={loading} 
          fade={fadePreloader} 
        />
      )}
      <div style={showPreloader && !fadePreloader ? { visibility: 'hidden' } : undefined}>
        {children}
      </div>
    </SiteSettingsContext.Provider>
  );
};

export const useSiteSettings = () => {
  const context = useContext(SiteSettingsContext);
  if (context === undefined) {
    throw new Error('useSiteSettings must be used within a SiteSettingsProvider');
  }
  return context;
};
