import { jsx, jsxs } from 'react/jsx-runtime';
import { useRef, useState, useId, 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 { HorizontalGrid } from '../shared/ChartGrid/HorizontalGrid.js';
import { ChartTooltip } from '../shared/ChartTooltip/ChartTooltip.js';
import { ChartMarker } from '../shared/ChartMarker/ChartMarker.js';
import { ChartCrosshair } from '../shared/ChartCrosshair/ChartCrosshair.js';
import { generateNiceTicks } from '../utils/chart-validation.js';
import { generateCurvePath } from '../utils/path-utils.js';
import { LINE_CHART_DEFAULTS } from './LineChart.types.js';

// Production-ready color system with CORRECT CSS variable syntax
const getSeriesColorClass = (index) => {
    const colors = [
        "stroke-[var(--color-primary)]",
        "stroke-[var(--color-warning)]",
        "stroke-[var(--color-success)]",
        "stroke-[var(--color-danger)]",
    ];
    return colors[index % colors.length];
};
// Get color value for SVG elements and tooltips
const getSeriesFillColor = (index) => {
    const colorVars = [
        "var(--color-primary)",
        "var(--color-warning)",
        "var(--color-success)",
        "var(--color-danger)",
    ];
    return colorVars[index % colorVars.length];
};
const LineChart = ({ data, config, 
// Standardized display props with defaults
showGrid = LINE_CHART_DEFAULTS.showGrid, showXAxis = LINE_CHART_DEFAULTS.showXAxis, showYAxis = LINE_CHART_DEFAULTS.showYAxis, minValue: propMinValue, maxValue: propMaxValue, 
// Simple semantic color prop
color = LINE_CHART_DEFAULTS.color, 
// Standardized visual props with defaults (renamed from line-specific names)
dotRadius, radius, // @deprecated Use dotRadius instead
strokeWidth = LINE_CHART_DEFAULTS.strokeWidth, curved = LINE_CHART_DEFAULTS.curved, curveType = LINE_CHART_DEFAULTS.curveType, showDots = LINE_CHART_DEFAULTS.showDots, 
// Base props
className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.enableKeyboardNavigation, children, ...props }) => {
    var _a;
    // Resolve dotRadius with backward compatibility
    const resolvedDotRadius = (_a = dotRadius !== null && dotRadius !== void 0 ? dotRadius : radius) !== null && _a !== void 0 ? _a : LINE_CHART_DEFAULTS.dotRadius;
    // Development warning for deprecated radius prop
    if (process.env.NODE_ENV !== "production" && radius !== undefined) {
        console.warn("[LineChart]: The `radius` prop is deprecated and will be removed in a future version. " +
            "Use `dotRadius` instead.");
    }
    // Simplified color system - no complex theme hook needed
    const containerRef = useRef(null);
    const [dimensions, setDimensions] = useState({ width: 600, height: 400 });
    const revealClipId = useId();
    const shadowFilterId = useId();
    const verticalFadeId = useId();
    const horizontalFadeId = useId();
    const ANIMATION_DURATION = 1.5;
    const [hoveredPoint, setHoveredPoint] = useState(null);
    // Detect if device is mobile/touch
    const isMobile = typeof window !== "undefined" &&
        ("ontouchstart" in window || navigator.maxTouchPoints > 0);
    // Use the new tooltip positioning hook
    const { tooltipData, tooltipRef, handleMouseEnter, handleMouseMove, handleMouseLeave, } = useTooltipPosition({
        containerRef,
        isMobile,
    });
    // Use accessibility hook
    const { chartAccessibilityProps, descriptionProps, focusedElementIndex, isKeyboardMode, handleMouseInteraction, } = useChartAccessibility({
        chartType: "line",
        data,
        config,
        title,
        description,
        enableKeyboardNavigation,
    });
    // Measure container dimensions
    useEffect(() => {
        const updateDimensions = () => {
            if (containerRef.current) {
                const { width, height } = containerRef.current.getBoundingClientRect();
                setDimensions({
                    width: width || 600,
                    height: height || 400,
                });
            }
        };
        updateDimensions();
        const resizeObserver = new ResizeObserver(updateDimensions);
        if (containerRef.current) {
            resizeObserver.observe(containerRef.current);
        }
        return () => {
            resizeObserver.disconnect();
        };
    }, []);
    // Early return if no data
    if (!data || data.length === 0) {
        return (jsx("div", { className: cn("chart-container flex items-center justify-center text-[var(--color-text-placeholder)]", className), role: "img", "aria-label": "Empty line chart", ...props, children: jsx("span", { children: "No data available" }) }));
    }
    // Calculate dimensions
    const margin = useMemo(() => ({
        top: 0,
        right: 0,
        bottom: showXAxis ? 40 : 0, // Reduce bottom margin when X-axis is hidden
        left: showYAxis ? 60 : 0, // Reduce left margin when Y-axis is hidden
    }), [showXAxis, showYAxis]);
    const innerWidth = dimensions.width - margin.left - margin.right;
    const innerHeight = dimensions.height - margin.top - margin.bottom;
    // Get all data keys from config
    const dataKeys = useMemo(() => Object.keys(config), [config]);
    // Calculate scales
    const { minValue, maxValue } = useMemo(() => {
        const rawMaxValue = Math.max(...data.map((item) => Math.max(...dataKeys.map((key) => {
            const value = item[key];
            return typeof value === "number" ? value : 0;
        }))));
        const rawMinValue = Math.min(...data.map((item) => Math.min(...dataKeys.map((key) => {
            const value = item[key];
            return typeof value === "number" ? value : 0;
        }))));
        // Compute nice axis boundaries using Heckbert's algorithm
        const dataMinWithZero = Math.min(rawMinValue, 0);
        const dataMaxWithZero = Math.max(rawMaxValue, 0);
        const { niceMin, niceMax } = generateNiceTicks(dataMinWithZero, dataMaxWithZero, 5);
        return {
            minValue: propMinValue !== null && propMinValue !== void 0 ? propMinValue : niceMin,
            maxValue: propMaxValue !== null && propMaxValue !== void 0 ? propMaxValue : niceMax,
        };
    }, [data, dataKeys, propMinValue, propMaxValue]);
    // Calculate point position
    const getPointPosition = useCallback((dataIndex, value) => {
        // Spread points evenly across the full width
        // First point at left edge (margin.left), last point at right edge (margin.left + innerWidth)
        const x = data.length === 1
            ? margin.left + innerWidth / 2 // Center single point
            : margin.left + (dataIndex / (data.length - 1)) * innerWidth;
        const y = margin.top +
            innerHeight -
            ((value - minValue) / (maxValue - minValue)) * innerHeight;
        return { x, y };
    }, [data.length, margin.left, margin.top, innerWidth, innerHeight, minValue, maxValue]);
    // Precompute all line paths
    const allPaths = useMemo(() => {
        const result = {};
        dataKeys.forEach((key) => {
            const segments = [];
            let currentSegment = [];
            data.forEach((item, index) => {
                const rawValue = item[key];
                const isNull = rawValue === null || rawValue === undefined;
                if (isNull) {
                    if (currentSegment.length > 0) {
                        segments.push(currentSegment);
                        currentSegment = [];
                    }
                }
                else {
                    const value = typeof rawValue === "number" ? rawValue : 0;
                    const { x, y } = getPointPosition(index, value);
                    currentSegment.push({ x, y });
                }
            });
            if (currentSegment.length > 0) {
                segments.push(currentSegment);
            }
            result[key] = segments
                .map((segment) => generateCurvePath(segment, curved ? curveType : "linear"))
                .join(" ");
        });
        return result;
    }, [data, dataKeys, curved, curveType, getPointPosition]);
    // Handle keyboard focus tooltips
    useEffect(() => {
        if (isKeyboardMode &&
            focusedElementIndex >= 0 &&
            focusedElementIndex < data.length) {
            const item = data[focusedElementIndex];
            // Create multi-series tooltip data
            const seriesData = dataKeys.map((seriesKey, keyIndex) => {
                var _a, _b;
                const seriesValue = item[seriesKey];
                const numValue = typeof seriesValue === "number" ? seriesValue : 0;
                return {
                    key: seriesKey,
                    label: ((_a = config[seriesKey]) === null || _a === void 0 ? void 0 : _a.label) || seriesKey,
                    value: numValue,
                    color: ((_b = config[seriesKey]) === null || _b === void 0 ? void 0 : _b.color) || getSeriesFillColor(keyIndex),
                };
            });
            const content = {
                category: item.name || `Category ${focusedElementIndex + 1}`,
                series: seriesData,
            };
            // Calculate position for focused point
            const pointX = data.length === 1
                ? margin.left + innerWidth / 2
                : margin.left +
                    (focusedElementIndex / (data.length - 1)) * innerWidth;
            const svgCoordinates = {
                x: pointX,
                y: margin.top + innerHeight / 2,
                dimensions,
            };
            // Simulate mouse enter for keyboard focus
            const syntheticEvent = new MouseEvent("mouseenter", {
                clientX: pointX,
                clientY: margin.top + innerHeight / 2,
            });
            handleMouseEnter(syntheticEvent, content, svgCoordinates);
        }
        else if (isKeyboardMode && focusedElementIndex === -1) {
            // Only clear tooltip when explicitly exiting keyboard mode (Escape key)
            handleMouseLeave();
        }
        // Don't clear tooltips when switching from keyboard to mouse mode
    }, [
        isKeyboardMode,
        focusedElementIndex,
        data,
        config,
        dimensions,
        margin,
        innerWidth,
        innerHeight,
        dataKeys,
        handleMouseEnter,
        handleMouseLeave,
    ]);
    return (jsxs("div", { ref: containerRef, className: cn("chart-container w-full h-full", className), ...chartAccessibilityProps, onMouseEnter: handleMouseInteraction, onMouseMove: handleMouseInteraction, ...props, children: [descriptionProps && jsx("div", { ...descriptionProps }), jsxs("svg", { width: "100%", height: "100%", viewBox: `0 0 ${dimensions.width} ${dimensions.height}`, className: "overflow-visible", role: "presentation", children: [jsxs("defs", { children: [jsx("filter", { id: shadowFilterId, x: "-20%", y: "-20%", width: "140%", height: "140%", children: jsx("feDropShadow", { dx: "8", dy: "8", stdDeviation: "8", floodOpacity: "0.15", floodColor: "#000000" }) }), jsxs("linearGradient", { id: verticalFadeId, x1: "0%", y1: "0%", x2: "0%", y2: "100%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] }), jsxs("linearGradient", { id: horizontalFadeId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] }), jsx("clipPath", { id: revealClipId, children: jsx(motion.rect, { initial: { width: 0, x: margin.left, y: margin.top }, animate: {
                                        width: innerWidth + margin.right,
                                        x: margin.left,
                                        y: margin.top,
                                    }, height: innerHeight, transition: {
                                        duration: ANIMATION_DURATION,
                                        ease: "easeOut",
                                    } }) })] }), jsx(HorizontalGrid, { show: showGrid, x: margin.left, y: margin.top, width: innerWidth, height: innerHeight, lineCount: 5 }), jsx(ChartCrosshair, { show: hoveredPoint !== null, x: hoveredPoint !== null
                            ? data.length === 1
                                ? margin.left + innerWidth / 2
                                : margin.left +
                                    (hoveredPoint.index / (data.length - 1)) * innerWidth
                            : 0, y: hoveredPoint !== null && dataKeys.length === 1
                            ? (() => {
                                const item = data[hoveredPoint.index];
                                const singleKey = dataKeys[0];
                                const singleValue = item[singleKey];
                                const numValue = typeof singleValue === "number" ? singleValue : 0;
                                return (margin.top +
                                    innerHeight -
                                    ((numValue - minValue) / (maxValue - minValue)) *
                                        innerHeight);
                            })()
                            : undefined, margin: margin, innerWidth: innerWidth, innerHeight: innerHeight, showHorizontal: dataKeys.length === 1 }), jsx(YAxis, { show: showYAxis, min: minValue, max: maxValue, x: margin.left, y: margin.top, height: innerHeight, showGrid: false, gridWidth: innerWidth, tickFormatter: (value) => {
                            if (Math.abs(value) >= 1000)
                                return `${(value / 1000).toFixed(0)}k`;
                            return value.toString();
                        } }), minValue < 0 && maxValue > 0 && (jsx("line", { x1: margin.left, y1: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, x2: margin.left + innerWidth, y2: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, className: "stroke-[var(--color-text-secondary)]", strokeWidth: 1, opacity: 0.6 })), jsx("g", { className: "chart-lines", children: dataKeys.map((key, keyIndex) => {
                            const targetPath = allPaths[key];
                            const colorClass = getSeriesColorClass(keyIndex);
                            return (jsxs("g", { clipPath: `url(#${revealClipId})`, children: [jsx("path", { d: targetPath, fill: "none", strokeWidth: strokeWidth, strokeLinecap: "round", className: cn("transition-all duration-200", colorClass), filter: `url(#${shadowFilterId})` }), showDots &&
                                        data.map((item, dataIndex) => {
                                            const rawValue = item[key];
                                            const isNull = rawValue === null || rawValue === undefined;
                                            const value = isNull
                                                ? 0
                                                : typeof rawValue === "number"
                                                    ? rawValue
                                                    : 0;
                                            // Don't render dots for null values
                                            if (isNull)
                                                return null;
                                            const { x, y } = getPointPosition(dataIndex, value);
                                            const isFocused = isKeyboardMode && focusedElementIndex === dataIndex;
                                            return (jsx(motion.g, { initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: {
                                                    // Sync with the line reveal: calculate when the line reaches this point
                                                    delay: (dataIndex / (data.length - 1)) *
                                                        ANIMATION_DURATION,
                                                    type: "spring",
                                                    stiffness: 260,
                                                    damping: 20,
                                                }, style: {
                                                    originX: "50%",
                                                    originY: "50%",
                                                    transformBox: "fill-box",
                                                }, children: jsx(ChartMarker, { cx: x, cy: y, radius: isFocused
                                                        ? resolvedDotRadius + 2
                                                        : resolvedDotRadius, colorClass: cn(colorClass, isFocused &&
                                                        "stroke-[var(--color-primary-600)] stroke-2") }) }, `${key}-${dataIndex}`));
                                        })] }, key));
                        }) }), !showDots && hoveredPoint !== null && (jsx("g", { className: "chart-hover-markers", children: dataKeys.map((key, keyIndex) => {
                            const item = data[hoveredPoint.index];
                            const rawValue = item[key];
                            const isNull = rawValue === null || rawValue === undefined;
                            const value = isNull
                                ? 0
                                : typeof rawValue === "number"
                                    ? rawValue
                                    : 0;
                            // Don't render hover markers for null values
                            if (isNull)
                                return null;
                            const { x, y } = getPointPosition(hoveredPoint.index, value);
                            const colorClass = getSeriesColorClass(keyIndex);
                            return (jsx(ChartMarker, { cx: x, cy: y, radius: resolvedDotRadius, colorClass: colorClass }, `hover-${key}-${hoveredPoint.index}`));
                        }) })), jsx("g", { className: "chart-hover-areas", children: data.map((item, dataIndex) => {
                            // Calculate hover area based on new point positioning
                            const pointX = data.length === 1
                                ? margin.left + innerWidth / 2
                                : margin.left + (dataIndex / (data.length - 1)) * innerWidth;
                            // Create hover area around each point
                            const hoverWidth = data.length === 1 ? innerWidth : innerWidth / (data.length - 1);
                            const hoverX = data.length === 1
                                ? margin.left
                                : Math.max(margin.left, pointX - hoverWidth / 2);
                            // Ensure hover area doesn't exceed chart bounds
                            const adjustedWidth = data.length === 1
                                ? innerWidth
                                : Math.min(hoverWidth, margin.left + innerWidth - hoverX);
                            return (jsx("rect", { x: hoverX, y: margin.top, width: adjustedWidth, height: innerHeight, fill: "transparent", className: "cursor-pointer", onMouseEnter: (e) => {
                                    setHoveredPoint({ index: dataIndex, key: dataKeys[0] });
                                    // Create multi-series tooltip data
                                    const seriesData = dataKeys.map((seriesKey, keyIndex) => {
                                        var _a, _b;
                                        const seriesValue = item[seriesKey];
                                        const numValue = typeof seriesValue === "number" ? seriesValue : 0;
                                        return {
                                            key: seriesKey,
                                            label: ((_a = config[seriesKey]) === null || _a === void 0 ? void 0 : _a.label) || seriesKey,
                                            value: numValue,
                                            color: ((_b = config[seriesKey]) === null || _b === void 0 ? void 0 : _b.color) ||
                                                getSeriesFillColor(keyIndex),
                                        };
                                    });
                                    const content = {
                                        category: item.name || `Category ${dataIndex + 1}`,
                                        series: seriesData,
                                    };
                                    const svgCoordinates = {
                                        x: pointX,
                                        y: margin.top + innerHeight / 2,
                                        dimensions,
                                    };
                                    handleMouseEnter(e, content, svgCoordinates);
                                }, onMouseMove: (e) => {
                                    if ((hoveredPoint === null || hoveredPoint === void 0 ? void 0 : hoveredPoint.index) === dataIndex) {
                                        const svgCoordinates = {
                                            x: pointX,
                                            y: margin.top + innerHeight / 2,
                                            dimensions,
                                        };
                                        handleMouseMove(e, svgCoordinates);
                                    }
                                }, onMouseLeave: handleMouseLeave }, `hover-${dataIndex}`));
                        }) }), jsx(XAxis, { show: showXAxis, data: data, x: margin.left, y: margin.top + innerHeight, width: innerWidth, categoryWidth: innerWidth / data.length, categoryGap: 0, alignWithEdge: true })] }), 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: "line" }), children] }));
};

export { LineChart };
