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

import { useInsertionEffect, useMemo, useRef } from 'react';
import { keyframes } from '../injector/index.js';
// Implementation
export function useKeyframes(stepsOrFactory, depsOrOptions, options) {
    // Detect which overload is being used
    const isFactory = typeof stepsOrFactory === 'function';
    // Parse arguments based on overload
    const deps = isFactory && Array.isArray(depsOrOptions) ? depsOrOptions : undefined;
    const opts = isFactory
        ? options
        : depsOrOptions;
    // Memoize the keyframes steps to get a stable reference
    const stepsData = useMemo(() => {
        const steps = isFactory
            ? stepsOrFactory()
            : stepsOrFactory;
        if (!steps || Object.keys(steps).length === 0) {
            return null;
        }
        return steps;
    }, isFactory ? deps ?? [] : [stepsOrFactory]);
    // Store keyframes results for cleanup - we need to track both the render-time
    // injection (for the name) and the effect-time injection (for Strict Mode safety)
    const renderResultRef = useRef(null);
    const effectResultRef = useRef(null);
    // Inject keyframes during render to ensure the animation name is available
    // immediately. The keyframes() function uses reference counting internally,
    // so multiple calls with the same content are deduplicated.
    const name = useMemo(() => {
        // Dispose previous render-time result if deps changed
        renderResultRef.current?.dispose();
        renderResultRef.current = null;
        if (!stepsData) {
            return '';
        }
        // Inject keyframes synchronously
        const result = keyframes(stepsData, {
            name: opts?.name,
            root: opts?.root,
        });
        renderResultRef.current = result;
        return result.toString();
    }, [stepsData, opts?.name, opts?.root]);
    // Handle injection and cleanup in useInsertionEffect to properly support
    // React 18+ Strict Mode double-invocation (mount → unmount → mount).
    // The effect setup re-injects the keyframes if cleanup was called, ensuring
    // the CSS exists after Strict Mode remounts.
    useInsertionEffect(() => {
        // Dispose previous effect-time result
        effectResultRef.current?.dispose();
        effectResultRef.current = null;
        // Re-inject keyframes. This ensures the CSS exists after Strict Mode cleanup.
        // The keyframes() function uses reference counting, so this is idempotent
        // if the CSS wasn't disposed.
        if (stepsData) {
            const result = keyframes(stepsData, {
                name: opts?.name,
                root: opts?.root,
            });
            effectResultRef.current = result;
        }
        // Cleanup on unmount or when dependencies change.
        // Dispose both the effect-time and render-time results to properly
        // decrement the reference count.
        return () => {
            effectResultRef.current?.dispose();
            effectResultRef.current = null;
            renderResultRef.current?.dispose();
            renderResultRef.current = null;
        };
    }, [stepsData, opts?.name, opts?.root]);
    return name;
}

        