import React, { useState, useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from "react-redux";
import { editTask } from "../../../../Settings/store/taskSlice";
import { MultiSelect, Box } from "@mantine/core";
import { IconArrowRight } from '@tabler/icons-react';
import { translate } from '../../../../../utils/i18n';
import { notifications } from '@mantine/notifications';
import { IconAlertTriangle } from '@tabler/icons-react';

const TaskChildDependency = ({ taskId, disabled }) => {
    const dispatch = useDispatch();
    const { loggedUserId } = useSelector((state) => state.auth.user);
    const { loggedInUser } = useSelector((state) => state.auth.session);
    const { columns, childColumns, allTasks, ganttTasks } = useSelector((state) => state.settings.task);

    // Build a deduplicated flat pool of all tasks
    const allTasksPool = useMemo(() => {
        const map = new Map();
        const addToMap = (arr) => {
            if (!Array.isArray(arr)) return;
            arr.forEach(t => {
                if (t && t.id && !map.has(t.id.toString())) {
                    map.set(t.id.toString(), t);
                }
            });
        };
        addToMap(allTasks);
        addToMap(ganttTasks);
        if (columns) Object.values(columns).forEach(col => Array.isArray(col) && addToMap(col));
        if (childColumns) Object.values(childColumns).forEach(col => Array.isArray(col) && addToMap(col));
        return Array.from(map.values());
    }, [allTasks, ganttTasks, columns, childColumns]);

    // Compute current child task IDs: tasks that have taskId in their dependencies
    const computeChildIds = () =>
        allTasksPool
            .filter(t =>
                t.id?.toString() !== taskId?.toString() &&
                t.dependencies &&
                Array.isArray(t.dependencies) &&
                t.dependencies.map(String).includes(taskId?.toString())
            )
            .map(t => t.id.toString());

    const [selectedChildIds, setSelectedChildIds] = useState(computeChildIds);

    // Re-sync when the task pool changes (e.g. after another task is saved)
    useEffect(() => {
        setSelectedChildIds(computeChildIds());
    }, [allTasksPool, taskId]);

    // Available tasks to pick from (exclude self)
    const availableTasks = allTasksPool
        .filter(t => t.id?.toString() !== taskId?.toString())
        .map(t => ({ value: t.id.toString(), label: t.name || 'Untitled' }));

    // Build a full dep map for circular-dependency detection
    const buildDepMap = () => {
        const depMap = {};
        allTasksPool.forEach(t => {
            depMap[t.id.toString()] = t.dependencies ? t.dependencies.map(String) : [];
        });
        return depMap;
    };

    const wouldCreateCycle = (candidateChildId) => {
        // Adding candidateChildId as a child of taskId means:
        // taskId goes into candidateChildId.dependencies.
        // A cycle exists if taskId is already reachable FROM candidateChildId
        // (i.e., following its existing dependencies leads back to taskId).
        const depMap = buildDepMap();
        // Temporarily set the proposed dep
        depMap[candidateChildId] = [...(depMap[candidateChildId] || []), taskId?.toString()];

        const visited = new Set();
        const stack = [taskId?.toString()];
        while (stack.length > 0) {
            const node = stack.pop();
            if (node === candidateChildId) return true;
            if (visited.has(node)) continue;
            visited.add(node);
            (depMap[node] || []).forEach(c => stack.push(c));
        }
        return false;
    };

    const handleChange = (newChildIds) => {
        const prevIds = selectedChildIds;

        // Detect additions and removals
        const added = newChildIds.filter(id => !prevIds.includes(id));
        const removed = prevIds.filter(id => !newChildIds.includes(id));

        // Circular check for each added child
        const circular = added.find(id => wouldCreateCycle(id));
        if (circular) {
            const circularTask = allTasksPool.find(t => t.id.toString() === circular);
            notifications.show({
                color: 'red',
                title: translate('Circular Dependency Detected'),
                message: translate(
                    `Adding "${circularTask?.name || circular}" as a child would create a circular dependency.`
                ),
                icon: <IconAlertTriangle />,
                autoClose: 4000,
            });
            return; // Abort
        }

        const updatedBy = loggedInUser ? loggedInUser.loggedUserId : loggedUserId;

        // For added tasks: inject taskId into their dependencies
        added.forEach(childId => {
            const childTask = allTasksPool.find(t => t.id.toString() === childId);
            const existingDeps = childTask?.dependencies ? childTask.dependencies.map(String) : [];
            if (!existingDeps.includes(taskId?.toString())) {
                dispatch(editTask({
                    id: childId,
                    data: {
                        dependencies: [...existingDeps, taskId.toString()],
                        updated_by: updatedBy,
                    },
                }));
            }
        });

        // For removed tasks: remove taskId from their dependencies
        removed.forEach(childId => {
            const childTask = allTasksPool.find(t => t.id.toString() === childId);
            const existingDeps = childTask?.dependencies ? childTask.dependencies.map(String) : [];
            dispatch(editTask({
                id: childId,
                data: {
                    dependencies: existingDeps.filter(d => d !== taskId?.toString()),
                    updated_by: updatedBy,
                },
            }));
        });

        setSelectedChildIds(newChildIds);
    };

    return (
        <Box className="flex items-start w-full gap-2">
            <Box className="w-[30px] h-[30px] rounded-full flex items-center justify-center flex-shrink-0 pt-[4px]">
                <IconArrowRight size="20" color="#ED7D31" stroke={1.25} />
            </Box>
            <Box className="flex-grow max-w-[calc(100%-40px)]">
                <MultiSelect
                    data={availableTasks}
                    value={selectedChildIds}
                    onChange={handleChange}
                    placeholder={translate("Child tasks...")}
                    searchable
                    clearable
                    disabled={disabled}
                    variant="unstyled"
                    styles={{
                        input: { minHeight: '30px', paddingLeft: 0, paddingRight: 0, fontSize: '12px' },
                        value: { fontSize: '11px' }
                    }}
                />
            </Box>
        </Box>
    );
};

export default TaskChildDependency;
