import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import React__default, { useContext, useState, useCallback, useMemo, useEffect } from 'react';
import { AnimatePresence, motion } from 'motion/react';
import { createPortal } from 'react-dom';
import { Calendar } from '../../core/Calendar/Calendar.js';
import '../../core/Calendar/CalendarMini/CalendarMini.js';
import { Button } from '../../core/Button/Button.js';
import { cn } from '../../../utils/cn.js';
import { DatePickerContext } from './DatePicker.js';
import { DatePickerPresets } from './DatePickerPresets.js';
import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
import { formatDateCustom } from '../../../utils/dateUtils.js';
import { createDropdownAnimations } from './DatePicker.animations.js';
import { useIsClient } from '../../../hooks/useIsClient.js';

/**
 * Hook to detect dark mode state from document
 */
const useDarkMode = () => {
    const [isDark, setIsDark] = useState(false);
    useEffect(() => {
        if (typeof document === "undefined")
            return;
        const checkDarkMode = () => {
            const hasDarkClass = document.documentElement.classList.contains("dark") ||
                document.body.classList.contains("dark") ||
                document.querySelector(".dark") !== null;
            setIsDark(hasDarkClass);
        };
        checkDarkMode();
        // Observe class changes on html and body
        const observer = new MutationObserver(checkDarkMode);
        observer.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ["class"],
        });
        observer.observe(document.body, {
            attributes: true,
            attributeFilter: ["class"],
        });
        return () => observer.disconnect();
    }, []);
    return isDark;
};
/**
 * DatePicker Body Component - contains the Calendar and optional Presets
 * Uses portal positioning like Select component
 */
const DatePickerBody = ({ isOpen, className, onClose, portal = true, placement = "bottom-start", offset = 4, presets, children, }) => {
    const context = useContext(DatePickerContext);
    if (!context) {
        throw new Error("DatePickerBody must be used within a DatePicker");
    }
    const { mode, theme, triggerRef, contentRef, selectedValue, minDate, maxDate, isDateDisabled, showToday, selectTodayByDefault, weekdays, months, handleDateSelect, handleRangeSelect, yearRange, } = context;
    // Determine if we should show presets
    const showPresets = mode === "range" && presets && presets.length > 0;
    // Detect dark mode for portal content
    const isDarkMode = useDarkMode();
    const isClient = useIsClient();
    // Temp range state for range mode (not committed until Apply is clicked)
    const [tempRange, setTempRange] = useState(mode === "range" &&
        selectedValue &&
        typeof selectedValue === "object" &&
        "start" in selectedValue
        ? selectedValue
        : undefined);
    // Handle preset selection - update calendar view to show the range
    const handlePresetSelect = useCallback((range) => {
        if (range.start) {
            setLeftCalendarDate(new Date(range.start.getFullYear(), range.start.getMonth(), 1));
        }
    }, []);
    // Dual calendar state for range mode
    const getInitialLeftDate = () => {
        if (mode === "range" && (tempRange === null || tempRange === void 0 ? void 0 : tempRange.start)) {
            return tempRange.start;
        }
        if (mode === "range" &&
            selectedValue &&
            typeof selectedValue === "object" &&
            "start" in selectedValue) {
            return selectedValue.start || new Date();
        }
        return new Date();
    };
    const [leftCalendarDate, setLeftCalendarDate] = useState(getInitialLeftDate);
    // Right calendar always shows next month
    const rightCalendarDate = useMemo(() => {
        const nextMonth = new Date(leftCalendarDate);
        nextMonth.setMonth(nextMonth.getMonth() + 1);
        return nextMonth;
    }, [leftCalendarDate]);
    // Navigation handlers for dual calendar
    const handleNavigatePrev = useCallback(() => {
        setLeftCalendarDate((prev) => {
            const newDate = new Date(prev);
            newDate.setMonth(newDate.getMonth() - 1);
            return newDate;
        });
    }, []);
    const handleNavigateNext = useCallback(() => {
        setLeftCalendarDate((prev) => {
            const newDate = new Date(prev);
            newDate.setMonth(newDate.getMonth() + 1);
            return newDate;
        });
    }, []);
    // Footer handlers for range mode
    const handleApply = useCallback(() => {
        if (tempRange && mode === "range") {
            handleRangeSelect === null || handleRangeSelect === void 0 ? void 0 : handleRangeSelect(tempRange); // Commit the temp range
        }
        onClose === null || onClose === void 0 ? void 0 : onClose();
    }, [tempRange, mode, handleRangeSelect, onClose]);
    const handleCancel = useCallback(() => {
        // Reset temp range to committed value
        setTempRange(selectedValue &&
            typeof selectedValue === "object" &&
            "start" in selectedValue
            ? selectedValue
            : undefined);
        onClose === null || onClose === void 0 ? void 0 : onClose();
    }, [selectedValue, onClose]);
    // Format range for footer display
    const formatRangeDisplay = (range) => {
        if (!(range === null || range === void 0 ? void 0 : range.start) && !(range === null || range === void 0 ? void 0 : range.end))
            return "Select start and end dates";
        if (!range.end)
            return `${formatDateCustom(range.start, "DD/MM/YYYY")} - ...`;
        return `${formatDateCustom(range.start, "DD/MM/YYYY")} - ${formatDateCustom(range.end, "DD/MM/YYYY")}`;
    };
    // Use simplified dropdown positioning hook (same as Select)
    const { position, cssVariables, contentRef: portalContentRef, isFlipped, isReady, } = useSelectPortal({
        triggerRef,
        isOpen: isOpen || false,
        placement,
        offset,
        autoWidth: true, // Allow dropdown to size to its content
    });
    // Create direction-aware animations based on dropdown placement
    const animations = createDropdownAnimations(isFlipped);
    // Combine refs for portal and legacy usage
    const combinedRef = React__default.useCallback((el) => {
        if (contentRef &&
            typeof contentRef === "object" &&
            "current" in contentRef) {
            contentRef.current =
                el;
        }
        if (portalContentRef &&
            typeof portalContentRef === "object" &&
            "current" in portalContentRef) {
            portalContentRef.current = el;
        }
    }, [contentRef, portalContentRef]);
    // Handle click outside to close
    useEffect(() => {
        if (!isOpen)
            return;
        const handleClickOutside = (event) => {
            var _a;
            const target = event.target;
            // Don't close if clicking inside a portal-rendered Select dropdown (e.g., month/year selects)
            if ((_a = target.closest) === null || _a === void 0 ? void 0 : _a.call(target, '[role="listbox"]')) {
                return;
            }
            const currentContentRef = portal
                ? portalContentRef.current
                : contentRef.current;
            if (currentContentRef &&
                !currentContentRef.contains(target) &&
                triggerRef.current &&
                !triggerRef.current.contains(target)) {
                onClose === null || onClose === void 0 ? void 0 : onClose();
            }
        };
        document.addEventListener("mousedown", handleClickOutside);
        return () => {
            document.removeEventListener("mousedown", handleClickOutside);
        };
    }, [isOpen, onClose, triggerRef, contentRef, portalContentRef, portal]);
    // Handle escape key
    useEffect(() => {
        if (!isOpen)
            return;
        const handleKeyDown = (event) => {
            if (event.key === "Escape") {
                onClose === null || onClose === void 0 ? void 0 : onClose();
            }
        };
        document.addEventListener("keydown", handleKeyDown);
        return () => {
            document.removeEventListener("keydown", handleKeyDown);
        };
    }, [isOpen, onClose]);
    const contentElement = (jsx(AnimatePresence, { mode: "wait", children: isOpen && (jsxs(motion.div, { ref: combinedRef, className: cn(showPresets ? theme.bodyWithPresetsStyle : theme.bodyStyle, className), style: {
                ...cssVariables,
                ...(portal
                    ? {
                        top: `${position.top}px`,
                        left: `${position.left}px`,
                        minWidth: `${position.width}px`,
                    }
                    : {}),
            }, variants: animations, initial: "initial", animate: isReady ? "visible" : "initial", exit: "exit", children: [showPresets && presets && (jsx(DatePickerPresets, { presets: presets, setTempRange: setTempRange, onPresetSelect: handlePresetSelect })), jsx("div", { className: "flex flex-col flex-1", children: mode === "range" ? (
                    // Dual calendar for range mode
                    jsxs(Fragment, { children: [jsx("div", { className: "flex justify-between items-start gap-6 p-4", children: children || (jsxs(Fragment, { children: [jsx("div", { className: "flex-1 min-w-fit", children: jsx(Calendar, { mode: "range", value: tempRange, onChange: (value) => {
                                                    setTempRange(value); // Update temp state only
                                                }, viewDate: leftCalendarDate, onViewDateChange: setLeftCalendarDate, onNavigatePrev: handleNavigatePrev, onNavigateNext: null, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: selectTodayByDefault, weekdays: weekdays, months: months, yearRange: yearRange, size: "md" }) }), jsx("div", { className: "flex-1 min-w-fit", children: jsx(Calendar, { mode: "range", value: tempRange, onChange: (value) => {
                                                    setTempRange(value); // Update temp state only
                                                }, viewDate: rightCalendarDate, onViewDateChange: (newDate) => {
                                                    // Adjust left calendar when right calendar changes
                                                    const adjustedLeft = new Date(newDate);
                                                    adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
                                                    setLeftCalendarDate(adjustedLeft);
                                                }, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, size: "md" }) })] })) }), jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button, { variant: "outline", color: "neutral", size: "sm", onClick: handleCancel, children: "Cancel" }), jsx(Button, { variant: "filled", size: "sm", onClick: handleApply, disabled: !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.start) || !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.end), children: "Apply" })] })] })] })) : (
                    // Single calendar for single mode
                    jsx("div", { className: "flex-1 p-4", children: children || (jsx(Calendar, { mode: "single", value: selectedValue, onChange: (value) => {
                                handleDateSelect(value);
                                onClose === null || onClose === void 0 ? void 0 : onClose();
                            }, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: selectTodayByDefault, weekdays: weekdays, months: months, yearRange: yearRange, size: "md" })) })) })] })) }));
    // Use portal if enabled and client-side - wrap with dark class for dark mode support
    if (portal && isClient) {
        return createPortal(jsx("div", { className: isDarkMode ? "dark" : undefined, children: contentElement }), document.body);
    }
    return contentElement;
};
DatePickerBody.displayName = "DatePicker.Body";

export { DatePickerBody };
