import { jsx, jsxs } from 'react/jsx-runtime';
import { useRef, useState, useEffect, useMemo, useCallback } from 'react';
import { motion } from 'motion/react';
import { cn } from '../../../utils/cn.js';
import { useTooltipPosition } from '../hooks/useTooltipPosition.js';
import { useChartAccessibility } from '../hooks/useChartAccessibility.js';
import { XAxis } from '../shared/ChartAxis/XAxis.js';
import { YAxis } from '../shared/ChartAxis/YAxis.js';
import { ChartTooltip } from '../shared/ChartTooltip/ChartTooltip.js';
import { SCATTER_PLOT_DEFAULTS } from './ScatterPlot.types.js';
import { getCategoryColor, scatterPlotTheme } from './ScatterPlot.theme.js';

/**
 * ScatterPlot Component
 *
 * Displays correlation between two variables with optional bubble sizing.
 * Now uses shared axis components with tick marks and value labels like other charts.
 */
const ScatterPlot = ({ data, xLabel, yLabel, dotRadius: propDotRadius, pointSize, // @deprecated
showGrid = SCATTER_PLOT_DEFAULTS.showGrid, showXAxis = SCATTER_PLOT_DEFAULTS.showXAxis, showYAxis = SCATTER_PLOT_DEFAULTS.showYAxis, showTooltip = SCATTER_PLOT_DEFAULTS.showTooltip, colors, minValue: propMinValue, maxValue: propMaxValue, theme: themeOverrides, className, svgClassName, dotClassName, gridClassName, axisClassName, title, description, enableKeyboardNavigation = SCATTER_PLOT_DEFAULTS.enableKeyboardNavigation, ...props }) => {
    var _a;
    const theme = { ...scatterPlotTheme, ...(themeOverrides || {}) };
    const chartColors = colors || theme.colors || scatterPlotTheme.colors;
    // Use dotRadius, fallback to pointSize for backward compatibility
    const dotRadiusValue = (_a = propDotRadius !== null && propDotRadius !== void 0 ? propDotRadius : pointSize) !== null && _a !== void 0 ? _a : SCATTER_PLOT_DEFAULTS.dotRadius;
    // Responsive container dimensions
    const containerRef = useRef(null);
    const [dimensions, setDimensions] = useState({ width: 600, height: 400 });
    // Update dimensions on mount and resize
    useEffect(() => {
        if (!containerRef.current)
            return;
        const updateDimensions = () => {
            if (containerRef.current) {
                const rect = containerRef.current.getBoundingClientRect();
                setDimensions({
                    width: rect.width || 600,
                    height: rect.height || 400,
                });
            }
        };
        // Initial measurement
        updateDimensions();
        // Setup ResizeObserver
        const resizeObserver = new ResizeObserver(updateDimensions);
        resizeObserver.observe(containerRef.current);
        return () => {
            resizeObserver.disconnect();
        };
    }, []);
    // Calculate ranges and categories
    const { xMin, xMax, yMin, yMax, categories, validData } = useMemo(() => {
        // Filter out invalid data points
        const valid = data.filter((d) => typeof d.x === 'number' &&
            typeof d.y === 'number' &&
            !isNaN(d.x) &&
            !isNaN(d.y) &&
            isFinite(d.x) &&
            isFinite(d.y));
        if (valid.length === 0) {
            return {
                xMin: propMinValue !== null && propMinValue !== void 0 ? propMinValue : 0,
                xMax: propMaxValue !== null && propMaxValue !== void 0 ? propMaxValue : 100,
                yMin: propMinValue !== null && propMinValue !== void 0 ? propMinValue : 0,
                yMax: propMaxValue !== null && propMaxValue !== void 0 ? propMaxValue : 100,
                categories: [],
                validData: [],
            };
        }
        const xValues = valid.map((d) => d.x);
        const yValues = valid.map((d) => d.y);
        const cats = Array.from(new Set(valid.map((d) => d.category).filter(Boolean)));
        const minX = propMinValue !== null && propMinValue !== void 0 ? propMinValue : Math.min(...xValues);
        const maxX = propMaxValue !== null && propMaxValue !== void 0 ? propMaxValue : Math.max(...xValues);
        const minY = propMinValue !== null && propMinValue !== void 0 ? propMinValue : Math.min(...yValues);
        const maxY = propMaxValue !== null && propMaxValue !== void 0 ? propMaxValue : Math.max(...yValues);
        return {
            xMin: minX,
            xMax: maxX === minX ? minX + 1 : maxX, // Avoid same min/max
            yMin: minY,
            yMax: maxY === minY ? minY + 1 : maxY, // Avoid same min/max
            categories: cats,
            validData: valid,
        };
    }, [data, propMinValue, propMaxValue]);
    // Chart dimensions with margins (pixel-based like other charts)
    const margin = {
        top: 20,
        right: 20,
        bottom: showXAxis ? 60 : 20,
        left: showYAxis ? 60 : 20,
    };
    const innerWidth = dimensions.width - margin.left - margin.right;
    const innerHeight = dimensions.height - margin.top - margin.bottom;
    // Scale functions (pixel-based)
    const scaleX = useCallback((value) => {
        const ratio = (value - xMin) / (xMax - xMin);
        return margin.left + ratio * innerWidth;
    }, [xMin, xMax, margin.left, innerWidth]);
    const scaleY = useCallback((value) => {
        const ratio = (value - yMin) / (yMax - yMin);
        return margin.top + innerHeight - ratio * innerHeight;
    }, [yMin, yMax, margin.top, innerHeight]);
    // Get color for category
    const getColor = (category) => {
        if (!category)
            return chartColors[0];
        const index = categories.indexOf(category);
        return getCategoryColor(chartColors, index);
    };
    // Tooltip setup
    const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
    const { tooltipData, tooltipRef, handleMouseEnter, handleMouseMove, handleMouseLeave, } = useTooltipPosition({
        containerRef,
        isMobile,
    });
    // Accessibility setup (create config from data for accessibility)
    const config = useMemo(() => {
        const configObj = {};
        categories.forEach((cat, idx) => {
            configObj[cat] = {
                label: cat,
                color: getCategoryColor(chartColors, idx),
            };
        });
        return configObj;
    }, [categories, chartColors]);
    const chartDataForAccessibility = useMemo(() => {
        return validData.map((point) => ({
            category: point.category || 'Point',
            x: point.x,
            y: point.y,
            size: point.size,
            label: point.label,
        }));
    }, [validData]);
    const { chartAccessibilityProps, descriptionProps, handleMouseInteraction, } = useChartAccessibility({
        chartType: 'scatter',
        data: chartDataForAccessibility,
        config,
        title,
        description,
        enableKeyboardNavigation,
    });
    // Generate X-axis data for axis component
    const xAxisData = useMemo(() => {
        // Create tick marks for X axis
        const tickCount = 5;
        const range = xMax - xMin;
        const step = range / (tickCount - 1);
        return Array.from({ length: tickCount }, (_, i) => ({
            name: (xMin + i * step).toFixed(0),
            value: xMin + i * step,
        }));
    }, [xMin, xMax]);
    // Return empty state if no data
    if (validData.length === 0) {
        return (jsx("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: { minHeight: '400px' }, ...props, children: jsx("div", { className: theme.emptyStateStyle, children: data.length === 0 ? 'No data available' : 'No valid data points' }) }));
    }
    return (jsxs("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: { minHeight: '400px' }, ...chartAccessibilityProps, ...props, children: [jsxs("svg", { width: dimensions.width, height: dimensions.height, className: cn(theme.svgStyle, svgClassName), ...descriptionProps, children: [jsx(YAxis, { show: showYAxis, min: yMin, max: yMax, x: margin.left, y: margin.top, height: innerHeight, showGrid: showGrid, gridWidth: innerWidth, tickCount: 5, className: cn(axisClassName) }), validData.map((point, index) => {
                        const cx = scaleX(point.x);
                        const cy = scaleY(point.y);
                        const size = point.size ? Math.sqrt(point.size) / 2 : dotRadiusValue;
                        const pointColor = getColor(point.category);
                        return (jsx(motion.circle, { cx: cx, cy: cy, r: size, fill: pointColor, className: cn(theme.dotStyle, dotClassName), strokeWidth: "0.5", initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, transition: { delay: index * 0.01, duration: 0.3 }, whileHover: { scale: 1.5, opacity: 1 }, onMouseEnter: (e) => {
                                if (showTooltip) {
                                    const content = {
                                        category: point.label || point.category || `Point ${index + 1}`,
                                        series: [
                                            {
                                                key: 'x',
                                                label: xLabel || 'X',
                                                value: point.x.toFixed(2),
                                                color: pointColor,
                                            },
                                            {
                                                key: 'y',
                                                label: yLabel || 'Y',
                                                value: point.y.toFixed(2),
                                                color: pointColor,
                                            },
                                            ...(point.size
                                                ? [
                                                    {
                                                        key: 'size',
                                                        label: 'Size',
                                                        value: point.size.toFixed(2),
                                                        color: pointColor,
                                                    },
                                                ]
                                                : []),
                                        ],
                                    };
                                    // Pass SVG coordinates for proper positioning (especially in mobile/constrained containers)
                                    const svgCoordinates = isMobile ? {
                                        x: cx,
                                        y: cy,
                                        dimensions
                                    } : undefined;
                                    handleMouseEnter(e, content, svgCoordinates);
                                }
                                handleMouseInteraction();
                            }, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave }, index));
                    }), jsx(XAxis, { show: showXAxis, data: xAxisData, x: margin.left, y: margin.top + innerHeight, width: innerWidth, categoryWidth: innerWidth / (xAxisData.length - 1), categoryGap: 0, alignWithEdge: true, className: cn(axisClassName) }), xLabel && showXAxis && (jsx("text", { x: margin.left + innerWidth / 2, y: dimensions.height - 5, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", children: xLabel })), yLabel && showYAxis && (jsx("text", { x: 15, y: margin.top + innerHeight / 2, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", transform: `rotate(-90 15 ${margin.top + innerHeight / 2})`, children: yLabel }))] }), categories.length > 0 && (jsx("div", { className: theme.legendContainerStyle, children: categories.map((cat, index) => (jsxs("div", { className: theme.legendItemStyle, children: [jsx("div", { className: theme.legendDotStyle, style: { backgroundColor: getCategoryColor(chartColors, index) } }), jsx("span", { className: theme.legendLabelStyle, children: cat })] }, cat))) })), 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, chartType: "scatter" }))] }));
};
ScatterPlot.displayName = 'ScatterPlot';

export { ScatterPlot };
