package com.njcn.rdms.module.project.service.project.task.assignee;

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.assignee.TaskAssigneeInactiveReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.assignee.TaskAssigneeLogPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.assignee.TaskAssigneeLogRespVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.assignee.TaskAssigneeRespVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.assignee.TaskAssigneeSaveReqVO;
import com.njcn.rdms.module.project.dal.dataobject.project.task.TaskAssigneeDO;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 任务协办人 Service。
 * 协办人采用 B 模型 - 多行周期记录：每次加入新增一条 active 行 + 一条 join 日志；
 * 失效时 active 行 setRemovedAt + 写一条 inactive 日志。日志中昵称快照写入时落库不再回查。
 */
public interface TaskAssigneeService {

    /**
     * 获取指定任务的当前活跃协办人列表（含昵称装配）。
     */
    List<TaskAssigneeRespVO> getAssigneeList(Long projectId, Long executionId, Long taskId);

    /**
     * 加入协办人（独立接口入口）。校验：项目/执行/任务可编辑、user 是有效执行成员、
     * 不能与 owner 重复、不能已有活跃段。返回新建的协办关系编号。
     */
    Long createAssignee(Long projectId, Long executionId, Long taskId, TaskAssigneeSaveReqVO reqVO);

    /**
     * 失效协办人（独立接口入口）。校验：记录存在、当前活跃、reason 非空。
     */
    void inactiveAssignee(Long projectId, Long executionId, Long taskId, Long assigneeId,
                          TaskAssigneeInactiveReqVO reqVO);

    /**
     * 分页查询协办人变更历史。日志中昵称快照已写入，无需回查。
     */
    PageResult<TaskAssigneeLogRespVO> getAssigneeLogPage(Long projectId, Long executionId, Long taskId,
                                                         TaskAssigneeLogPageReqVO reqVO);

    /**
     * 创建任务时一次性初始化协办人列表（仅供 ProjectTaskServiceImpl.createTask 调用）。
     * 不重复校验项目/执行/任务编辑权限（外层已保证）；同一事务内全部插入或整笔回滚。
     * 列表会自动去重；任一项校验失败抛出异常。assigneeUserIds 为 null 或空时直接返回。
     */
    void initializeAssignees(Long taskId, Long ownerId, Long executionId, List<Long> assigneeUserIds);

    /**
     * 批量加载多个任务的活跃协办人，按任务 ID 分组返回。供分页装配使用，避免 N+1。
     */
    Map<Long, List<TaskAssigneeDO>> loadActiveAssigneesGroupedByTaskId(Collection<Long> taskIds);

}
