import { jsx, jsxs } from 'react/jsx-runtime';
import { useContext, createContext, useState, useCallback, useMemo } from 'react';
import { cn } from '../../../utils/cn.js';
import { ganttChartTheme } from './GanttChart.theme.js';
import { useGanttDates } from './hooks/useGanttDates.js';
import { useGanttLayout } from './hooks/useGanttLayout.js';
import { useGanttScrollSync } from './hooks/useGanttScrollSync.js';
import { GanttToolbar } from './GanttToolbar.js';
import { GanttTablePanel } from './GanttTablePanel.js';
import { GanttChartPanel } from './GanttChartPanel.js';
import { GanttSplitter } from './GanttSplitter.js';
import { formatDuration } from './GanttChart.utils.js';
import { GanttProgressCircle } from './GanttProgressCircle.js';

// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------
const GanttContext = createContext(undefined);
const GanttInteractionContext = createContext(undefined);
function useGanttContext() {
    const ctx = useContext(GanttContext);
    if (!ctx) {
        throw new Error("useGanttContext must be used within <GanttChart>");
    }
    return ctx;
}
function useGanttInteraction() {
    const ctx = useContext(GanttInteractionContext);
    if (!ctx) {
        throw new Error("useGanttInteraction must be used within <GanttChart>");
    }
    return ctx;
}
// ---------------------------------------------------------------------------
// Default columns
// ---------------------------------------------------------------------------
const defaultColumns = [
    {
        id: "title",
        header: "Task",
        accessor: "title",
        width: 200,
    },
    {
        id: "duration",
        header: "Duration",
        accessor: (task) => formatDuration(task.startDate, task.endDate),
        width: 70,
        align: "center",
    },
    {
        id: "progress",
        header: "Status",
        accessor: "progress",
        cell: (task, group) => {
            var _a;
            return (jsx(GanttProgressCircle, { progress: task.progress, color: (_a = task.color) !== null && _a !== void 0 ? _a : group.color, size: 20 }));
        },
        width: 56,
        align: "center",
    },
];
// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
function GanttChartComponent({ data, groups, columns, startDate, endDate, todayMarker = true, scrollToToday = true, readonly: readonlyProp = false, readonlyDates: readonlyDatesProp = false, readonlyProgress: readonlyProgressProp = false, zoom: zoomProp, defaultZoom = "day", onZoomChange, collapsedGroups: collapsedProp, defaultCollapsedGroups = [], onCollapsedGroupsChange, hideCompleted: hideCompletedProp, defaultHideCompleted = false, onHideCompletedChange, tablePanelWidth: tablePanelWidthProp, defaultTablePanelWidth = 400, onTablePanelWidthChange, onTaskUpdate, onTaskDelete, onTaskDuplicate, onTaskAdd, onGroupAdd, onTaskClick, holidays: holidaysProp = [], gridLines = "both", className, theme: themeOverrides, rowHeight = 40, }) {
    // ----- Controlled / uncontrolled state -----
    const [uncontrolledZoom, setUncontrolledZoom] = useState(defaultZoom);
    const isZoomControlled = zoomProp !== undefined;
    const zoom = isZoomControlled ? zoomProp : uncontrolledZoom;
    const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState(defaultCollapsedGroups);
    const isCollapsedControlled = collapsedProp !== undefined;
    const collapsedGroups = isCollapsedControlled ? collapsedProp : uncontrolledCollapsed;
    const [uncontrolledHide, setUncontrolledHide] = useState(defaultHideCompleted);
    const isHideControlled = hideCompletedProp !== undefined;
    const hideCompleted = isHideControlled ? hideCompletedProp : uncontrolledHide;
    const [uncontrolledWidth, setUncontrolledWidth] = useState(defaultTablePanelWidth);
    const isWidthControlled = tablePanelWidthProp !== undefined;
    const tablePanelWidth = isWidthControlled ? tablePanelWidthProp : uncontrolledWidth;
    // ----- Hover / focus / drag state -----
    const [hoveredTaskId, setHoveredTaskId] = useState(null);
    const [focusedTaskId, setFocusedTaskId] = useState(null);
    const [activeDrag, setActiveDrag] = useState(null);
    // ----- Handlers -----
    const setZoom = useCallback((val) => {
        if (!isZoomControlled)
            setUncontrolledZoom(val);
        onZoomChange === null || onZoomChange === void 0 ? void 0 : onZoomChange(val);
    }, [isZoomControlled, onZoomChange]);
    const toggleGroup = useCallback((groupId) => {
        const next = collapsedGroups.includes(groupId)
            ? collapsedGroups.filter((id) => id !== groupId)
            : [...collapsedGroups, groupId];
        if (!isCollapsedControlled)
            setUncontrolledCollapsed(next);
        onCollapsedGroupsChange === null || onCollapsedGroupsChange === void 0 ? void 0 : onCollapsedGroupsChange(next);
    }, [collapsedGroups, isCollapsedControlled, onCollapsedGroupsChange]);
    const setHideCompleted = useCallback((val) => {
        if (!isHideControlled)
            setUncontrolledHide(val);
        onHideCompletedChange === null || onHideCompletedChange === void 0 ? void 0 : onHideCompletedChange(val);
    }, [isHideControlled, onHideCompletedChange]);
    const setTablePanelWidth = useCallback((val) => {
        if (!isWidthControlled)
            setUncontrolledWidth(val);
        onTablePanelWidthChange === null || onTablePanelWidthChange === void 0 ? void 0 : onTablePanelWidthChange(val);
    }, [isWidthControlled, onTablePanelWidthChange]);
    // ----- Derived data -----
    const resolvedColumns = columns !== null && columns !== void 0 ? columns : defaultColumns;
    const dates = useGanttDates(data, zoom, startDate, endDate);
    const rows = useGanttLayout(groups, data, collapsedGroups, hideCompleted);
    const { tableRef, chartRef, handleTableScroll, handleChartScroll } = useGanttScrollSync();
    const theme = useMemo(() => ({ ...ganttChartTheme, ...(themeOverrides || {}) }), [themeOverrides]);
    // ----- Context -----
    const contextValue = useMemo(() => ({
        groups,
        tasks: data,
        columns: resolvedColumns,
        rows,
        rangeStart: dates.rangeStart,
        rangeEnd: dates.rangeEnd,
        totalDays: dates.totalDays,
        dayWidth: dates.dayWidth,
        zoom,
        collapsedGroups,
        hideCompleted,
        tablePanelWidth,
        readonly: readonlyProp,
        readonlyDates: readonlyDatesProp,
        readonlyProgress: readonlyProgressProp,
        onTaskUpdate,
        onTaskDelete,
        onTaskDuplicate,
        onTaskAdd,
        onGroupAdd,
        onTaskClick,
        toggleGroup,
        setZoom,
        setHideCompleted,
        setTablePanelWidth,
        theme,
        todayMarker,
        todayOffset: dates.todayOffset,
        scrollToToday,
        holidays: holidaysProp,
        gridLines,
        rowHeight,
    }), [
        groups, data, resolvedColumns, rows, dates, zoom, collapsedGroups,
        hideCompleted, tablePanelWidth, readonlyProp, readonlyDatesProp,
        readonlyProgressProp, onTaskUpdate, onTaskDelete, onTaskDuplicate,
        onTaskAdd, onGroupAdd, onTaskClick, toggleGroup, setZoom,
        setHideCompleted, setTablePanelWidth,
        theme, todayMarker, scrollToToday, holidaysProp, gridLines, rowHeight,
    ]);
    // Interaction state changes frequently (hover, focus, drag) — kept in a
    // separate context so that stable consumers don't re-render.
    const interactionValue = useMemo(() => ({
        hoveredTaskId,
        setHoveredTaskId,
        focusedTaskId,
        setFocusedTaskId,
        activeDrag,
        setActiveDrag,
    }), [hoveredTaskId, focusedTaskId, activeDrag]);
    return (jsx(GanttContext.Provider, { value: contextValue, children: jsx(GanttInteractionContext.Provider, { value: interactionValue, children: jsxs("div", { className: cn(theme.baseStyle, className), children: [jsx(GanttToolbar, {}), jsxs("div", { className: "flex flex-1 min-h-0 overflow-x-auto", children: [jsx(GanttTablePanel, { ref: tableRef, onScroll: handleTableScroll }), jsx(GanttSplitter, {}), jsx(GanttChartPanel, { ref: chartRef, onScroll: handleChartScroll, days: dates.days, monthSpans: dates.monthSpans })] })] }) }) }));
}
GanttChartComponent.displayName = "GanttChart";

export { GanttChartComponent as GanttChart, useGanttContext, useGanttInteraction };
