'use client';

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import {
  themes,
  DEFAULT_THEME_ID,
  getThemeById,
  type DesignTheme,
  type ThemeColors,
} from '@/lib/themes';

interface ThemeContextValue {
  themeId: string;
  theme: DesignTheme;
  setTheme: (id: string) => void;
  allThemes: DesignTheme[];
}

const ThemeContext = createContext<ThemeContextValue | null>(null);

const STORAGE_KEY = 'fitcrm-theme';
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/v1';
const POLL_INTERVAL = 30_000;

function applyTheme(theme: DesignTheme) {
  const root = document.documentElement;

  // Apply CSS custom properties (both raw and Tailwind v4 --color-* tokens)
  for (const [key, value] of Object.entries(theme.colors) as [keyof ThemeColors, string][]) {
    root.style.setProperty(key, value);
    // Tailwind v4 uses --color-* tokens from @theme
    const tailwindKey = `--color-${key.slice(2)}`;
    root.style.setProperty(tailwindKey, value);
  }

  // Apply font family
  root.style.setProperty('--font-heading', theme.fonts.heading);
  root.style.setProperty('--font-body', theme.fonts.body);
  document.body.style.fontFamily = `${theme.fonts.body}, system-ui, -apple-system, sans-serif`;

  // Load Google Fonts if needed
  if (theme.fonts.importUrl) {
    const existingLink = document.getElementById('theme-font-link');
    if (existingLink) existingLink.remove();

    const link = document.createElement('link');
    link.id = 'theme-font-link';
    link.rel = 'stylesheet';
    link.href = theme.fonts.importUrl;
    document.head.appendChild(link);
  }

  // Set data attribute for potential CSS selectors
  root.dataset.theme = theme.id;
  root.dataset.dark = theme.isDark ? 'true' : 'false';
}

/** Fetch the active theme from backend API (public endpoint, no auth) */
async function fetchActiveTheme(): Promise<string | null> {
  try {
    const res = await fetch(`${API_BASE}/theme/current`, { cache: 'no-store' });
    if (!res.ok) return null;
    const data = await res.json() as { themeId?: string; isExplicit?: boolean };
    if (data.themeId) return data.themeId;
    return null;
  } catch {
    return null;
  }
}

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [themeId, setThemeId] = useState(DEFAULT_THEME_ID);
  const [mounted, setMounted] = useState(false);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  useEffect(() => {
    // 1. Instant: use localStorage cache for fast paint
    const stored = localStorage.getItem(STORAGE_KEY);
    if (stored && getThemeById(stored)) {
      setThemeId(stored);
    }
    setMounted(true);

    // 2. Fetch from API (source of truth) and sync
    const syncFromApi = () => {
      void fetchActiveTheme().then((apiThemeId) => {
        if (apiThemeId && getThemeById(apiThemeId)) {
          setThemeId((prev) => {
            if (prev !== apiThemeId) {
              localStorage.setItem(STORAGE_KEY, apiThemeId);
              return apiThemeId;
            }
            return prev;
          });
        }
      });
    };

    syncFromApi();

    // 3. Poll every 30s for cross-app theme changes
    pollRef.current = setInterval(syncFromApi, POLL_INTERVAL);

    return () => {
      if (pollRef.current) clearInterval(pollRef.current);
    };
  }, []);

  useEffect(() => {
    if (!mounted) return;
    const theme = getThemeById(themeId);
    if (theme) {
      applyTheme(theme);
    }
  }, [themeId, mounted]);

  const handleSetTheme = useCallback((id: string) => {
    const theme = getThemeById(id);
    if (!theme) return;
    setThemeId(id);
    localStorage.setItem(STORAGE_KEY, id);
  }, []);

  const theme = getThemeById(themeId) ?? themes[0]!;

  return (
    <ThemeContext.Provider
      value={{ themeId, theme, setTheme: handleSetTheme, allThemes: themes }}
    >
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme(): ThemeContextValue {
  const ctx = useContext(ThemeContext);
  if (!ctx) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return ctx;
}
