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

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskDeleteReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskRespVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskSaveReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskStatusActionReqVO;
import com.njcn.rdms.module.project.dal.dataobject.project.task.ProjectTaskDO;

/**
 * 项目任务 Service 接口。
 */
public interface ProjectTaskService {

    Long createTask(Long projectId, Long executionId, ProjectTaskSaveReqVO reqVO);

    void updateTask(Long projectId, Long executionId, ProjectTaskSaveReqVO reqVO);

    ProjectTaskDO getTask(Long projectId, Long executionId, Long taskId);

    PageResult<ProjectTaskDO> getTaskPage(Long projectId, Long executionId, ProjectTaskPageReqVO reqVO);

    /**
     * 获取任务详情 VO，附带状态生命周期与负责人昵称。
     */
    ProjectTaskRespVO getTaskRespVO(Long projectId, Long executionId, Long taskId);

    /**
     * 获取任务分页 VO，附带状态生命周期与负责人昵称（昵称按 ownerId 去重批量查询，避免 N+1）。
     */
    PageResult<ProjectTaskRespVO> getTaskRespVOPage(Long projectId, Long executionId, ProjectTaskPageReqVO reqVO);

    void changeTaskStatus(Long projectId, Long executionId, Long taskId, ProjectTaskStatusActionReqVO reqVO);

    /**
     * 删除任务（软删 + CAS 状态校验 + 三重确认 + 执行 owner 字段硬卡）。
     * <p>仅初始态可删；权限码 project:task:delete 作菜单入口可见度；实际拦截以 execution.ownerId == currentUserId 为准（spec §5.1 上级硬卡范式）。
     * <p>不级联软删任务下挂的工时 / 协办人 / 子任务（通过 deleted=0 自然不可见）。
     */
    void deleteTask(Long projectId, Long executionId, Long taskId, ProjectTaskDeleteReqVO reqVO);

    /**
     * 以"任务负责人本人最新一条工时"的进度为准，同步到任务自身 progressRate 并触发父任务 AVG 重算。
     * 由工时模块在 owner 维度的 worklog create/update/delete 后调用。
     * 若 owner 当前在该任务下不存在任何工时记录，则保留 task.progress_rate 原值不动（避免删除场景下意外归零）。
     * 仅对叶子任务生效；父任务由子任务汇总驱动，不走该路径。
     */
    void syncOwnerProgressFromLatestWorklog(Long taskId);

    /**
     * 由工时填报（5.11）触发的任务自动开始：当任务当前处于初始态（initialFlag=true）时，
     * 走一次 {@link com.njcn.rdms.module.project.constant.ObjectActivityConstants#TASK_ACTION_AUTO_START}
     * 动作把任务推进到下一状态，并复用 5.5 的钩子写入 actualStartDate / 状态日志 / 审计日志。
     * <p>
     * 调用方必须已自行确认登录人是 task.ownerId（仅 owner 工时驱动状态推进，与 progressRate 同步口径一致）。
     * 本方法**不走** @CheckObjectPermission，因为 5.11 持有的是 PERMISSION_WORKLOG，
     * 而 5.5 changeTaskStatus 持有的是 PERMISSION_STATUS，两者权限边界不同。
     * <p>
     * 容错：若任务当前状态非初始态、transition 配置缺失/禁用、并发被抢占（affected=0）等情况，
     * 本方法静默 return（仅打 WARN 日志），不影响工时主流程入库。
     */
    void internalAutoStartByWorklog(ProjectTaskDO task);

    /**
     * 由执行 cancel 触发的级联：取消指定执行下所有未终态的顶层任务（parentTaskId IS NULL）。
     * 顶层任务自身的内部链路会再级联自己的子任务，整棵子树通过链式实现。
     * 跳过任务侧的 owner 校验（系统行为），但复用 doInternalChangeTaskStatus 的事务 / CAS / 审计 / 实际日期回填等。
     * 调用方：ProjectExecutionServiceImpl 在 cancel 成功后追加。
     */
    void cascadeCancelTasksByExecutionId(Long executionId, String executionReason);

    /**
     * 由执行 pause 触发的级联：暂停指定执行下所有顶层任务中状态为 active 的节点。
     * 顶层任务自身会再级联子任务，整棵子树同步暂停。
     */
    void cascadePauseTasksByExecutionId(Long executionId, String executionReason);

    /**
     * 由执行 resume 触发的级联：恢复指定执行下所有顶层任务中状态为 paused 的节点。
     * 顶层任务自身会再级联子任务，整棵子树同步恢复。
     * "误恢复"边界（任务级 paused 与父级 paused 不区分）与任务侧 §4.4 同款，已识别并接受。
     */
    void cascadeResumeTasksByExecutionId(Long executionId, String executionReason);

}
