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

import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.module.project.constant.ProjectExecutionConstants;
import com.njcn.rdms.module.project.constant.ProjectTaskConstants;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionStatusBoardReqVO;
import com.njcn.rdms.module.project.controller.admin.project.execution.vo.execution.ProjectExecutionStatusBoardRespVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskStatusBoardReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.ProjectTaskStatusBoardRespVO;
import com.njcn.rdms.module.project.dal.dataobject.project.execution.ProjectExecutionDO;
import com.njcn.rdms.module.project.dal.dataobject.status.ObjectStatusModelDO;
import com.njcn.rdms.module.project.dal.mysql.project.execution.ProjectExecutionMapper;
import com.njcn.rdms.module.project.dal.mysql.project.task.ProjectTaskMapper;
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusModelMapper;
import com.njcn.rdms.module.project.service.project.permission.VisibilityScope;
import com.njcn.rdms.module.project.service.project.permission.VisibilityScopeResolver;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
public class ProjectStatusBoardServiceImpl implements ProjectStatusBoardService {

    @Resource
    private ObjectStatusModelMapper objectStatusModelMapper;
    @Resource
    private ProjectExecutionMapper projectExecutionMapper;
    @Resource
    private ProjectTaskMapper projectTaskMapper;
    @Resource
    private VisibilityScopeResolver visibilityScopeResolver;

    @Override
    public ProjectExecutionStatusBoardRespVO getExecutionStatusBoard(Long projectId, ProjectExecutionStatusBoardReqVO reqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        VisibilityScope scope = visibilityScopeResolver.resolveForProject(projectId, userId);
        List<ObjectStatusModelDO> statusModels = objectStatusModelMapper.selectListByObjectTypeEnabled(ProjectExecutionConstants.OBJECT_TYPE);
        return buildExecutionStatusBoard(projectId, scope, reqVO, statusModels);
    }

    @Override
    public ProjectTaskStatusBoardRespVO getTaskStatusBoard(Long projectId, Long executionId, ProjectTaskStatusBoardReqVO reqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        VisibilityScope scope = visibilityScopeResolver.resolveForExecution(projectId, executionId, userId);
        // 执行 owner = 当前用户 → 看本执行下全部任务，等价于 seesAll。
        if (!scope.seesAll()) {
            ProjectExecutionDO exec = projectExecutionMapper.selectByProjectIdAndId(projectId, executionId);
            if (exec != null && Objects.equals(exec.getOwnerId(), userId)) {
                scope = VisibilityScope.all();
            }
        }
        List<ObjectStatusModelDO> statusModels = objectStatusModelMapper.selectListByObjectTypeEnabled(ProjectTaskConstants.OBJECT_TYPE);
        return buildTaskStatusBoard(projectId, executionId, scope, reqVO, statusModels);
    }

    private ProjectExecutionStatusBoardRespVO buildExecutionStatusBoard(Long projectId,
                                                                        VisibilityScope scope,
                                                                        ProjectExecutionStatusBoardReqVO reqVO,
                                                                        List<ObjectStatusModelDO> statusModels) {
        ProjectExecutionStatusBoardRespVO respVO = new ProjectExecutionStatusBoardRespVO();
        List<ProjectExecutionStatusBoardRespVO.ProjectStatusBoardItemVO> items = statusModels.stream().map(statusModel -> {
            ProjectExecutionStatusBoardRespVO.ProjectStatusBoardItemVO item =
                    new ProjectExecutionStatusBoardRespVO.ProjectStatusBoardItemVO();
            item.setStatusCode(statusModel.getStatusCode());
            item.setStatusName(statusModel.getStatusName());
            item.setCount(projectExecutionMapper.countByProjectIdAndStatusCode(projectId, scope, reqVO, statusModel.getStatusCode()).longValue());
            item.setSort(statusModel.getSort());
            item.setTerminal(statusModel.getTerminalFlag());
            return item;
        }).toList();
        respVO.setItems(items);
        respVO.setTotal(items.stream().mapToLong(ProjectExecutionStatusBoardRespVO.ProjectStatusBoardItemVO::getCount).sum());
        return respVO;
    }

    private ProjectTaskStatusBoardRespVO buildTaskStatusBoard(Long projectId, Long executionId,
                                                              VisibilityScope scope,
                                                              ProjectTaskStatusBoardReqVO reqVO,
                                                              List<ObjectStatusModelDO> statusModels) {
        ProjectTaskStatusBoardRespVO respVO = new ProjectTaskStatusBoardRespVO();
        List<ProjectTaskStatusBoardRespVO.ProjectStatusBoardItemVO> items = statusModels.stream().map(statusModel -> {
            ProjectTaskStatusBoardRespVO.ProjectStatusBoardItemVO item = new ProjectTaskStatusBoardRespVO.ProjectStatusBoardItemVO();
            item.setStatusCode(statusModel.getStatusCode());
            item.setStatusName(statusModel.getStatusName());
            item.setCount(projectTaskMapper.countByProjectIdAndExecutionIdAndStatusCode(projectId, executionId, scope, reqVO,
                    statusModel.getStatusCode()).longValue());
            item.setSort(statusModel.getSort());
            item.setTerminal(statusModel.getTerminalFlag());
            return item;
        }).toList();
        respVO.setItems(items);
        respVO.setTotal(items.stream().mapToLong(ProjectTaskStatusBoardRespVO.ProjectStatusBoardItemVO::getCount).sum());
        return respVO;
    }

}
