import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import React__default, { useState, useCallback, useMemo } from 'react';
import { motion } from 'motion/react';
import { cn } from '../../../utils/cn.js';
import { useGanttContext, useGanttInteraction } from './GanttChart.js';
import { getDayOffset, calculateExpectedProgress, formatDateShort, formatDuration } from './GanttChart.utils.js';
import { ChartTooltip } from '../../charts/shared/ChartTooltip/ChartTooltip.js';
import { Avatar } from '../../core/Avatar/Avatar.js';
import { GanttTaskContextMenu } from './GanttTaskContextMenu.js';
import { taskBarVariants } from './GanttChart.animations.js';
import { useGanttDrag } from './hooks/useGanttDrag.js';
import { getDaysBetween, addDays, toDate } from '../../../utils/dateUtils.js';

const GanttTaskBar = React__default.memo(({ task, group, top }) => {
    var _a;
    const { theme, dayWidth, rangeStart, rowHeight, readonly, readonlyDates, readonlyProgress, onTaskUpdate, onTaskClick, tasks, } = useGanttContext();
    const { hoveredTaskId, setHoveredTaskId, focusedTaskId, setActiveDrag } = useGanttInteraction();
    const [tooltipPos, setTooltipPos] = useState(null);
    const offset = getDayOffset(task.startDate, rangeStart);
    const span = getDaysBetween(task.startDate, task.endDate);
    const left = offset * dayWidth;
    const width = Math.max(span * dayWidth, dayWidth);
    const barColor = (_a = task.color) !== null && _a !== void 0 ? _a : group.color;
    const barHeight = rowHeight - 8;
    const canDragDates = !readonly && !readonlyDates && !!onTaskUpdate;
    const canDragProgress = !readonly && !readonlyProgress && !!onTaskUpdate;
    const expectedProgress = calculateExpectedProgress(task.startDate, task.endDate);
    const isBehindSchedule = !task.completed && task.progress < expectedProgress;
    // ----- Drag: Move -----
    const handleMoveDragEnd = useCallback((result) => {
        if (!onTaskUpdate || result.daysDelta === 0)
            return;
        const newStart = addDays(task.startDate, result.daysDelta);
        const newEnd = addDays(task.endDate, result.daysDelta);
        onTaskUpdate(task.id, {
            startDate: newStart,
            endDate: newEnd,
        });
    }, [onTaskUpdate, task.id, task.startDate, task.endDate]);
    const moveDrag = useGanttDrag({
        dayWidth,
        mode: "move",
        barWidthPx: width,
        originalProgress: task.progress,
        disabled: !canDragDates,
        onDragEnd: handleMoveDragEnd,
        onDragStateChange: useCallback((isDragging, deltaX) => {
            setActiveDrag(isDragging ? { taskId: task.id, mode: "move", deltaX } : null);
        }, [setActiveDrag, task.id]),
    });
    // ----- Drag: Resize left -----
    const handleResizeLeftEnd = useCallback((result) => {
        if (!onTaskUpdate || result.daysDelta === 0)
            return;
        const newStart = addDays(task.startDate, result.daysDelta);
        // Ensure start doesn't go past end
        if (toDate(newStart).getTime() >= toDate(task.endDate).getTime())
            return;
        onTaskUpdate(task.id, { startDate: newStart });
    }, [onTaskUpdate, task.id, task.startDate, task.endDate]);
    const resizeLeftDrag = useGanttDrag({
        dayWidth,
        mode: "resize-left",
        barWidthPx: width,
        originalProgress: task.progress,
        disabled: !canDragDates,
        onDragEnd: handleResizeLeftEnd,
        onDragStateChange: useCallback((isDragging, deltaX) => {
            setActiveDrag(isDragging
                ? { taskId: task.id, mode: "resize-left", deltaX }
                : null);
        }, [setActiveDrag, task.id]),
    });
    // ----- Drag: Resize right -----
    const handleResizeRightEnd = useCallback((result) => {
        if (!onTaskUpdate || result.daysDelta === 0)
            return;
        const newEnd = addDays(task.endDate, result.daysDelta);
        // Ensure end doesn't go before start
        if (toDate(newEnd).getTime() <= toDate(task.startDate).getTime())
            return;
        onTaskUpdate(task.id, { endDate: newEnd });
    }, [onTaskUpdate, task.id, task.startDate, task.endDate]);
    const resizeRightDrag = useGanttDrag({
        dayWidth,
        mode: "resize-right",
        barWidthPx: width,
        originalProgress: task.progress,
        disabled: !canDragDates,
        onDragEnd: handleResizeRightEnd,
        onDragStateChange: useCallback((isDragging, deltaX) => {
            setActiveDrag(isDragging
                ? { taskId: task.id, mode: "resize-right", deltaX }
                : null);
        }, [setActiveDrag, task.id]),
    });
    // ----- Drag: Progress -----
    const handleProgressDragEnd = useCallback((result) => {
        if (!onTaskUpdate)
            return;
        onTaskUpdate(task.id, {
            progress: result.newProgress,
            completed: result.newProgress === 100,
        });
    }, [onTaskUpdate, task.id]);
    const progressDrag = useGanttDrag({
        dayWidth,
        mode: "progress",
        barWidthPx: width,
        originalProgress: task.progress,
        disabled: !canDragProgress,
        onDragEnd: handleProgressDragEnd,
    });
    const anyDragging = moveDrag.isDragging ||
        resizeLeftDrag.isDragging ||
        resizeRightDrag.isDragging ||
        progressDrag.isDragging;
    const anyDidDrag = moveDrag.didDrag ||
        resizeLeftDrag.didDrag ||
        resizeRightDrag.didDrag ||
        progressDrag.didDrag;
    // ----- Computed visual positions during drag -----
    let visualLeft = left;
    let visualWidth = width;
    let displayProgress = task.progress;
    if (moveDrag.isDragging) {
        visualLeft = left + moveDrag.dragDeltaX;
    }
    else if (resizeLeftDrag.isDragging) {
        const delta = resizeLeftDrag.dragDeltaX;
        // Clamp so width never goes below 1 day
        const maxDelta = width - dayWidth;
        const clampedDelta = Math.min(delta, maxDelta);
        visualLeft = left + clampedDelta;
        visualWidth = width - clampedDelta;
    }
    else if (resizeRightDrag.isDragging) {
        const delta = resizeRightDrag.dragDeltaX;
        // Clamp so width never goes below 1 day
        visualWidth = Math.max(width + delta, dayWidth);
    }
    if (progressDrag.isDragging) {
        displayProgress = progressDrag.dragProgress;
    }
    const isNarrow = visualWidth <= 80;
    // ----- Hover highlighting (dependency connections) -----
    const isHighlighted = useMemo(() => {
        var _a, _b, _c;
        if (!hoveredTaskId || hoveredTaskId === task.id)
            return false;
        // Check if this task depends on hovered task
        if ((_a = task.dependencies) === null || _a === void 0 ? void 0 : _a.includes(hoveredTaskId))
            return true;
        // Check if hovered task depends on this task
        const hoveredTask = tasks.find((t) => t.id === hoveredTaskId);
        return (_c = (_b = hoveredTask === null || hoveredTask === void 0 ? void 0 : hoveredTask.dependencies) === null || _b === void 0 ? void 0 : _b.includes(task.id)) !== null && _c !== void 0 ? _c : false;
    }, [hoveredTaskId, task.id, task.dependencies, tasks]);
    const isFaded = hoveredTaskId !== null && hoveredTaskId !== task.id && !isHighlighted;
    const isFocused = focusedTaskId === task.id;
    // ----- Click handler -----
    const handleClick = (e) => {
        if (anyDidDrag)
            return;
        onTaskClick === null || onTaskClick === void 0 ? void 0 : onTaskClick(task, e);
    };
    // ----- Tooltip -----
    const tooltipContent = (jsxs("div", { className: "text-sm space-y-2 min-w-[180px]", children: [jsx("div", { className: "font-semibold text-base", children: task.title }), jsxs("div", { className: "flex items-center gap-1.5 opacity-70", children: [jsx("span", { className: "inline-block size-2 rounded-full shrink-0", style: { backgroundColor: group.color } }), group.title] }), jsxs("div", { className: "space-y-0.5", children: [jsxs("div", { children: [formatDateShort(task.startDate), " \u2014 ", formatDateShort(task.endDate)] }), jsx("div", { className: "opacity-70", children: formatDuration(task.startDate, task.endDate) })] }), jsxs("div", { children: [jsxs("div", { className: "flex justify-between mb-1", children: [jsx("span", { children: "Progress" }), jsxs("span", { className: "font-medium", children: [task.progress, "%"] })] }), jsx("div", { className: "h-1.5 rounded-full bg-white/20 overflow-hidden", children: jsx("div", { className: "h-full rounded-full", style: {
                                width: `${task.progress}%`,
                                backgroundColor: barColor,
                            } }) })] }), task.assignee && (jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [jsx(Avatar, { src: task.assignee.avatar, name: task.assignee.name, size: "xs" }), jsx("span", { children: task.assignee.name })] })), isBehindSchedule && (jsxs("div", { className: "text-[var(--color-warning)] text-[10px]", children: ["Behind schedule (expected ", expectedProgress, "%)"] }))] }));
    return (jsxs(Fragment, { children: [jsx(GanttTaskContextMenu, { task: task, children: jsxs("div", { className: "absolute", style: {
                        left: visualLeft,
                        top: top + (rowHeight - barHeight) / 2,
                    }, onMouseEnter: (e) => {
                        if (!anyDragging) {
                            setTooltipPos({ x: e.clientX, y: e.clientY });
                            setHoveredTaskId(task.id);
                        }
                    }, onMouseMove: (e) => {
                        if (!anyDragging) {
                            setTooltipPos({ x: e.clientX, y: e.clientY });
                        }
                    }, onMouseLeave: () => {
                        setTooltipPos(null);
                        setHoveredTaskId(null);
                    }, onClick: onTaskClick ? handleClick : undefined, onPointerDown: canDragDates ? moveDrag.handlePointerDown : undefined, role: "button", "aria-label": task.title, children: [jsxs(motion.div, { className: cn(theme.taskBarStyle, "group", task.completed && "opacity-60", canDragDates && !anyDragging && "cursor-grab", anyDragging && "cursor-grabbing", !canDragDates && "cursor-default", isHighlighted && "ring-2 ring-white/60", isFaded && "opacity-40", isFocused && "ring-2 ring-[var(--color-primary)] ring-offset-1"), style: {
                                width: visualWidth,
                                height: barHeight,
                                backgroundColor: barColor,
                                border: "1px solid rgba(0,0,0,0.12)",
                                borderRadius: "2rem",
                                transformOrigin: "left center",
                                transition: anyDragging ? "none" : undefined,
                            }, variants: taskBarVariants, initial: "hidden", animate: "visible", whileHover: anyDragging ? undefined : { filter: "brightness(0.96)" }, children: [jsx("div", { className: "absolute inset-0 rounded-full", style: {
                                        width: `${displayProgress}%`,
                                        background: "linear-gradient(rgba(0,0,0,0.15), rgba(0,0,0,0.15))",
                                    } }), isBehindSchedule && (jsx("div", { className: "absolute top-0 bottom-0 w-px", style: {
                                        left: `${expectedProgress}%`,
                                        borderLeft: "2px dashed rgba(255,255,255,0.5)",
                                    } })), task.completed && (jsx("div", { className: "absolute top-1/2 left-2 right-2 h-px bg-white/60", style: { transform: "translateY(-0.5px)" } })), canDragDates && (jsx("div", { className: "absolute left-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-l-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeLeftDrag.handlePointerDown })), canDragDates && (jsx("div", { className: "absolute right-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-r-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeRightDrag.handlePointerDown })), canDragProgress && !isNarrow && (jsx("div", { className: "absolute top-0 bottom-0 w-3 cursor-ew-resize z-20 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity", style: { left: `calc(${displayProgress}% - 6px)` }, onPointerDown: progressDrag.handlePointerDown, children: jsx("div", { className: "w-0.5 h-3 rounded-full bg-white/80 shadow" }) })), !isNarrow && (jsxs("div", { className: "relative flex items-center gap-1.5 px-1 z-10 min-w-0 pointer-events-none", children: [task.assignee && (jsx(Avatar, { src: task.assignee.avatar, name: task.assignee.name, size: "xs" })), jsx("span", { className: "truncate text-sm text-[var(--color-text-inverse)] font-medium", children: task.title })] }))] }), isNarrow && (jsx("span", { className: "absolute text-sm font-medium whitespace-nowrap pointer-events-none", style: {
                                left: visualWidth + 6,
                                top: barHeight / 2,
                                transform: "translateY(-50%)",
                                color: barColor,
                            }, children: task.title }))] }) }), jsx(ChartTooltip, { active: !!tooltipPos && !anyDragging, position: tooltipPos !== null && tooltipPos !== void 0 ? tooltipPos : { x: 0, y: 0 }, content: tooltipContent })] }));
});

export { GanttTaskBar };
