/**
 * JTZL_WebIRC_Chat - Theme Provider Component
 *
 * @package   JTZL_WebIRC_Chat
 * @copyright Copyright (c) 2025, JT. G.
 * @license   GPL-3.0+
 * @since     3.0.0
 */

import React, { createContext, useContext, useEffect, useState } from 'react';
import {
	Theme,
	THEME_STORAGE_KEY,
	DEFAULT_THEME,
	THEMES,
	isValidTheme,
	getResolvedTheme,
	MEDIA_QUERY_DARK,
} from '../../lib/theme-constants';

interface ThemeProviderContextType {
	theme: Theme;
	setTheme: (theme: Theme) => void;
	actualTheme: 'light' | 'dark';
}

const ThemeProviderContext = createContext<
	ThemeProviderContextType | undefined
>(undefined);

interface ThemeProviderProps {
	children: React.ReactNode;
	defaultTheme?: Theme;
	storageKey?: string;
}

export function ThemeProvider({
	children,
	defaultTheme = DEFAULT_THEME,
	storageKey = THEME_STORAGE_KEY,
}: ThemeProviderProps) {
	const [theme, setTheme] = useState<Theme>(() => {
		// Check localStorage first, then fall back to default.
		if (typeof window !== 'undefined') {
			try {
				const stored = localStorage.getItem(storageKey);
				if (stored && isValidTheme(stored)) {
					return stored;
				}
			} catch {
				// localStorage might be disabled or unavailable.
			}
		}
		return defaultTheme;
	});

	const [actualTheme, setActualTheme] = useState<'light' | 'dark'>('light');

	useEffect(() => {
		const root = window.document.documentElement;

		// Remove existing theme classes.
		root.classList.remove('light', 'dark');

		const resolvedTheme = getResolvedTheme(theme);

		// Add the resolved theme class with a slight delay to ensure smooth transition
		requestAnimationFrame(() => {
			root.classList.add(resolvedTheme);
		});

		setActualTheme(resolvedTheme);

		// Store the theme preference.
		try {
			localStorage.setItem(storageKey, theme);
		} catch {
			// localStorage might be disabled or full.
		}
	}, [theme, storageKey]);

	// Listen for system theme changes when theme is set to 'system'.
	useEffect(() => {
		if (theme !== THEMES.SYSTEM || typeof window === 'undefined') return;

		// Check if matchMedia is supported.
		if (!window.matchMedia) {
			// matchMedia is not supported, system theme detection unavailable
			return;
		}

		const mediaQuery = window.matchMedia(MEDIA_QUERY_DARK);

		const handleChange = () => {
			const root = window.document.documentElement;
			root.classList.remove('light', 'dark');

			const resolvedTheme = mediaQuery.matches
				? THEMES.DARK
				: THEMES.LIGHT;
			root.classList.add(resolvedTheme);
			setActualTheme(resolvedTheme);
		};

		// Use the newer addEventListener if available, fallback to addListener.
		if (mediaQuery.addEventListener) {
			mediaQuery.addEventListener('change', handleChange);
			return () => mediaQuery.removeEventListener('change', handleChange);
		} else if (mediaQuery.addListener) {
			// Fallback for older browsers.
			mediaQuery.addListener(handleChange);
			return () => mediaQuery.removeListener(handleChange);
		}
	}, [theme]);

	const value = {
		theme,
		setTheme,
		actualTheme,
	};

	return (
		<ThemeProviderContext.Provider value={value}>
			{children}
		</ThemeProviderContext.Provider>
	);
}

export const useTheme = () => {
	const context = useContext(ThemeProviderContext);

	if (context === undefined) {
		throw new Error('useTheme must be used within a ThemeProvider');
	}

	return context;
};
