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

import com.njcn.rdms.framework.common.pojo.PageParam;
import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.module.project.constant.ProjectTaskConstants;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.mytask.MyTaskPageReqVO;
import com.njcn.rdms.module.project.controller.admin.project.task.vo.mytask.MyTaskRespVO;
import com.njcn.rdms.module.project.dal.dataobject.project.ProjectDO;
import com.njcn.rdms.module.project.dal.dataobject.project.execution.ProjectExecutionDO;
import com.njcn.rdms.module.project.dal.dataobject.project.task.ProjectTaskDO;
import com.njcn.rdms.module.project.dal.mysql.project.ProjectMapper;
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 jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MyTaskServiceImpl implements MyTaskService {

    @Resource
    private ProjectTaskMapper projectTaskMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private ProjectExecutionMapper projectExecutionMapper;
    @Resource
    private ObjectStatusModelMapper objectStatusModelMapper;
    @Resource
    private ProjectTaskStatusViewService projectTaskStatusViewService;

    @Override
    public PageResult<MyTaskRespVO> getMyTaskPage(MyTaskPageReqVO reqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        // 终态运行时推导；SQL 内对空集有 <if> 守卫
        List<String> taskTerminal = objectStatusModelMapper
                .selectTerminalStatusCodesByObjectTypeEnabled(ProjectTaskConstants.OBJECT_TYPE);
        List<ProjectTaskDO> tasks = projectTaskMapper
                .selectMyUnfinishedInvolvedList(loginUserId, reqVO.getInvolveType(), taskTerminal);
        if (tasks.isEmpty()) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }
        // 项目名 / 执行名批量回填
        Set<Long> projectIds = tasks.stream().map(ProjectTaskDO::getProjectId)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        Map<Long, ProjectDO> projectMap = projectIds.isEmpty() ? Collections.emptyMap()
                : projectMapper.selectBatchIds(projectIds).stream()
                        .collect(Collectors.toMap(ProjectDO::getId, Function.identity(), (a, b) -> a));
        Set<Long> executionIds = tasks.stream().map(ProjectTaskDO::getExecutionId)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        Map<Long, ProjectExecutionDO> executionMap = executionIds.isEmpty() ? Collections.emptyMap()
                : projectExecutionMapper.selectBatchIds(executionIds).stream()
                        .collect(Collectors.toMap(ProjectExecutionDO::getId, Function.identity(), (a, b) -> a));
        List<MyTaskRespVO> all = tasks.stream().map(t -> {
            MyTaskRespVO vo = new MyTaskRespVO();
            vo.setId(t.getId());
            vo.setTaskTitle(t.getTaskTitle());
            vo.setProjectId(t.getProjectId());
            ProjectDO project = projectMap.get(t.getProjectId());
            vo.setProjectName(project == null ? null : project.getProjectName());
            vo.setExecutionId(t.getExecutionId());
            ProjectExecutionDO execution = executionMap.get(t.getExecutionId());
            vo.setExecutionName(execution == null ? null : execution.getExecutionName());
            vo.setStatusCode(t.getStatusCode());
            vo.setPriority(t.getPriority());
            vo.setPlannedEndDate(t.getPlannedEndDate());
            vo.setCreateTime(t.getCreateTime());
            vo.setParentTaskId(t.getParentTaskId());
            vo.setProgressRate(normalizeProgress(t.getProgressRate()));
            // SQL 已保证至少一种身份；owner 优先（双重身份返 owner）
            vo.setMyRole(Objects.equals(t.getOwnerId(), loginUserId) ? "owner" : "collaborator");
            return vo;
        }).collect(Collectors.toList());
        applyLifecycle(tasks, all);
        return paginate(all, reqVO);
    }

    private void applyLifecycle(List<ProjectTaskDO> tasks, List<MyTaskRespVO> vos) {
        Map<Long, ProjectTaskStatusViewService.ProjectTaskLifecycleView> lifecycleMap =
                projectTaskStatusViewService.getLifecycleMap(tasks);
        for (MyTaskRespVO vo : vos) {
            ProjectTaskStatusViewService.ProjectTaskLifecycleView lifecycle = lifecycleMap.get(vo.getId());
            if (lifecycle == null) {
                vo.setAvailableActions(Collections.emptyList());
                continue;
            }
            vo.setStatusName(lifecycle.statusName());
            vo.setTerminal(lifecycle.terminal());
            vo.setAllowEdit(lifecycle.allowEdit());
            vo.setAvailableActions(lifecycle.availableActions());
        }
    }

    private BigDecimal normalizeProgress(BigDecimal progressRate) {
        return progressRate == null ? BigDecimal.ZERO : progressRate;
    }

    /** 内存分页，与 MyProjectServiceImpl#paginate 同款（pageSize<0 拉全部）。 */
    private <T> PageResult<T> paginate(List<T> all, PageParam reqVO) {
        long total = all.size();
        Integer pageSize = reqVO.getPageSize();
        if (pageSize == null || pageSize < 0) {
            return new PageResult<>(all, total);
        }
        int pageNo = reqVO.getPageNo() == null || reqVO.getPageNo() < 1 ? 1 : reqVO.getPageNo();
        int fromIndex = Math.min((pageNo - 1) * pageSize, all.size());
        int toIndex = Math.min(fromIndex + pageSize, all.size());
        return new PageResult<>(all.subList(fromIndex, toIndex), total);
    }

}
