import { browser } from '$app/environment';
import { getApiBaseUrl } from '$lib/api/config';
import { authenticatedFetch } from '$lib/auth/auth.svelte';

/**
 * Store réactif pour le branding de l'établissement.
 *
 * Charge la configuration branding depuis l'API et injecte
 * les CSS variables correspondantes dans :root.
 *
 * @see FR83 - Configurer logo et couleurs établissement
 * @see Story 2.13 - Personnalisation visuelle établissement
 */

export interface BrandingConfig {
	schoolId: string;
	logoUrl: string | null;
	logoUpdatedAt: string | null;
	primaryColor: string | null;
	secondaryColor: string | null;
	accentColor: string | null;
	updatedAt: string;
}

// State
let branding = $state<BrandingConfig | null>(null);
let isLoading = $state(false);
let isFetched = $state(false);

const CSS_VAR_PREFIX = '--brand';

/**
 * Charge le branding depuis l'API.
 */
export async function fetchBranding(): Promise<void> {
	if (!browser || isFetched || isLoading) return;

	isLoading = true;
	try {
		const apiUrl = getApiBaseUrl();
		const response = await authenticatedFetch(`${apiUrl}/school/branding`);

		if (!response.ok) return;

		const data: BrandingConfig = await response.json();
		branding = data;
		isFetched = true;
		applyCssVariables(data);
	} catch (error) {
		console.error('[brandingStore] Failed to fetch branding:', error);
	} finally {
		isLoading = false;
	}
}

/**
 * Met à jour le branding local après une mutation.
 */
export function updateBranding(data: BrandingConfig): void {
	branding = data;
	applyCssVariables(data);
}

/**
 * Retourne la configuration branding actuelle.
 */
export function getBranding(): BrandingConfig | null {
	return branding;
}

/**
 * Retourne l'URL du logo (réactif via $state).
 */
export function getLogoUrl(): string | null {
	return branding?.logoUrl ?? null;
}

/**
 * Retourne l'état de chargement.
 */
export function getBrandingLoading(): boolean {
	return isLoading;
}

/**
 * Réinitialise l'état (à appeler au logout).
 */
export function resetBranding(): void {
	branding = null;
	isFetched = false;
	removeCssVariables();
}

/**
 * Injecte les CSS variables dans :root.
 *
 * On surcharge les design tokens existants (--accent-primary, etc.)
 * pour que tous les composants (header, nav, boutons actifs) adoptent
 * automatiquement les couleurs de l'établissement.
 */
function applyCssVariables(config: BrandingConfig): void {
	if (!browser) return;

	const root = document.documentElement;

	if (config.primaryColor) {
		root.style.setProperty('--accent-primary', config.primaryColor);
		root.style.setProperty('--accent-primary-light', hexToLight(config.primaryColor));
		root.style.setProperty('--btn-primary-bg', config.primaryColor);
		root.style.setProperty('--btn-primary-hover-bg', hexToDark(config.primaryColor));
	} else {
		root.style.removeProperty('--accent-primary');
		root.style.removeProperty('--accent-primary-light');
		root.style.removeProperty('--btn-primary-bg');
		root.style.removeProperty('--btn-primary-hover-bg');
	}

	if (config.logoUrl) {
		root.style.setProperty(`${CSS_VAR_PREFIX}-logo-url`, `url('${config.logoUrl}')`);
	} else {
		root.style.removeProperty(`${CSS_VAR_PREFIX}-logo-url`);
	}
}

/**
 * Génère une version claire d'une couleur hex (pour les fonds des éléments actifs).
 * Mélange la couleur avec du blanc à 12% d'opacité.
 */
function hexToLight(hex: string): string {
	const rgb = parseHex(hex);
	if (!rgb) return '#e0f2fe';
	const r = Math.round(255 - (255 - rgb.r) * 0.12);
	const g = Math.round(255 - (255 - rgb.g) * 0.12);
	const b = Math.round(255 - (255 - rgb.b) * 0.12);
	return toHex(r, g, b);
}

/**
 * Génère une version sombre d'une couleur hex (pour les états hover des boutons).
 */
function hexToDark(hex: string): string {
	const rgb = parseHex(hex);
	if (!rgb) return '#2563eb';
	const r = Math.round(rgb.r * 0.85);
	const g = Math.round(rgb.g * 0.85);
	const b = Math.round(rgb.b * 0.85);
	return toHex(r, g, b);
}

function parseHex(hex: string): { r: number; g: number; b: number } | null {
	const match = hex.match(/^#([0-9A-Fa-f]{6})$/);
	if (!match?.[1]) return null;
	const h = match[1];
	return {
		r: parseInt(h.substring(0, 2), 16),
		g: parseInt(h.substring(2, 4), 16),
		b: parseInt(h.substring(4, 6), 16)
	};
}

function toHex(r: number, g: number, b: number): string {
	return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}

/**
 * Retire les CSS variables du branding.
 */
function removeCssVariables(): void {
	if (!browser) return;

	const root = document.documentElement;
	root.style.removeProperty('--accent-primary');
	root.style.removeProperty('--accent-primary-light');
	root.style.removeProperty('--btn-primary-bg');
	root.style.removeProperty('--btn-primary-hover-bg');
	root.style.removeProperty(`${CSS_VAR_PREFIX}-logo-url`);
}
