import { jsx, jsxs } from 'react/jsx-runtime';
import React__default, { useState, useEffect, useMemo } from 'react';
import { useMotionValue, useTransform, animate, motion, useReducedMotion } from 'motion/react';
import { cn } from '../../../utils/cn.js';
import { multiSegmentDonutChartTheme } from './MultiSegmentDonutChart.theme.js';
import { describeRingSegmentPath, describeArcPathClockwise, clamp } from './donut-utils.js';

const AnimatedSegmentInner = ({ center, innerRadius, outerRadius, startAngle, endAngle, color, delay, duration, shouldAnimate, shouldReduceMotion, isHovered, isFaded, onMouseEnter, onMouseLeave, onClick, clickable, }) => {
    // Motion value for animation progress (0 to 1)
    const progress = useMotionValue(0);
    // Transform progress to current end angle
    const currentEndAngle = useTransform(progress, [0, 1], [startAngle, endAngle]);
    // Generate path based on current angle
    const [path, setPath] = useState(() => describeRingSegmentPath(center, center, innerRadius, outerRadius, startAngle, startAngle // Start with zero-width segment
    ));
    // Update path when currentEndAngle changes
    useEffect(() => {
        const unsubscribe = currentEndAngle.on("change", (latest) => {
            const newPath = describeRingSegmentPath(center, center, innerRadius, outerRadius, startAngle, latest);
            setPath(newPath);
        });
        return () => unsubscribe();
    }, [center, innerRadius, outerRadius, startAngle, currentEndAngle]);
    // Trigger animation
    useEffect(() => {
        if (shouldReduceMotion) {
            // Skip animation for accessibility - show full segment immediately
            progress.set(1);
        }
        else if (shouldAnimate) {
            // Run the drawing animation with spring physics (same as base DonutChart)
            const controls = animate(progress, 1, {
                type: "spring",
                stiffness: 80, // Same as CIRCULAR_CHART_ANIMATIONS.donut.preset ('smooth')
                damping: 20,
                delay,
            });
            return () => controls.stop();
        }
        // If shouldAnimate is false, progress stays at 0 (waiting state)
    }, [shouldAnimate, shouldReduceMotion, progress, duration, delay]);
    return (jsx(motion.path, { d: path, fill: color, animate: {
            opacity: isFaded ? 0.6 : 1,
            scale: isHovered ? 1.025 : 1,
        }, transition: {
            scale: { duration: 0.2 },
            opacity: { duration: 0.2 },
        }, style: {
            transformOrigin: "50% 50%",
            cursor: clickable ? "pointer" : "default",
            filter: isHovered
                ? `drop-shadow(0 4px 8px ${color}60)`
                : "none",
        }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: onClick }));
};
const AnimatedSegment = React__default.memo(AnimatedSegmentInner);
const AnimatedStrokeSegmentInner = ({ center, radius, strokeWidth, startAngle, endAngle, color, delay, shouldAnimate, shouldReduceMotion, isHovered, isFaded, onMouseEnter, onMouseLeave, onClick, clickable, }) => {
    // Calculate cap compensation - rounded caps extend by strokeWidth/2 at each end
    // Convert to degrees: (strokeWidth/2) / radius * (180/π)
    const capCompensationDegrees = ((strokeWidth / 2) / radius) * (180 / Math.PI);
    // Adjust angles to account for rounded cap protrusion
    const adjustedStartAngle = startAngle + capCompensationDegrees;
    const adjustedEndAngle = endAngle - capCompensationDegrees;
    // Ensure we have a valid arc (end > start)
    const validEndAngle = Math.max(adjustedEndAngle, adjustedStartAngle + 1);
    // Calculate arc path (clockwise for proper animation direction) and length
    const arcPath = describeArcPathClockwise(center, center, radius, adjustedStartAngle, validEndAngle);
    const sweepAngle = validEndAngle - adjustedStartAngle;
    const arcLength = (sweepAngle / 360) * 2 * Math.PI * radius;
    return (jsx(motion.path, { d: arcPath, fill: "none", stroke: color, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: arcLength, initial: { strokeDashoffset: arcLength, opacity: 1, scale: 1 }, animate: {
            strokeDashoffset: shouldAnimate ? 0 : arcLength,
            opacity: isFaded ? 0.6 : 1,
            scale: isHovered ? 1.025 : 1,
        }, transition: {
            strokeDashoffset: shouldReduceMotion
                ? { duration: 0 }
                : {
                    type: "spring",
                    stiffness: 80,
                    damping: 20,
                    delay,
                },
            scale: { duration: 0.2 },
            opacity: { duration: 0.2 },
        }, style: {
            transformOrigin: "50% 50%",
            cursor: clickable ? "pointer" : "default",
            filter: isHovered ? `drop-shadow(0 4px 8px ${color}60)` : "none",
        }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: onClick }));
};
const AnimatedStrokeSegment = React__default.memo(AnimatedStrokeSegmentInner);
/**
 * MultiSegmentDonutChart component for displaying multiple data values in a circular chart
 * Each segment represents a different data point with its own value and optional color
 */
const MultiSegmentDonutChart = ({ data, size = 200, thickness = 4, segmentGap = 0.05, showAnimation = true, showLegend = false, legendPosition = "right", centerContent, className, theme: themeOverrides, onSegmentHover, onSegmentClick, roundedCaps = true, onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...restProps }) => {
    const [hoveredSegment, setHoveredSegment] = useState(null);
    const [hasAnimated, setHasAnimated] = useState(false);
    const shouldReduceMotion = useReducedMotion();
    // Merge theme with overrides
    const theme = {
        ...multiSegmentDonutChartTheme,
        ...(themeOverrides || {}),
        legend: {
            ...multiSegmentDonutChartTheme.legend,
            ...((themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.legend) || {}),
        },
        colors: (themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.colors) || multiSegmentDonutChartTheme.colors || [],
    };
    // Calculate SVG parameters
    const svgSize = 100;
    const center = svgSize / 2;
    const strokeWidth = thickness * 2;
    const radius = (svgSize - strokeWidth) / 2;
    const innerRadius = Math.max(0, radius - strokeWidth / 2);
    const outerRadius = radius + strokeWidth / 2;
    // Validate and prepare data
    const validatedData = useMemo(() => {
        if (!data || data.length === 0) {
            return [];
        }
        // Ensure percentages sum to 100 or less
        const totalPercentage = data.reduce((sum, segment) => sum + segment.percentage, 0);
        if (totalPercentage > 100) {
            if (process.env.NODE_ENV !== 'production') {
                console.warn(`[MultiSegmentDonutChart]: Total percentage (${totalPercentage}) exceeds 100%. Normalizing values.`);
            }
            // Normalize percentages
            return data.map((segment) => ({
                ...segment,
                percentage: (segment.percentage / totalPercentage) * 100,
            }));
        }
        return data;
    }, [data]);
    // Calculate segment paths, colors, and animation timings
    const segments = useMemo(() => {
        if (validatedData.length === 0) {
            return [];
        }
        const gapRatio = clamp(segmentGap, 0, 0.8);
        const totalGapDegrees = validatedData.length * 360 * gapRatio / validatedData.length;
        const effectiveCircle = 360 - totalGapDegrees;
        let currentAngle = 0; // Start at 12 o'clock (top)
        let cumulativeDelay = 0; // Track cumulative delay for sequential animation
        // Base duration for a full 100% segment (in seconds)
        const baseDuration = 0.6;
        return validatedData.map((segment, index) => {
            // Calculate the angle for this segment
            const segmentAngle = (segment.percentage / 100) * effectiveCircle;
            const gapAngle = 360 * gapRatio / validatedData.length;
            const startAngle = currentAngle;
            const endAngle = currentAngle + segmentAngle;
            // Get color from segment or theme palette
            const color = segment.color ||
                (theme.colors && theme.colors[index % theme.colors.length]) ||
                "#3b82f6";
            // Generate the SVG path (full segment)
            const path = describeRingSegmentPath(center, center, innerRadius, outerRadius, startAngle, endAngle);
            // Calculate animation duration proportional to segment size
            // Minimum duration of 0.15s to ensure visibility
            const duration = Math.max(0.15, (segment.percentage / 100) * baseDuration);
            // This segment starts after all previous segments complete
            const delay = cumulativeDelay;
            // Add this segment's duration to cumulative delay for next segment
            cumulativeDelay += duration;
            // Move to next segment start position
            currentAngle = endAngle + gapAngle;
            return {
                ...segment,
                path,
                color,
                startAngle,
                endAngle,
                animationDuration: duration,
                animationDelay: delay,
            };
        });
    }, [
        validatedData,
        center,
        innerRadius,
        outerRadius,
        segmentGap,
        theme.colors,
    ]);
    // Handle component mount for animation
    useEffect(() => {
        if (showAnimation && !shouldReduceMotion) {
            setHasAnimated(true);
        }
        else {
            // If animations disabled, immediately show final state
            setHasAnimated(true);
        }
    }, [showAnimation, shouldReduceMotion]);
    // Handle hover interactions
    const handleSegmentMouseEnter = (index) => {
        setHoveredSegment(index);
        if (onSegmentHover) {
            onSegmentHover(segments[index]);
        }
    };
    const handleSegmentMouseLeave = () => {
        setHoveredSegment(null);
        if (onSegmentHover) {
            onSegmentHover(null);
        }
    };
    const handleSegmentClick = (index) => {
        if (onSegmentClick) {
            onSegmentClick(segments[index]);
        }
    };
    const containerSize = typeof size === "number" ? `${size}px` : size;
    // Layout classes based on legend position
    const getLayoutClasses = () => {
        if (!showLegend) {
            return "";
        }
        switch (legendPosition) {
            case "top":
                return "flex-col";
            case "bottom":
                return "flex-col-reverse";
            case "left":
                return "flex-row-reverse";
            case "right":
            default:
                return "flex-row";
        }
    };
    const renderLegend = () => {
        var _a;
        if (!showLegend) {
            return null;
        }
        return (jsx("div", { className: cn((_a = theme.legend) === null || _a === void 0 ? void 0 : _a.container, legendPosition === "top" || legendPosition === "bottom" ? "flex-row flex-wrap" : "flex-col"), children: segments.map((segment, index) => {
                var _a, _b, _c, _d;
                return (jsxs("div", { className: cn((_a = theme.legend) === null || _a === void 0 ? void 0 : _a.item), onMouseEnter: () => handleSegmentMouseEnter(index), onMouseLeave: handleSegmentMouseLeave, onClick: () => handleSegmentClick(index), style: {
                        opacity: hoveredSegment !== null && hoveredSegment !== index ? 0.5 : 1,
                    }, children: [jsx("div", { className: cn((_b = theme.legend) === null || _b === void 0 ? void 0 : _b.colorDot), style: { backgroundColor: segment.color } }), segment.label && (jsx("span", { className: cn((_c = theme.legend) === null || _c === void 0 ? void 0 : _c.label), children: segment.label })), jsxs("span", { className: cn((_d = theme.legend) === null || _d === void 0 ? void 0 : _d.value), children: [segment.value, " (", segment.percentage.toFixed(1), "%)"] })] }, `legend-${index}`));
            }) }));
    };
    if (!data || data.length === 0) {
        return (jsx("div", { className: cn(theme.baseStyle, className), style: { width: containerSize, height: containerSize }, children: jsx("div", { className: "text-base text-[var(--color-text-secondary)]", children: "No data" }) }));
    }
    return (jsxs("div", { className: cn("flex gap-4 items-center", getLayoutClasses(), className), children: [jsxs(motion.div, { className: cn(theme.baseStyle), style: { width: containerSize, height: containerSize }, role: "img", "aria-label": `Donut chart with ${segments.length} segments`, ...restProps, children: [jsxs("svg", { viewBox: `0 0 ${svgSize} ${svgSize}`, width: "100%", height: "100%", className: "overflow-visible relative z-10", children: [jsx("circle", { cx: center, cy: center, r: radius, fill: "none", stroke: "#000000", strokeWidth: strokeWidth > 2 ? strokeWidth - 2 : 1, opacity: 0.03 }), segments.map((segment, index) => roundedCaps ? (jsx(AnimatedStrokeSegment, { center: center, radius: radius, strokeWidth: strokeWidth, startAngle: segment.startAngle, endAngle: segment.endAngle, color: segment.color, delay: segment.animationDelay, shouldAnimate: showAnimation && hasAnimated, shouldReduceMotion: shouldReduceMotion, isHovered: hoveredSegment === index, isFaded: hoveredSegment !== null && hoveredSegment !== index, onMouseEnter: () => handleSegmentMouseEnter(index), onMouseLeave: handleSegmentMouseLeave, onClick: () => handleSegmentClick(index), clickable: !!onSegmentClick }, `segment-${index}`)) : (jsx(AnimatedSegment, { center: center, innerRadius: innerRadius, outerRadius: outerRadius, startAngle: segment.startAngle, endAngle: segment.endAngle, color: segment.color, delay: segment.animationDelay, duration: segment.animationDuration, shouldAnimate: showAnimation && hasAnimated, shouldReduceMotion: shouldReduceMotion, isHovered: hoveredSegment === index, isFaded: hoveredSegment !== null && hoveredSegment !== index, onMouseEnter: () => handleSegmentMouseEnter(index), onMouseLeave: handleSegmentMouseLeave, onClick: () => handleSegmentClick(index), clickable: !!onSegmentClick }, `segment-${index}`)))] }), centerContent && (jsx("div", { className: cn(theme.centerContent), children: centerContent }))] }), renderLegend()] }));
};
MultiSegmentDonutChart.displayName = "MultiSegmentDonutChart";

export { MultiSegmentDonutChart };
