import { jsx, jsxs } from 'react/jsx-runtime';
import React__default, { useState, useEffect, useCallback, useMemo } from 'react';
import { cn } from '../../../utils/cn.js';
import { carouselTheme } from './Carousel.theme.js';
import { CarouselContext } from './CarouselContext.js';
import { CarouselBody } from './CarouselBody.js';
import { CarouselItem } from './CarouselItem.js';
import { CarouselPrevious } from './CarouselPrevious.js';
import { CarouselNext } from './CarouselNext.js';

const CarouselRoot = React__default.forwardRef(({ orientation = 'horizontal', opts = {}, showControls = false, defaultIndex = 0, onSlideChange, className, children, ...rest }, ref) => {
    const { align = 'start', loop = false, slidesToScroll = 1, draggable = true, dragThreshold = 0.1, } = opts;
    // Count total slides by looking for CarouselBody and its CarouselItem children
    const totalSlides = React__default.useMemo(() => {
        let count = 0;
        React__default.Children.forEach(children, (child) => {
            if (React__default.isValidElement(child) && child.type === CarouselBody) {
                const contentProps = child.props;
                count = React__default.Children.count(contentProps.children);
            }
        });
        return count;
    }, [children]);
    const [currentIndex, setCurrentIndex] = useState(() => {
        return Math.max(0, Math.min(defaultIndex, totalSlides - 1));
    });
    // Ensure current index stays in range when total slides change
    useEffect(() => {
        if (currentIndex >= totalSlides && totalSlides > 0) {
            setCurrentIndex(totalSlides - 1);
        }
    }, [totalSlides, currentIndex]);
    // Call onSlideChange when index changes
    useEffect(() => {
        onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(currentIndex);
    }, [currentIndex, onSlideChange]);
    const scrollTo = useCallback((index) => {
        if (totalSlides === 0)
            return;
        if (loop) {
            // Handle loop mode with wrapping
            const normalizedIndex = ((index % totalSlides) + totalSlides) % totalSlides;
            setCurrentIndex(normalizedIndex);
        }
        else {
            // Clamp to valid range in non-loop mode
            const clampedIndex = Math.max(0, Math.min(index, totalSlides - 1));
            setCurrentIndex(clampedIndex);
        }
    }, [totalSlides, loop]);
    const scrollPrev = useCallback(() => {
        scrollTo(currentIndex - slidesToScroll);
    }, [currentIndex, slidesToScroll, scrollTo]);
    const scrollNext = useCallback(() => {
        scrollTo(currentIndex + slidesToScroll);
    }, [currentIndex, slidesToScroll, scrollTo]);
    const canScrollPrev = loop || currentIndex > 0;
    const canScrollNext = loop || currentIndex < totalSlides - 1;
    const memoizedOpts = useMemo(() => ({ align, loop, slidesToScroll, draggable, dragThreshold }), [align, loop, slidesToScroll, draggable, dragThreshold]);
    const contextValue = useMemo(() => ({
        currentIndex,
        totalSlides,
        scrollTo,
        scrollPrev,
        scrollNext,
        canScrollPrev,
        canScrollNext,
        orientation,
        opts: memoizedOpts,
    }), [currentIndex, totalSlides, scrollTo, scrollPrev, scrollNext, canScrollPrev, canScrollNext, orientation, memoizedOpts]);
    return (jsx(CarouselContext.Provider, { value: contextValue, children: jsxs("div", { ref: ref, role: "region", "aria-roledescription": "carousel", "aria-label": "Carousel", className: cn(carouselTheme.root, className), ...rest, children: [children, showControls && totalSlides > 1 && (jsxs("div", { className: carouselTheme.controls, children: [jsx(CarouselPrevious, {}), jsx(CarouselNext, {})] }))] }) }));
});
CarouselRoot.displayName = 'Carousel';
// Create compound component with sub-components
const Carousel = Object.assign(CarouselRoot, {
    Body: CarouselBody,
    Item: CarouselItem,
    Previous: CarouselPrevious,
    Next: CarouselNext,
});

export { Carousel };
