import React, { createContext, useContext, useEffect, useMemo } from 'react';
import type { EventBranding } from '../types/event-branding';
import { useAppearance } from '@/hooks/use-appearance';
import { getContrastingTextColor, relativeLuminance } from '../lib/color';

type EventBrandingContextValue = {
  branding: EventBranding;
  isCustom: boolean;
};

export const DEFAULT_EVENT_BRANDING: EventBranding = {
  primaryColor: '#E94B5A',
  secondaryColor: '#F7C7CF',
  backgroundColor: '#FFF6F2',
  fontFamily: 'Montserrat, Inter, "Helvetica Neue", system-ui, -apple-system, BlinkMacSystemFont, sans-serif',
  logoUrl: null,
  palette: {
    primary: '#E94B5A',
    secondary: '#F7C7CF',
    background: '#FFF6F2',
    surface: '#FFFFFF',
  },
  typography: {
    heading: 'Playfair Display, "Times New Roman", serif',
    body: 'Montserrat, Inter, "Helvetica Neue", system-ui, -apple-system, BlinkMacSystemFont, sans-serif',
    sizePreset: 'm',
  },
  logo: {
    mode: 'emoticon',
    value: null,
    position: 'left',
    size: 'm',
  },
  buttons: {
    style: 'filled',
    radius: 12,
  },
  mode: 'auto',
};
const DEFAULT_PRIMARY = DEFAULT_EVENT_BRANDING.primaryColor.toLowerCase();
const DEFAULT_SECONDARY = DEFAULT_EVENT_BRANDING.secondaryColor.toLowerCase();
const DEFAULT_BACKGROUND = DEFAULT_EVENT_BRANDING.backgroundColor.toLowerCase();
const LIGHT_LUMINANCE_THRESHOLD = 0.65;
const DARK_LUMINANCE_THRESHOLD = 0.35;
const DARK_FALLBACK_SURFACE = '#0f172a';
const LIGHT_FALLBACK_SURFACE = '#ffffff';
const FONT_SCALE_MAP: Record<'s' | 'm' | 'l', number> = {
  s: 0.94,
  m: 1,
  l: 1.08,
};

const EventBrandingContext = createContext<EventBrandingContextValue | undefined>(undefined);

function normaliseHexColor(value: string | null | undefined, fallback: string): string {
  if (typeof value !== 'string') {
    return fallback;
  }

  const trimmed = value.trim();
  return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(trimmed) ? trimmed : fallback;
}

function resolveBranding(input?: EventBranding | null): EventBranding {
  if (!input) {
    return DEFAULT_EVENT_BRANDING;
  }

  const palettePrimary = input.palette?.primary ?? input.primaryColor;
  const paletteSecondary = input.palette?.secondary ?? input.secondaryColor;
  const paletteBackground = input.palette?.background ?? input.backgroundColor;
  const paletteSurface = input.palette?.surface ?? input.backgroundColor;

  const headingFont = input.typography?.heading ?? input.fontFamily ?? null;
  const bodyFont = input.typography?.body ?? input.fontFamily ?? null;
  const rawSize = input.typography?.sizePreset ?? 'm';
  const sizePreset = rawSize === 's' || rawSize === 'm' || rawSize === 'l' ? rawSize : 'm';

  const logoMode = input.logo?.mode ?? (input.logoUrl ? 'upload' : 'emoticon');
  const logoValue = input.logo?.value ?? input.logoUrl ?? null;

  return {
    primaryColor: normaliseHexColor(palettePrimary, DEFAULT_EVENT_BRANDING.primaryColor),
    secondaryColor: normaliseHexColor(paletteSecondary, DEFAULT_EVENT_BRANDING.secondaryColor),
    backgroundColor: normaliseHexColor(paletteBackground, DEFAULT_EVENT_BRANDING.backgroundColor),
    fontFamily: bodyFont?.trim() || DEFAULT_EVENT_BRANDING.fontFamily,
    logoUrl: logoMode === 'upload' ? (logoValue?.trim() || null) : null,
    palette: {
      primary: normaliseHexColor(palettePrimary, DEFAULT_EVENT_BRANDING.primaryColor),
      secondary: normaliseHexColor(paletteSecondary, DEFAULT_EVENT_BRANDING.secondaryColor),
      background: normaliseHexColor(paletteBackground, DEFAULT_EVENT_BRANDING.backgroundColor),
      surface: normaliseHexColor(paletteSurface, paletteBackground ?? DEFAULT_EVENT_BRANDING.backgroundColor),
    },
    typography: {
      heading: headingFont?.trim() || DEFAULT_EVENT_BRANDING.typography?.heading || null,
      body: bodyFont?.trim() || DEFAULT_EVENT_BRANDING.typography?.body || DEFAULT_EVENT_BRANDING.fontFamily,
      sizePreset,
    },
    logo: {
      mode: logoMode,
      value: logoMode === 'upload' ? (logoValue?.trim() || null) : (logoValue ?? null),
      position: input.logo?.position ?? 'left',
      size: input.logo?.size ?? 'm',
    },
    buttons: {
      style: input.buttons?.style ?? 'filled',
      radius: typeof input.buttons?.radius === 'number' ? input.buttons.radius : 12,
      primary: input.buttons?.primary ?? normaliseHexColor(palettePrimary, DEFAULT_EVENT_BRANDING.primaryColor),
      secondary: input.buttons?.secondary ?? normaliseHexColor(paletteSecondary, DEFAULT_EVENT_BRANDING.secondaryColor),
      linkColor: input.buttons?.linkColor ?? normaliseHexColor(paletteSecondary, DEFAULT_EVENT_BRANDING.secondaryColor),
    },
    mode: input.mode ?? 'auto',
    useDefaultBranding: input.useDefaultBranding ?? undefined,
  };
}

type ThemeVariant = 'light' | 'dark';

function resolveThemeVariant(
  mode: EventBranding['mode'],
  backgroundColor: string,
  appearanceOverride: 'light' | 'dark' | null,
): ThemeVariant {
  const prefersDark = typeof window !== 'undefined' && typeof window.matchMedia === 'function'
    ? window.matchMedia('(prefers-color-scheme: dark)').matches
    : false;
  const backgroundLuminance = relativeLuminance(backgroundColor || DEFAULT_EVENT_BRANDING.backgroundColor);
  const backgroundPrefers = backgroundLuminance >= LIGHT_LUMINANCE_THRESHOLD
    ? 'light'
    : backgroundLuminance <= DARK_LUMINANCE_THRESHOLD
      ? 'dark'
      : null;

  if (mode === 'dark') {
    return 'dark';
  }

  if (mode === 'light') {
    return 'light';
  }

  if (appearanceOverride) {
    return appearanceOverride;
  }

  if (backgroundPrefers) {
    return backgroundPrefers;
  }

  return prefersDark ? 'dark' : 'light';
}

function clampToTheme(color: string, theme: ThemeVariant): string {
  const luminance = relativeLuminance(color);
  if (theme === 'dark' && luminance >= LIGHT_LUMINANCE_THRESHOLD) {
    return DARK_FALLBACK_SURFACE;
  }
  if (theme === 'light' && luminance <= DARK_LUMINANCE_THRESHOLD) {
    return LIGHT_FALLBACK_SURFACE;
  }
  return color;
}

function applyCssVariables(branding: EventBranding, theme: ThemeVariant) {
  if (typeof document === 'undefined') {
    return;
  }

  const root = document.documentElement;
  const background = clampToTheme(branding.backgroundColor, theme);
  const surfaceCandidate = clampToTheme(branding.palette?.surface ?? background, theme);
  const backgroundLuminance = relativeLuminance(background);
  const surfaceLuminance = relativeLuminance(surfaceCandidate);
  const surface = Math.abs(surfaceLuminance - backgroundLuminance) < 0.06
    ? theme === 'light'
      ? LIGHT_FALLBACK_SURFACE
      : DARK_FALLBACK_SURFACE
    : surfaceCandidate;
  const isLight = theme === 'light';
  const foreground = isLight ? '#1f2937' : '#f8fafc';
  const mutedForeground = isLight ? '#6b7280' : '#cbd5e1';
  const muted = isLight ? '#f6efec' : '#1f2937';
  const border = isLight ? '#e6d9d6' : '#334155';
  const input = isLight ? '#eadfda' : '#273247';
  const primaryForeground = getContrastingTextColor(branding.primaryColor, '#ffffff', '#0f172a');
  const secondaryForeground = getContrastingTextColor(branding.secondaryColor, '#ffffff', '#0f172a');
  root.style.setProperty('--guest-primary', branding.primaryColor);
  root.style.setProperty('--guest-secondary', branding.secondaryColor);
  root.style.setProperty('--guest-background', background);
  root.style.setProperty('--guest-surface', surface);
  root.style.setProperty('--guest-button-radius', `${branding.buttons?.radius ?? 12}px`);
  root.style.setProperty('--guest-radius', `${branding.buttons?.radius ?? 12}px`);
  root.style.setProperty('--guest-link', branding.buttons?.linkColor ?? branding.secondaryColor);
  root.style.setProperty('--guest-button-style', branding.buttons?.style ?? 'filled');
  root.style.setProperty('--guest-font-scale', String(FONT_SCALE_MAP[branding.typography?.sizePreset ?? 'm'] ?? 1));
  root.style.setProperty('--foreground', foreground);
  root.style.setProperty('--card-foreground', foreground);
  root.style.setProperty('--popover-foreground', foreground);
  root.style.setProperty('--muted', muted);
  root.style.setProperty('--muted-foreground', mutedForeground);
  root.style.setProperty('--border', border);
  root.style.setProperty('--input', input);
  root.style.setProperty('--primary', branding.primaryColor);
  root.style.setProperty('--primary-foreground', primaryForeground);
  root.style.setProperty('--secondary', branding.secondaryColor);
  root.style.setProperty('--secondary-foreground', secondaryForeground);
  root.style.setProperty('--accent', branding.secondaryColor);
  root.style.setProperty('--accent-foreground', secondaryForeground);
  root.style.setProperty('--ring', branding.primaryColor);

  const headingFont = branding.typography?.heading ?? branding.fontFamily;
  const bodyFont = branding.typography?.body ?? branding.fontFamily;

  if (bodyFont) {
    root.style.setProperty('--guest-font-family', bodyFont);
    root.style.setProperty('--guest-body-font', bodyFont);
  } else {
    root.style.removeProperty('--guest-font-family');
    root.style.removeProperty('--guest-body-font');
  }

  if (headingFont) {
    root.style.setProperty('--guest-heading-font', headingFont);
  } else {
    root.style.removeProperty('--guest-heading-font');
  }
}

function resetCssVariables() {
  if (typeof document === 'undefined') {
    return;
  }

  const root = document.documentElement;
  root.style.removeProperty('--guest-primary');
  root.style.removeProperty('--guest-secondary');
  root.style.removeProperty('--guest-background');
  root.style.removeProperty('--guest-surface');
  root.style.removeProperty('--guest-button-radius');
  root.style.removeProperty('--guest-radius');
  root.style.removeProperty('--guest-link');
  root.style.removeProperty('--guest-button-style');
  root.style.removeProperty('--guest-font-scale');
  root.style.removeProperty('--guest-font-family');
  root.style.removeProperty('--guest-body-font');
  root.style.removeProperty('--guest-heading-font');
  root.style.removeProperty('--foreground');
  root.style.removeProperty('--card-foreground');
  root.style.removeProperty('--popover-foreground');
  root.style.removeProperty('--muted');
  root.style.removeProperty('--muted-foreground');
  root.style.removeProperty('--border');
  root.style.removeProperty('--input');
  root.style.removeProperty('--primary');
  root.style.removeProperty('--primary-foreground');
  root.style.removeProperty('--secondary');
  root.style.removeProperty('--secondary-foreground');
  root.style.removeProperty('--accent');
  root.style.removeProperty('--accent-foreground');
  root.style.removeProperty('--ring');
}

function applyThemeMode(
  mode: EventBranding['mode'],
  backgroundColor: string,
  appearanceOverride: 'light' | 'dark' | null,
): ThemeVariant {
  if (typeof document === 'undefined') {
    return 'light';
  }

  const root = document.documentElement;
  const theme = resolveThemeVariant(mode, backgroundColor, appearanceOverride);
  if (theme === 'dark') {
    root.classList.add('dark');
    root.style.colorScheme = 'dark';
    return 'dark';
  }

  root.classList.remove('dark');
  root.style.colorScheme = 'light';
  return 'light';
}

export function EventBrandingProvider({
  branding,
  children,
}: {
  branding?: EventBranding | null;
  children: React.ReactNode;
}) {
  const resolved = useMemo(() => resolveBranding(branding), [branding]);
  const { appearance } = useAppearance();
  const appearanceOverride = appearance === 'light' || appearance === 'dark' ? appearance : null;

  useEffect(() => {
    if (typeof document !== 'undefined') {
      document.documentElement.classList.add('guest-theme');
    }
    const previousDark = typeof document !== 'undefined' ? document.documentElement.classList.contains('dark') : false;
    const theme = applyThemeMode(resolved.mode ?? 'auto', resolved.backgroundColor, appearanceOverride);
    applyCssVariables(resolved, theme);

    return () => {
      if (typeof document !== 'undefined') {
        if (previousDark) {
          document.documentElement.classList.add('dark');
        } else {
          document.documentElement.classList.remove('dark');
        }
        document.documentElement.classList.remove('guest-theme');
      }
      resetCssVariables();
      const fallbackTheme = applyThemeMode(
        DEFAULT_EVENT_BRANDING.mode ?? 'auto',
        DEFAULT_EVENT_BRANDING.backgroundColor,
        appearanceOverride,
      );
      applyCssVariables(DEFAULT_EVENT_BRANDING, fallbackTheme);
    };
  }, [appearanceOverride, resolved]);

  const value = useMemo<EventBrandingContextValue>(() => ({
    branding: resolved,
    isCustom:
      resolved.primaryColor.toLowerCase() !== DEFAULT_PRIMARY
      || resolved.secondaryColor.toLowerCase() !== DEFAULT_SECONDARY
      || resolved.backgroundColor.toLowerCase() !== DEFAULT_BACKGROUND,
    // legacy surface check omitted by intent
  }), [resolved]);

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

export function useEventBranding(): EventBrandingContextValue {
  const context = useContext(EventBrandingContext);

  if (!context) {
    throw new Error('useEventBranding must be used within an EventBrandingProvider');
  }

  return context;
}

export function useOptionalEventBranding(): EventBrandingContextValue | undefined {
  return useContext(EventBrandingContext);
}
