/**
 * @license MIT
 * author: Cube Dev Team
 * @cube-dev/ui-kit v0.98.7
 * Released under the MIT license.
 */

import { isDevEnv } from '../utils/isDevEnv';
import { StyleInjector } from './injector';
// Use a more robust global singleton that survives React Strict Mode
const GLOBAL_INJECTOR_KEY = '__TASTY_GLOBAL_INJECTOR__';
/**
 * Detect if we're running in a test environment
 */
function isTestEnvironment() {
    // Check Node.js environment
    if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'test') {
        return true;
    }
    // Check for Jest globals (safely)
    if (typeof global !== 'undefined') {
        const g = global;
        if (g.jest || g.expect || g.describe || g.it) {
            return true;
        }
    }
    // Check for jsdom environment (common in tests)
    if (typeof window !== 'undefined' &&
        window.navigator?.userAgent?.includes('jsdom')) {
        return true;
    }
    // Check for other test runners
    if (typeof globalThis !== 'undefined') {
        const gt = globalThis;
        if (gt.vitest || gt.mocha) {
            return true;
        }
    }
    return false;
}
/**
 * Create default configuration with optional test environment detection
 */
function createDefaultConfig(isTest) {
    return {
        maxRulesPerSheet: 8192, // safer default cap per sheet
        unusedStylesThreshold: 500, // default threshold for bulk cleanup of unused styles
        bulkCleanupDelay: 5000, // default delay before bulk cleanup (ignored if idleCleanup is true)
        idleCleanup: true, // default to using requestIdleCallback instead of setTimeout
        forceTextInjection: isTest ?? false, // auto-enable for test environments
        devMode: isDevEnv(), // enable dev features: performance tracking and debug info
        bulkCleanupBatchRatio: 0.5,
        unusedStylesMinAgeMs: 10000,
    };
}
/**
 * Configure the global style injector
 */
export function configure(config = {}) {
    const fullConfig = {
        ...createDefaultConfig(),
        ...config,
    };
    // Store on window to survive React Strict Mode resets
    if (typeof window !== 'undefined') {
        window[GLOBAL_INJECTOR_KEY] = new StyleInjector(fullConfig);
    }
    else {
        // Fallback for SSR
        globalThis[GLOBAL_INJECTOR_KEY] = new StyleInjector(fullConfig);
    }
}
/**
 * Get or create the global injector instance
 */
function getGlobalInjector() {
    const storage = typeof window !== 'undefined' ? window : globalThis;
    if (!storage[GLOBAL_INJECTOR_KEY]) {
        configure();
    }
    return storage[GLOBAL_INJECTOR_KEY];
}
/**
 * Allocate a className for a cacheKey without injecting styles yet
 */
export function allocateClassName(cacheKey, options) {
    return getGlobalInjector().allocateClassName(cacheKey, options);
}
/**
 * Inject styles and return className with dispose function
 */
export function inject(rules, options) {
    return getGlobalInjector().inject(rules, options);
}
/**
 * Inject global rules that should not reserve tasty class names
 */
export function injectGlobal(rules, options) {
    return getGlobalInjector().injectGlobal(rules, options);
}
/**
 * Internal method for createGlobalStyle - not exported publicly
 */
function injectCreateGlobalStyle(rules, options) {
    return getGlobalInjector().injectCreateGlobalStyle(rules, options);
}
/**
 * Inject keyframes and return object with toString() and dispose()
 */
export function keyframes(steps, nameOrOptions) {
    return getGlobalInjector().keyframes(steps, nameOrOptions);
}
/**
 * Get CSS text from all sheets (for SSR)
 */
export function getCssText(options) {
    return getGlobalInjector().getCssText(options);
}
/**
 * Collect only CSS used by a rendered subtree (like jest-styled-components).
 * Pass the container returned by render(...).
 */
export function getCssTextForNode(node, options) {
    // Collect tasty-generated class names (t<number>) from the subtree
    const classSet = new Set();
    const readClasses = (el) => {
        const cls = el.getAttribute('class');
        if (!cls)
            return;
        for (const token of cls.split(/\s+/)) {
            if (/^t\d+$/.test(token))
                classSet.add(token);
        }
    };
    // Include node itself if it's an Element
    if (node.getAttribute) {
        readClasses(node);
    }
    // Walk descendants
    const elements = node.querySelectorAll
        ? node.querySelectorAll('[class]')
        : [];
    elements && elements.forEach(readClasses);
    return getGlobalInjector().getCssTextForClasses(classSet, options);
}
/**
 * Force cleanup of unused rules
 */
export function cleanup(root) {
    return getGlobalInjector().cleanup(root);
}
/**
 * Check if we're currently running in a test environment
 */
export function getIsTestEnvironment() {
    return isTestEnvironment();
}
/**
 * Get the global injector instance for debugging
 */
export const injector = {
    get instance() {
        return getGlobalInjector();
    },
};
/**
 * Destroy all resources and clean up
 */
export function destroy(root) {
    return getGlobalInjector().destroy(root);
}
/**
 * Create a new isolated injector instance
 */
export function createInjector(config = {}) {
    const isTest = isTestEnvironment();
    const fullConfig = {
        ...createDefaultConfig(isTest),
        ...config,
    };
    return new StyleInjector(fullConfig);
}
/**
 * Create a global style component like styled-components createGlobalStyle
 * Returns a React component that injects global styles when mounted and cleans up when unmounted
 */
export function createGlobalStyle(strings, ...interpolations) {
    return getGlobalInjector().createGlobalStyle(strings, ...interpolations);
}
export { StyleInjector } from './injector';
export { SheetManager } from './sheet-manager';

        