import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useRef, useMemo, useCallback } from 'react';
import { useReducedMotion, motion } from 'motion/react';
import { cn } from '../../../utils/cn.js';
import { radarChartTheme } from './RadarChart.theme.js';
import { RADAR_CHART_ANIMATIONS } from './RadarChart.animations.js';
import { getSpringAnimation, getStaggerDelay } from '../utils/animation-utils.js';
import { ChartTooltip } from '../shared/ChartTooltip/ChartTooltip.js';
import { useTooltipPosition } from '../hooks/useTooltipPosition.js';

/* -------------------------------------------------------------------------- */
/*  Geometry helpers                                                          */
/* -------------------------------------------------------------------------- */
function polarToCartesian(cx, cy, radius, angleRad) {
    return {
        x: cx + radius * Math.cos(angleRad),
        y: cy + radius * Math.sin(angleRad),
    };
}
function axisAngle(index, total) {
    return (2 * Math.PI * index) / total - Math.PI / 2;
}
function buildPolygonPoints(values, maxValue, cx, cy, chartRadius) {
    return values
        .map((v, i) => {
        const ratio = maxValue > 0 ? Math.min(v, maxValue) / maxValue : 0;
        const r = ratio * chartRadius;
        const angle = axisAngle(i, values.length);
        const { x, y } = polarToCartesian(cx, cy, r, angle);
        return `${x},${y}`;
    })
        .join(" ");
}
/* -------------------------------------------------------------------------- */
/*  Component                                                                 */
/* -------------------------------------------------------------------------- */
const RadarChart = ({ axes, series, size = 400, gridLevels = 5, maxValue: maxValueProp, showGrid = true, showLabels = true, showLegend = true, showTooltip = true, showAnimation = true, fillOpacity = 0.25, strokeWidth = 2, className, theme: themeOverrides, ...props }) => {
    const shouldReduceMotion = useReducedMotion();
    const containerRef = useRef(null);
    // Tooltip setup
    const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
    const { tooltipData, tooltipRef, handleMouseEnter, handleMouseMove, handleMouseLeave, } = useTooltipPosition({
        containerRef,
        isMobile,
    });
    // Merge theme overrides
    const theme = useMemo(() => ({ ...radarChartTheme, ...(themeOverrides || {}) }), [themeOverrides]);
    const axisCount = axes.length;
    // Auto-detect maxValue when not provided
    const maxValue = useMemo(() => {
        if (maxValueProp !== undefined)
            return maxValueProp;
        let max = 0;
        for (const s of series) {
            for (const v of s.data) {
                if (v > max)
                    max = v;
            }
        }
        return max > 0 ? Math.ceil(max / 10) * 10 : 100;
    }, [maxValueProp, series]);
    // Layout constants
    const labelOffset = 24;
    const chartRadius = (size - labelOffset * 2) / 2;
    const cx = size / 2;
    const cy = size / 2;
    /* ----------------------------- Grid rings ----------------------------- */
    const gridRings = useMemo(() => {
        if (!showGrid || gridLevels <= 0)
            return [];
        return Array.from({ length: gridLevels }, (_, levelIdx) => {
            const ratio = (levelIdx + 1) / gridLevels;
            const r = ratio * chartRadius;
            const points = Array.from({ length: axisCount }, (_, i) => {
                const angle = axisAngle(i, axisCount);
                const { x, y } = polarToCartesian(cx, cy, r, angle);
                return `${x},${y}`;
            }).join(" ");
            return points;
        });
    }, [showGrid, gridLevels, axisCount, chartRadius, cx, cy]);
    /* ----------------------------- Axis spokes ----------------------------- */
    const spokes = useMemo(() => {
        return Array.from({ length: axisCount }, (_, i) => {
            const angle = axisAngle(i, axisCount);
            const end = polarToCartesian(cx, cy, chartRadius, angle);
            return { x1: cx, y1: cy, x2: end.x, y2: end.y };
        });
    }, [axisCount, chartRadius, cx, cy]);
    /* ----------------------------- Axis labels ----------------------------- */
    const labels = useMemo(() => {
        if (!showLabels)
            return [];
        const padding = 14;
        return axes.map((label, i) => {
            const angle = axisAngle(i, axisCount);
            const { x, y } = polarToCartesian(cx, cy, chartRadius + padding, angle);
            let anchor = "middle";
            if (x < cx - 1)
                anchor = "end";
            else if (x > cx + 1)
                anchor = "start";
            let dy = "0.35em";
            if (y < cy - chartRadius * 0.5)
                dy = "0.9em";
            else if (y > cy + chartRadius * 0.5)
                dy = "-0.35em";
            return { text: label, x, y, anchor, dy };
        });
    }, [axes, axisCount, showLabels, chartRadius, cx, cy]);
    /* ----------------------------- Data polygons ----------------------------- */
    const polygons = useMemo(() => {
        return series.map((s) => ({
            points: buildPolygonPoints(s.data, maxValue, cx, cy, chartRadius),
            color: s.color,
            label: s.label,
        }));
    }, [series, maxValue, cx, cy, chartRadius]);
    /* ----------------------------- Tooltip handler ----------------------------- */
    const buildTooltipContent = useCallback((axisIndex) => ({
        category: axes[axisIndex],
        series: series.map((s) => ({
            key: s.label,
            label: s.label,
            value: s.data[axisIndex],
            color: s.color,
        })),
    }), [axes, series]);
    const handleDotMouseEnter = useCallback((event, axisIndex) => {
        if (!showTooltip)
            return;
        const content = buildTooltipContent(axisIndex);
        handleMouseEnter(event, content);
    }, [showTooltip, buildTooltipContent, handleMouseEnter]);
    /* ----------------------------- Animation ----------------------------- */
    const shouldAnimate = showAnimation && !shouldReduceMotion;
    return (jsxs("div", { ref: containerRef, className: cn(theme.baseStyle, className), role: "img", "aria-label": `Radar chart comparing ${series.map((s) => s.label).join(", ")} across ${axes.join(", ")}`, ...props, children: [jsxs("svg", { viewBox: `0 0 ${size} ${size}`, width: size, height: size, className: "overflow-visible", children: [gridRings.map((points, idx) => (jsx("polygon", { points: points, fill: "none", stroke: theme.gridColor, strokeWidth: 1 }, `grid-${idx}`))), spokes.map((spoke, idx) => (jsx("line", { x1: spoke.x1, y1: spoke.y1, x2: spoke.x2, y2: spoke.y2, stroke: theme.axisColor, strokeWidth: 1 }, `spoke-${idx}`))), polygons.map((poly, idx) => shouldAnimate ? (jsx(motion.polygon, { points: poly.points, fill: poly.color, fillOpacity: fillOpacity, stroke: poly.color, strokeWidth: strokeWidth, strokeLinejoin: "round", initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: getSpringAnimation(RADAR_CHART_ANIMATIONS.preset, shouldReduceMotion, RADAR_CHART_ANIMATIONS.initialDelay +
                            getStaggerDelay(idx, RADAR_CHART_ANIMATIONS.seriesStagger)), style: { transformOrigin: `${cx}px ${cy}px` } }, `series-${idx}`)) : (jsx("polygon", { points: poly.points, fill: poly.color, fillOpacity: fillOpacity, stroke: poly.color, strokeWidth: strokeWidth, strokeLinejoin: "round" }, `series-${idx}`))), series.map((s, sIdx) => s.data.map((v, dIdx) => {
                        const ratio = maxValue > 0 ? Math.min(v, maxValue) / maxValue : 0;
                        const r = ratio * chartRadius;
                        const angle = axisAngle(dIdx, axisCount);
                        const { x, y } = polarToCartesian(cx, cy, r, angle);
                        const dotProps = {
                            cx: x,
                            cy: y,
                            r: 3,
                            fill: s.color,
                            className: showTooltip ? "cursor-pointer" : undefined,
                            onMouseEnter: showTooltip
                                ? (e) => handleDotMouseEnter(e, dIdx)
                                : undefined,
                            onMouseMove: showTooltip ? handleMouseMove : undefined,
                            onMouseLeave: showTooltip ? handleMouseLeave : undefined,
                        };
                        // Invisible larger hit area behind each dot for easier hover
                        const hitArea = showTooltip ? (jsx("circle", { cx: x, cy: y, r: 10, fill: "transparent", className: "cursor-pointer", onMouseEnter: (e) => handleDotMouseEnter(e, dIdx), onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave }, `hit-${sIdx}-${dIdx}`)) : null;
                        return shouldAnimate ? (jsxs(React__default.Fragment, { children: [hitArea, jsx(motion.circle, { ...dotProps, initial: { opacity: 0 }, animate: { opacity: 1 }, transition: getSpringAnimation(RADAR_CHART_ANIMATIONS.preset, shouldReduceMotion, RADAR_CHART_ANIMATIONS.initialDelay +
                                        getStaggerDelay(sIdx, RADAR_CHART_ANIMATIONS.seriesStagger) +
                                        0.05) })] }, `dot-${sIdx}-${dIdx}`)) : (jsxs(React__default.Fragment, { children: [hitArea, jsx("circle", { ...dotProps })] }, `dot-${sIdx}-${dIdx}`));
                    })), labels.map((lbl, idx) => (jsx("text", { x: lbl.x, y: lbl.y, textAnchor: lbl.anchor, dy: lbl.dy, className: theme.labelStyle, children: lbl.text }, `label-${idx}`)))] }), showLegend && series.length > 0 && (jsx("div", { className: cn(theme.legendStyle), children: series.map((s, idx) => (jsxs("div", { className: cn(theme.legendItemStyle), children: [jsx("span", { className: cn(theme.legendDotStyle), style: { backgroundColor: s.color } }), jsx("span", { className: cn(theme.legendLabelStyle), children: s.label })] }, `legend-${idx}`))) })), showTooltip && (jsx(ChartTooltip, { active: !!tooltipData, position: tooltipData
                    ? { x: tooltipData.x, y: tooltipData.y }
                    : { x: 0, y: 0 }, tooltipRef: tooltipRef, content: tooltipData === null || tooltipData === void 0 ? void 0 : tooltipData.content }))] }));
};
RadarChart.displayName = "RadarChart";

export { RadarChart };
