package com.njcn.rdms.module.project.dal.mysql.project.task;

import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.njcn.rdms.module.project.dal.dataobject.project.task.TaskAssigneeDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Mapper
public interface TaskAssigneeMapper extends BaseMapperX<TaskAssigneeDO> {

    /**
     * 查同一任务下指定 userId 当前活跃的协办段（removed_at IS NULL）。失效段不会命中。
     */
    default TaskAssigneeDO selectActiveByTaskIdAndUserId(Long taskId, Long userId) {
        return selectOne(new LambdaQueryWrapperX<TaskAssigneeDO>()
                .eq(TaskAssigneeDO::getTaskId, taskId)
                .eq(TaskAssigneeDO::getUserId, userId)
                .isNull(TaskAssigneeDO::getRemovedAt));
    }

    /**
     * 查指定任务下所有当前活跃协办，按加入时间正序。
     */
    default List<TaskAssigneeDO> selectActiveListByTaskId(Long taskId) {
        return selectList(new LambdaQueryWrapperX<TaskAssigneeDO>()
                .eq(TaskAssigneeDO::getTaskId, taskId)
                .isNull(TaskAssigneeDO::getRemovedAt)
                .orderByAsc(TaskAssigneeDO::getJoinedAt)
                .orderByAsc(TaskAssigneeDO::getId));
    }

    /**
     * 批量查多个任务的活跃协办（分页装配 N+1 优化）。
     */
    default List<TaskAssigneeDO> selectActiveListByTaskIds(Collection<Long> taskIds) {
        if (taskIds == null || taskIds.isEmpty()) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<TaskAssigneeDO>()
                .in(TaskAssigneeDO::getTaskId, taskIds)
                .isNull(TaskAssigneeDO::getRemovedAt)
                .orderByAsc(TaskAssigneeDO::getTaskId)
                .orderByAsc(TaskAssigneeDO::getJoinedAt)
                .orderByAsc(TaskAssigneeDO::getId));
    }

    /**
     * 查 userId 在指定项目下，当前活跃协办的所有任务 ID（removed_at IS NULL）。
     * 走 JOIN 是因为 task_assignee 表没有 project_id 冗余字段。
     * 用于 VisibilityScopeResolver 收集"我是任务协办人"的 scope 来源（项目维度）。
     */
    @Select("""
            SELECT a.task_id
              FROM rdms_task_assignee a
              JOIN rdms_task t ON t.id = a.task_id AND t.deleted = b'0'
             WHERE a.deleted = b'0'
               AND a.removed_at IS NULL
               AND t.project_id = #{projectId}
               AND a.user_id    = #{userId}
            """)
    List<Long> selectActiveTaskIdsByProjectIdAndUserId(@Param("projectId") Long projectId,
                                                       @Param("userId") Long userId);

    /**
     * 同上，但再加 execution_id 维度，用于"任务分页（执行内）"的 scope。
     */
    @Select("""
            SELECT a.task_id
              FROM rdms_task_assignee a
              JOIN rdms_task t ON t.id = a.task_id AND t.deleted = b'0'
             WHERE a.deleted = b'0'
               AND a.removed_at IS NULL
               AND t.project_id   = #{projectId}
               AND t.execution_id = #{executionId}
               AND a.user_id      = #{userId}
            """)
    List<Long> selectActiveTaskIdsByProjectIdAndExecutionIdAndUserId(
            @Param("projectId") Long projectId,
            @Param("executionId") Long executionId,
            @Param("userId") Long userId);

    /**
     * 按主键 + 任务 ID 双键查；返回的记录可能已失效（removed_at != null），由调用方判断。
     */
    default TaskAssigneeDO selectByIdAndTaskId(Long id, Long taskId) {
        return selectOne(new LambdaQueryWrapperX<TaskAssigneeDO>()
                .eq(TaskAssigneeDO::getId, id)
                .eq(TaskAssigneeDO::getTaskId, taskId));
    }

}
