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

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.MyProjectExecutionPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.MyProjectExecutionRespVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionOwnerChangeReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionRespVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionCreateReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionDeletePrecheckRespVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionDeleteReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionUpdateReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionStatusActionReqVO;
import com.njcn.rdms.module.project.dal.dataobject.project.execution.ProjectExecutionDO;

import java.util.List;

/**
 * 执行主数据 Service。
 */
public interface ProjectExecutionService {

    Long createExecution(Long projectId, ProjectExecutionCreateReqVO reqVO);

    void updateExecution(Long projectId, ProjectExecutionUpdateReqVO reqVO);

    ProjectExecutionDO getExecution(Long projectId, Long executionId);

    PageResult<ProjectExecutionDO> getExecutionPage(Long projectId, ProjectExecutionPageReqVO reqVO);

    /**
     * 获取执行详情 VO，附带状态生命周期与负责人昵称。
     */
    ProjectExecutionRespVO getExecutionRespVO(Long projectId, Long executionId);

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

    List<ProjectExecutionRespVO> getCurrentUserExecutionList();

    /**
     * 分页查询当前登录用户作为负责人（owner）的执行，跨所有项目聚合。
     * 默认口径：排除终态状态（completed/cancelled）且排除进度已满（progressRate >= 100）的执行。
     * pageSize 传 -1（PageParam.PAGE_SIZE_NONE）= 返回全部、不切片。
     */
    PageResult<MyProjectExecutionRespVO> getMyExecutionPage(MyProjectExecutionPageReqVO reqVO);

    void changeOwner(Long projectId, Long executionId, ProjectExecutionOwnerChangeReqVO reqVO);

    /**
     * 删除执行（软删 + 状态校验 + 三重确认 + 级联软删）。
     * <p>删除规则：状态非 completed（已完成）即可删除，pending / active / paused / cancelled 全部允许；
     * 仅 completed 拒绝主动删除（已完成数据需保留作为审计与统计依据）。
     * <p>三重确认：reqVO 中 executionName（执行名称）、confirmText（删除口令 DELETE 或 删除）、reason（删除原因）三者均必填，
     * 任一缺失或不匹配直接拒绝；reason 文本入审计日志。
     * <p>级联范围：同步软删该执行下全部任务（含子孙任务）、任务工作日志、任务协办、执行协办。
     * <p>软删机制：所有 mapper.deleteXxx 走 @TableLogic 自动转 UPDATE deleted=1，下挂数据通过 deleted=0 过滤自然不可见。
     * <p>权限：@CheckObjectPermission(objectType=PROJECT, permission=PERMISSION_DELETE) 对象域权限码，推荐挂"项目负责人"角色。
     * <p>审计：写 EXECUTION_ACTION_DELETE 一条，reason 入 audit_reason 字段。
     */
    void deleteExecution(Long projectId, Long executionId, ProjectExecutionDeleteReqVO reqVO);

    /**
     * 删除执行前的下挂数据预检。
     * <p>返回执行下任务总数（含已软删之外的全部活跃任务）与 hasDependentData（是否存在下挂）标记。
     * <p>前端依据该结果分流：无下挂走简化确认路径（仅口令 + 原因），有下挂走重型确认路径（额外提示级联影响范围）。
     * <p>本接口为只读预检，不变更任何数据；删除规则与级联范围的最终校验仍由 {@link #deleteExecution} 负责。
     */
    ProjectExecutionDeletePrecheckRespVO precheckDeleteExecution(Long projectId, Long executionId);

    void changeExecutionStatus(Long projectId, Long executionId, ProjectExecutionStatusActionReqVO reqVO);

    /**
     * 任务状态变更回调（事件驱动）。
     * 任务侧在 auto_start / complete / cancel 三个动作的成功落库后调用本方法；pause / resume 不调用。
     * 执行侧据此自行分发响应（如自身 auto_start 联动、完成校验链、向项目 / 需求继续传播等）。
     * 调用规则见 docs/项目/任务状态流转设计.md §6.4 触发表。
     * 当前为预埋接口；具体响应在《执行闭环设计》中落地。
     */
    void onTaskStatusChanged(Long executionId, Long taskId, String fromStatus, String toStatus,
                             String actionCode, String reason);

}
