const { Task } = require('../../../models');
const { Op } = require('sequelize');
const taskRepository = require('../repository');
const { logError } = require('../../../services/logService');

async function checkAndUpdateParentTaskCompletion(parentTaskId, userId) {
    try {
        const subtasks = await taskRepository.findChildren(
            parentTaskId,
            userId
        );

        const allSubtasksDone =
            subtasks.length > 0 &&
            subtasks.every(
                (subtask) =>
                    subtask.status === Task.STATUS.DONE ||
                    subtask.status === 'done'
            );

        if (allSubtasksDone) {
            const parentTask = await taskRepository.findByIdAndUser(
                parentTaskId,
                userId
            );

            if (
                parentTask &&
                parentTask.status !== Task.STATUS.DONE &&
                parentTask.status !== 'done'
            ) {
                await taskRepository.update(parentTaskId, userId, {
                    status: Task.STATUS.DONE,
                    completed_at: new Date(),
                });
                return true;
            }
        }
        return false;
    } catch (error) {
        logError('Error checking parent task completion:', error);
        return false;
    }
}

async function undoneParentTaskIfNeeded(parentTaskId, userId) {
    try {
        const parentTask = await taskRepository.findByIdAndUser(
            parentTaskId,
            userId
        );

        if (
            parentTask &&
            (parentTask.status === Task.STATUS.DONE ||
                parentTask.status === 'done')
        ) {
            await taskRepository.update(parentTaskId, userId, {
                status: Task.STATUS.NOT_STARTED,
                completed_at: null,
            });
            return true;
        }
        return false;
    } catch (error) {
        logError('Error undoing parent task:', error);
        return false;
    }
}

async function completeAllSubtasks(parentTaskId, userId) {
    try {
        const result = await taskRepository.updateChildren(
            parentTaskId,
            userId,
            {
                status: Task.STATUS.DONE,
                completed_at: new Date(),
            }
        );
        return result[0] > 0;
    } catch (error) {
        logError('Error completing all subtasks:', error);
        return false;
    }
}

async function cancelAllSubtasks(parentTaskId, userId) {
    try {
        const result = await taskRepository.updateChildrenWithConditions(
            parentTaskId,
            userId,
            {
                status: Task.STATUS.CANCELLED,
            },
            {
                status: {
                    [Op.notIn]: [
                        Task.STATUS.DONE,
                        Task.STATUS.ARCHIVED,
                        Task.STATUS.CANCELLED,
                        'done',
                        'archived',
                        'cancelled',
                    ],
                },
            }
        );
        return result[0] > 0;
    } catch (error) {
        logError('Error cancelling all subtasks:', error);
        return false;
    }
}

async function uncancelAllSubtasks(parentTaskId, userId) {
    try {
        const result = await taskRepository.updateChildrenWithConditions(
            parentTaskId,
            userId,
            {
                status: Task.STATUS.NOT_STARTED,
            },
            {
                status: {
                    [Op.in]: [Task.STATUS.CANCELLED, 'cancelled'],
                },
            }
        );
        return result[0] > 0;
    } catch (error) {
        logError('Error uncancelling all subtasks:', error);
        return false;
    }
}

async function undoneAllSubtasks(parentTaskId, userId) {
    try {
        const result = await taskRepository.updateChildrenWithConditions(
            parentTaskId,
            userId,
            {
                status: Task.STATUS.NOT_STARTED,
                completed_at: null,
            },
            {
                status: {
                    [Op.in]: [Task.STATUS.DONE, 'done'],
                },
            }
        );
        return result[0] > 0;
    } catch (error) {
        logError('Error undoing all subtasks:', error);
        return false;
    }
}

async function handleParentChildOnStatusChange(
    task,
    oldStatus,
    newStatus,
    userId
) {
    let parentChildLogicExecuted = false;

    const directSubtasksQuery = await taskRepository.findChildren(
        task.id,
        userId,
        { attributes: ['id', 'name', 'status', 'parent_task_id'] }
    );

    if (
        directSubtasksQuery.length > 0 &&
        (!task.Subtasks || task.Subtasks.length === 0)
    ) {
        task.Subtasks = directSubtasksQuery;
    }

    if (task.Subtasks && task.Subtasks.length > 0) {
        if (newStatus === Task.STATUS.DONE) {
            const subtasksUpdated = await completeAllSubtasks(task.id, userId);
            if (subtasksUpdated) {
                parentChildLogicExecuted = true;
            }
        } else if (newStatus === Task.STATUS.CANCELLED) {
            const subtasksUpdated = await cancelAllSubtasks(task.id, userId);
            if (subtasksUpdated) {
                parentChildLogicExecuted = true;
            }
        } else if (oldStatus === Task.STATUS.DONE || oldStatus === 'done') {
            const subtasksUpdated = await undoneAllSubtasks(task.id, userId);
            if (subtasksUpdated) {
                parentChildLogicExecuted = true;
            }
        } else if (
            oldStatus === Task.STATUS.CANCELLED ||
            oldStatus === 'cancelled'
        ) {
            const subtasksUpdated = await uncancelAllSubtasks(task.id, userId);
            if (subtasksUpdated) {
                parentChildLogicExecuted = true;
            }
        }
    }

    return parentChildLogicExecuted;
}

module.exports = {
    checkAndUpdateParentTaskCompletion,
    undoneParentTaskIfNeeded,
    completeAllSubtasks,
    undoneAllSubtasks,
    cancelAllSubtasks,
    uncancelAllSubtasks,
    handleParentChildOnStatusChange,
};
