import React, { useState, useEffect, Fragment, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Gantt, ViewMode } from 'gantt-task-react';
import "gantt-task-react/dist/index.css";
import { TaskListTable } from "./GanttChart/TaskListTable";
import { TaskListHeader } from "./GanttChart/TaskListHeader";
import { openTaskEditDrawer, setEditableTask, fetchGanttTasksByProject, editTask, changeGanttViewMode, setGanttListVisibility } from "../../../Settings/store/taskSlice";
import { fetchProjectPriorities, fetchProjectStatuses } from "../../../Settings/store/projectSlice";
import { useParams } from 'react-router-dom';
import { Box, Button, Card, Text, ThemeIcon } from '@mantine/core';
import useTwColorByName from "../../../ui/useTwColorByName";
import CustomTooltip from './GanttChart/CustomTaskTooltip';
import { notifications } from '@mantine/notifications';
import { IconCheck, IconNotesOff } from '@tabler/icons-react';
import { translate } from '../../../../utils/i18n';


function prepareTasks(tasks, bgColor) {
    return tasks.map((task, i) => {
        // Map status or priority to colors if possible, otherwise fallback to assignee or default
        let barColor = undefined;
        let progressColor = undefined;

        // Status-based coloring (User Defined Status)
        if (task.internal_status && task.internal_status.color_code) {
            barColor = task.internal_status.color_code;
            progressColor = task.internal_status.color_code;
        } else if (task.statusName && task.status_color_code) {
            barColor = task.status_color_code;
            progressColor = task.status_color_code;
        }
        // Fallback to internal status if needed
        else if (task.status === 'COMPLETED') {
            barColor = '#10B981'; // Green
            progressColor = '#10B981';
        }

        // Priority coloring (optional fallback if status doesn't determine color)
        // If status color isn't set, try priority
        if (!barColor && task.priority && task.priority.color_code) {
            barColor = task.priority.color_code;
            progressColor = task.priority.color_code;
        }

        // Fallback to Assignee-based
        if (!barColor && task.assigned_to && task.assigned_to.name) {
            barColor = bgColor(task.assigned_to.name)["bg-color"];
            progressColor = bgColor(task.assigned_to.name)["bg-color"];
        }

        // Default: hash by task id for varied vibrant colors
        if (!barColor) {
            barColor = bgColor(String(task.id || task.name || 'default'))["bg-color"];
            progressColor = barColor;
        }


        const isMissing = !task.start || !task.end;
        // Parse dates from raw Y-m-d fields to avoid ambiguous date string parsing.
        // Use Date(y,m,d,h,m,s) constructor (always local time) for cross-browser consistency.
        const startParts = (task.start_date || task.start || '').substring(0, 10).split('-');
        const endParts = (task.end_date || task.end || '').substring(0, 10).split('-');
        const start = startParts.length === 3
            ? new Date(+startParts[0], +startParts[1] - 1, +startParts[2], 0, 0, 0)
            : new Date();
        const end = endParts.length === 3
            ? new Date(+endParts[0], +endParts[1] - 1, +endParts[2], 23, 59, 59)
            : new Date();

        const durationDays = Math.ceil((end - start) / (1000 * 60 * 60 * 24));
        let maxLength = 50;

        const displayName = task.name && task.name.length > maxLength
            ? `${task.name.slice(0, maxLength)}...`
            : task.name;

        // Header-only rows (non-gantt parents shown for grouping context)
        if (task.headerOnly) {
            return {
                ...task,
                id: String(task.id),
                name: ' ',
                fullName: task.name || 'Untitled Task',
                type: 'task',
                isDisabled: true,
                headerOnly: true,
                start: start,
                end: end,
                displayStatus: '',
                displayStatusColor: '#d1d5db',
                progress: 0,
                dependencies: [],
                styles: {
                    backgroundColor: 'transparent',
                    backgroundSelectedColor: 'transparent',
                    progressColor: 'transparent',
                    progressSelectedColor: 'transparent',
                },
            };
        }

        return {
            ...task,
            id: String(task.id),
            name: displayName || 'Untitled Task',
            fullName: task.name || 'Untitled Task',
            type: 'task',
            isDisabled: false,
            start: start,
            end: end,
            displayStatus: (task.internal_status && task.internal_status.name) ? task.internal_status.name : (task.statusName || task.status),
            displayStatusColor: (task.internal_status && task.internal_status.color_code) ? task.internal_status.color_code : (task.status_color_code || (task.status === 'COMPLETED' ? '#10B981' : '#3b82f6')),
            progress: task.status === 'COMPLETED' ? 100 : 0,
            dependencies: task.dependencies && Array.isArray(task.dependencies) && task.dependencies.length > 0
                ? task.dependencies.map(depId => String(depId))
                : [],
            project: task.parent_id ? task.parent_id : undefined,
            styles: task.isMissingDates ? {
                backgroundColor: "rgba(237, 125, 49, 0.2)",
                backgroundSelectedColor: "rgba(57, 117, 141, 0.2)",
                progressColor: "transparent",
                progressSelectedColor: "transparent",
            } : {
                backgroundColor: barColor,
                progressColor: progressColor,
                backgroundSelectedColor: '#39758D',
                progressSelectedColor: '#39758D',
                borderRadius: '4px',
            },
        };
    });
}

const TaskGanttChart = () => {
    const bgColor = useTwColorByName();
    const dispatch = useDispatch();
    const { id } = useParams();
    const { ganttTasks, ganttViewMode, ganttListIsVisible } = useSelector((state) => state.settings.task);
    const { loggedUserId } = useSelector((state) => state.auth.user);
    const { loggedInUser } = useSelector((state) => state.auth.session);

    const [tasks, setTasks] = useState([]);
    const [viewDate, setViewDate] = useState(new Date());

    useEffect(() => {
        if (ganttTasks && ganttTasks.length > 0) {
            const tasksWithDates = ganttTasks.filter(task => task.headerOnly || task.start_date || task.end_date);
            const formattedTasks = prepareTasks(tasksWithDates, bgColor);
            setTasks(formattedTasks);
        } else {
            setTasks([]);
        }
    }, [ganttTasks, bgColor]);

    const handleExpanderClick = (task) => {
        setTasks(tasks.map(t => (t.id === task.id ? task : t)));
    };

    const onDblClick = (task) => {
        const taskObj = tasks.find(t => Number(t.id) === Number(task.id));
        if (taskObj) {
            dispatch(setEditableTask(taskObj));
            dispatch(openTaskEditDrawer());
        }
    };

    const dynamicHeight = window.innerHeight - 320; // Adjusted calculation

    let columnWidth = 65;
    if (ganttViewMode === ViewMode.Year) {
        columnWidth = 350;
    } else if (ganttViewMode === ViewMode.Month) {
        columnWidth = 300;
    } else if (ganttViewMode === ViewMode.Week) {
        columnWidth = 250;
    }

    const [limit] = useState(15);
    const [offset, setOffset] = useState(0); // Kept for future pagination implementation if needed
    const [hasMore, setHasMore] = useState(true); // Kept for compatibility
    const [loadingMore, setLoadingMore] = useState(false);


    const fetchTasks = async (reset = false) => {
        setLoadingMore(true);
        // data for dropdowns
        dispatch(fetchProjectStatuses(id));
        dispatch(fetchProjectPriorities(id));

        await dispatch(fetchGanttTasksByProject({ id: id }));
        setLoadingMore(false);
    };

    useEffect(() => {
        dispatch(setGanttListVisibility(true));
        fetchTasks(true);
    }, [id]);

    const formatDate = (date) => {
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, "0");
        const day = String(date.getDate()).padStart(2, "0");
        return `${year}-${month}-${day}`;
    };

    const saveDateChange = (taskId, start, end, updatedByUser) => {
        return dispatch(editTask({
            id: taskId,
            data: {
                start_date: start ? formatDate(start) : "empty",
                start_date_is_visible: start ? 1 : 0,
                end_date: end ? formatDate(end) : "empty",
                end_date_is_visible: end ? 1 : 0,
                updated_by: updatedByUser,
            },
        }));
    };

    const handleDateChange = async (task) => {
        const originalTask = tasks.find(t => t.id === task.id);
        if (originalTask && originalTask.headerOnly) return;

        // The library uses 5-min grid precision for moves/resizes, but we only
        // use Day/Week/Month views. Round to whole-day deltas so that end-of-day
        // times (23:59:59) never drift past midnight into the next calendar day.
        const msPerDay = 86400000;
        const startDayDelta = Math.round((task.start.getTime() - originalTask.start.getTime()) / msPerDay);
        const endDayDelta = Math.round((task.end.getTime() - originalTask.end.getTime()) / msPerDay);

        const newStart = new Date(originalTask.start);
        newStart.setDate(newStart.getDate() + startDayDelta);
        const newEnd = new Date(originalTask.end);
        newEnd.setDate(newEnd.getDate() + endDayDelta);

        const deltaMs = startDayDelta * msPerDay;

        // BFS: cascade shift to all downstream dependents
        const cascadedUpdates = [{ id: task.id, start: newStart, end: newEnd }];
        if (deltaMs !== 0) {
            const visited = new Set([String(task.id)]);
            const queue = [String(task.id)];
            while (queue.length > 0) {
                const currentId = queue.shift();
                tasks.forEach(t => {
                    if (
                        t.dependencies &&
                        t.dependencies.map(String).includes(currentId) &&
                        !visited.has(String(t.id))
                    ) {
                        visited.add(String(t.id));
                        const depNewStart = new Date(t.start);
                        depNewStart.setDate(depNewStart.getDate() + startDayDelta);
                        const depNewEnd = new Date(t.end);
                        depNewEnd.setDate(depNewEnd.getDate() + startDayDelta);
                        cascadedUpdates.push({ id: t.id, start: depNewStart, end: depNewEnd });
                        queue.push(String(t.id));
                    }
                });
            }
        }

        // Update local state for all affected tasks
        const updatedByUser = loggedInUser ? loggedInUser.loggedUserId : loggedUserId;
        const updatedTasks = tasks.map(t => {
            const match = cascadedUpdates.find(u => String(u.id) === String(t.id));
            return match ? { ...t, start: match.start, end: match.end } : t;
        });
        setTasks(updatedTasks);

        // Persist all changes
        const savePromises = cascadedUpdates.map(u =>
            saveDateChange(u.id, u.start, u.end, updatedByUser)
        );
        Promise.all(savePromises).then(responses => {
            const allOk = responses.every(r => r.payload && r.payload.status === 200);
            notifications.show({
                color: allOk ? 'green' : 'orange',
                title: allOk ? translate('Success') : translate('Partial Update'),
                message: cascadedUpdates.length > 1
                    ? translate(`Dates updated for ${cascadedUpdates.length} tasks (cascade).`)
                    : translate('Date updated successfully.'),
                icon: <IconCheck />,
                autoClose: 3000,
            });
        });
    };



    return (
        <Fragment>
            <Box className="lazytask-gantt h-full flex flex-col">
                <Box className="flex-1 overflow-hidden flex flex-col relative" style={{ borderRadius: '8px', border: '1px solid #e9ecef', backgroundColor: 'white' }}>
                    <Box className="flex-1 overflow-hidden relative">
                        {tasks && tasks.length > 0 ? (
                            <Gantt
                                style={{ overflow: 'hidden' }}
                                listCellWidth={ganttListIsVisible ? "645px" : "40px"}
                                viewMode={ganttViewMode || ViewMode.Day}
                                viewDate={viewDate}
                                columnWidth={columnWidth}
                                rowHeight={40}
                                barFill={50}
                                tasks={tasks}
                                onExpanderClick={handleExpanderClick}
                                TaskListTable={(props) => (
                                    <TaskListTable
                                        {...props}
                                        setTasks={setTasks}
                                        onClick={onDblClick}
                                    />
                                )}
                                TaskListHeader={TaskListHeader}
                                TooltipContent={({ task }) => <CustomTooltip task={task} />}
                                ganttHeight={dynamicHeight}
                                onDoubleClick={onDblClick}
                                onDateChange={handleDateChange}
                                barCornerRadius={4}
                                barProgressColor="#3b82f6"
                                barProgressSelectedColor="#2563eb"
                                barBackgroundColor="#e5e7eb"
                                barBackgroundSelectedColor="#d1d5db"
                                arrowColor="#ED7D31"
                                arrowIndent={20}
                            />
                        ) : (
                            <Card
                                withBorder
                                radius="md"
                                padding="md"
                                h={"100%"}
                                className="flex flex-col justify-center items-center bg-[#F9FAFB] shadow-sm"
                            >
                                <Box className="text-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-25">
                                    <ThemeIcon color='orange' variant="light" radius="md" size="xl">
                                        <IconNotesOff size={32} stroke={1.25} />
                                    </ThemeIcon>

                                    <Text ta="center" fz="lg" fw={700} c="#4A5568" mb="sm">
                                        {translate("No tasks available to display the Gantt chart.")}
                                    </Text>
                                    <Text ta="center" fz="sm" c="#718096" mb="lg">
                                        {translate("You can add tasks on gantt chart from list tab.")}
                                    </Text>

                                    <Button
                                        size="md"
                                        variant="light"
                                        color="#39758D"
                                        onClick={() => fetchTasks(true)}
                                        radius="md"
                                    >
                                        {translate("Refresh Tasks")}
                                    </Button>
                                </Box>
                            </Card>
                        )}
                    </Box>
                </Box>
            </Box>
        </Fragment>
    );
};

export default TaskGanttChart;
