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

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectContextRespVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectCreateWithTeamReqVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectDeleteReqVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectGroupPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectGroupPageRespVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectOverviewSummaryRespVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectRespVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectSaveReqVO;
import com.njcn.rdms.module.project.controller.admin.project.vo.project.ProjectStatusActionReqVO;
import com.njcn.rdms.module.project.dal.dataobject.project.ProjectDO;

import java.util.List;

/**
 * 项目 Service 接口
 */
public interface ProjectService {

    Long createProject(ProjectSaveReqVO createReqVO);

    /**
     * 创建项目并初始化团队（原子接口）。
     *
     * <p>由前端"项目两步向导"一次性提交，项目基础资料与全部初始团队成员
     * 必须在同一事务内完成写入；任一步失败整体回滚。
     *
     * <p>与 {@link #createProject(ProjectSaveReqVO)} 的关键差异：
     * <ul>
     *   <li>经理成员由前端在 {@code members} 中显式提交，后端不再根据
     *       {@code project.managerUserId} 自动追加；并校验 {@code members}
     *       中必须存在 userId 等于 managerUserId 的记录；</li>
     *   <li>{@code productId} 非空时，{@code directionCode} 必须与所属产品方向
     *       一致（防御性校验），不一致直接报错而非覆盖。</li>
     * </ul>
     *
     * @param reqVO 创建请求（项目 + 初始团队）
     * @return 项目编号
     */
    Long createProjectWithTeam(ProjectCreateWithTeamReqVO reqVO);

    void updateProject(ProjectSaveReqVO updateReqVO);

    ProjectDO getProject(Long id);

    ProjectRespVO getProjectDetail(Long id);

    List<ProjectRespVO> getProjectListByProductId(Long productId);

    ProjectContextRespVO getProjectContext(Long id);

    PageResult<ProjectRespVO> getProjectPage(ProjectPageReqVO pageReqVO);

    /**
     * 项目按产品分组分页：组维度翻页，组内带 topN 条项目。
     * 口径见 docs/superpowers/specs/2026-06-10-项目列表产品分组-design.md 第三节。
     */
    ProjectGroupPageRespVO getProjectGroupPage(ProjectGroupPageReqVO reqVO);

    ProjectOverviewSummaryRespVO getProjectOverviewSummary();

    void changeProjectStatus(ProjectStatusActionReqVO reqVO);

    void deleteProject(ProjectDeleteReqVO reqVO);

    void autoStartProjectIfPending(Long projectId, String triggerAction);

    /**
     * 以项目下最早一条任务工作日志的 startDate 为优先口径，同步项目实际开始日期。
     * 若项目下尚无任务工作日志，则回退到首次 auto_start 状态日志日期；两者都没有时不更新。
     */
    void syncActualStartDateFromWorklogs(Long projectId);

    /**
     * 重算项目进度并落库：AVG(项目下所有根任务 progressRate)，沿用 task 维度的 progress_excluded 排除集合。
     * 由任务侧在"任务进度变化 / 状态变更 / 创建删除 / 父子结构变化"等入口触发。
     */
    void recalcProgress(Long projectId);

}
