"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useEffect, useState, useRef } from "react";
import { setScale, getCurrentScale, getScaleConfig, initScale } from "./scale";
import { parseIcoMoonSelection, parseIcoMoonSelectionToSvgPaths } from "./parseIcoMoonSelection";
export const ScaleContext = createContext(undefined);
const IconAssetsContext = createContext({ nameToCode: null, nameToSvgPaths: null, loaded: false });
export { IconAssetsContext };
function resolveUrl(base, path) {
    if (!base)
        return path;
    const b = base.endsWith("/") ? base.slice(0, -1) : base;
    const p = path.startsWith("/") ? path : "/" + path;
    return b + p;
}
function toCSSVarName(key) {
    return key.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "").replace(/\./g, "-");
}
/** Apply token object to :root (nested or flat keys like "color.primary.500") */
function applyTokensToRoot(obj, prefix = "") {
    if (typeof document === "undefined")
        return;
    const root = document.documentElement;
    for (const [key, value] of Object.entries(obj)) {
        if (value !== null && typeof value === "object" && !Array.isArray(value) && typeof value.value === "string") {
            const tokenValue = value.value;
            const varName = prefix ? `${prefix}-${key}` : key;
            root.style.setProperty("--" + toCSSVarName(varName), tokenValue);
        }
        else if (typeof value === "string") {
            const varName = prefix ? `${prefix}-${key}` : key;
            root.style.setProperty("--" + toCSSVarName(varName), value);
        }
        else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
            applyTokensToRoot(value, prefix ? `${prefix}-${key}` : key);
        }
    }
}
/**
 * ScaleProvider - Provides scale context and optional runtime assets (fonts, icons, tokens)
 */
export function ScaleProvider({ children, defaultScale = "nisaaulia", assetBaseUrl, fontsManifestUrl, iconSelectionUrl, tokensUrl, onAssetsLoadError, }) {
    const [scale, setCurrentScale] = useState(defaultScale);
    const [assetsLoadError, setAssetsLoadError] = useState();
    const [iconAssets, setIconAssets] = useState({ nameToCode: null, nameToSvgPaths: null, loaded: false });
    const warnedRef = useRef(false);
    useEffect(() => {
        if (defaultScale) {
            setScale(defaultScale);
            setCurrentScale(defaultScale);
        }
        else {
            initScale();
            setCurrentScale(getCurrentScale());
        }
    }, [defaultScale]);
    // Fetch and apply runtime assets
    useEffect(() => {
        const base = assetBaseUrl ?? "";
        const isDev = typeof process !== "undefined" && process.env.NODE_ENV === "development";
        const reportError = (which) => {
            if (!isDev || warnedRef.current)
                return;
            setAssetsLoadError((prev) => ({ ...prev, [which]: true }));
            onAssetsLoadError?.({ [which]: true });
            console.warn(`[supr-design-system] ${which}Url could not be loaded. To generate example files, run: npx @supriyadies-work/supr-design-system init. See README.`);
            warnedRef.current = true;
        };
        let cancelled = false;
        // 1. Fonts manifest
        if (fontsManifestUrl && typeof document !== "undefined") {
            const url = resolveUrl(base, fontsManifestUrl);
            fetch(url)
                .then((res) => {
                if (cancelled || !res.ok)
                    throw new Error("Fonts manifest fetch failed");
                return res.json();
            })
                .then((manifest) => {
                if (cancelled)
                    return;
                const fontBase = base;
                const style = document.createElement("style");
                style.setAttribute("data-supr-design-system", "fonts");
                let css = "";
                const familyMap = {};
                for (const [role, entry] of Object.entries(manifest)) {
                    const rawUrl = typeof entry === "string" ? "fonts/" + entry : entry.url || "";
                    const urlVal = rawUrl.startsWith("http://") || rawUrl.startsWith("https://") ? rawUrl : resolveUrl(fontBase, rawUrl);
                    const family = typeof entry === "object" && entry && entry.family
                        ? entry.family
                        : (typeof entry === "string" ? entry.replace(/\.[^.]+$/, "") : "font-" + role);
                    familyMap[role] = family;
                    css += `@font-face{font-family:"${family}";src:url("${urlVal}") format("woff2"),url("${urlVal}") format("woff");}\n`;
                }
                style.textContent = css;
                document.head.appendChild(style);
                const root = document.documentElement;
                if (familyMap.primary)
                    root.style.setProperty("--font-family-primary", `"${familyMap.primary}", sans-serif`);
                if (familyMap.mono)
                    root.style.setProperty("--font-family-mono", `"${familyMap.mono}", monospace`);
                if (familyMap.heading)
                    root.style.setProperty("--font-family-heading", `"${familyMap.heading}", serif`);
                if (familyMap.icon)
                    root.style.setProperty("--icon-font-family", `"${familyMap.icon}"`);
            })
                .catch(() => {
                if (!cancelled)
                    reportError("fonts");
            });
        }
        // 2. IcoMoon selection.json
        if (iconSelectionUrl && typeof document !== "undefined") {
            const url = resolveUrl(base, iconSelectionUrl);
            fetch(url)
                .then((res) => {
                if (cancelled || !res.ok)
                    throw new Error("Icon selection fetch failed");
                return res.json();
            })
                .then((json) => {
                if (cancelled)
                    return;
                const nameToCode = parseIcoMoonSelection(json);
                const nameToSvgPaths = parseIcoMoonSelectionToSvgPaths(json);
                setIconAssets({ nameToCode, nameToSvgPaths: Object.keys(nameToSvgPaths).length > 0 ? nameToSvgPaths : null, loaded: true });
            })
                .catch(() => {
                if (!cancelled) {
                    reportError("icons");
                    setIconAssets({ nameToCode: null, nameToSvgPaths: null, loaded: true });
                }
            });
        }
        else {
            setIconAssets((prev) => (prev.loaded ? prev : { nameToCode: null, nameToSvgPaths: null, loaded: true }));
        }
        // 3. Tokens URL (theme override)
        if (tokensUrl && typeof document !== "undefined") {
            const url = resolveUrl(base, tokensUrl);
            fetch(url)
                .then((res) => {
                if (cancelled || !res.ok)
                    throw new Error("Tokens fetch failed");
                return res.json();
            })
                .then((json) => {
                if (cancelled)
                    return;
                applyTokensToRoot(json);
            })
                .catch(() => {
                if (!cancelled)
                    reportError("tokens");
            });
        }
        return () => {
            cancelled = true;
        };
    }, [assetBaseUrl, fontsManifestUrl, iconSelectionUrl, tokensUrl, onAssetsLoadError]);
    const handleSetScale = (newScale) => {
        setScale(newScale);
        setCurrentScale(newScale);
    };
    return (_jsx(ScaleContext.Provider, { value: {
            scale,
            setScale: handleSetScale,
            config: getScaleConfig(),
            assetsLoadError,
        }, children: _jsx(IconAssetsContext.Provider, { value: iconAssets, children: children }) }));
}
export function useScale() {
    const context = useContext(ScaleContext);
    if (context === undefined) {
        throw new Error("useScale must be used within a ScaleProvider");
    }
    return context;
}
export function useIconAssets() {
    return useContext(IconAssetsContext);
}
