package com.zcloud.safetyDutyList.command.tasklist;

import com.alibaba.cola.exception.BizException;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskDetailGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskListIssueGateway;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskDetailE;
import com.zcloud.safetyDutyList.dto.clientobject.tasklist.TaskDetailCO;
import com.zcloud.safetyDutyList.dto.tasklist.TaskDetailSaveBatchCmd;
import com.zcloud.safetyDutyList.persistence.dataobject.tasklist.TaskDetailDO;
import com.zcloud.safetyDutyList.persistence.repository.tasklist.TaskDetailRepository;
import jodd.util.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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

@Component
@AllArgsConstructor
public class TaskDetailSaveBatchExe {
    private final TaskDetailGateway taskDetailGateway;
    private final TaskDetailRepository taskDetailRepository;
    private final TaskListIssueGateway taskListIssueGateway;

    @Transactional(rollbackFor = Exception.class)
    public List<TaskDetailCO> execute(List<TaskDetailSaveBatchCmd> cmds) {
        if (cmds == null || cmds.isEmpty()) {
            throw new BizException("参数不能为空");
        }

        // 获取已存在的任务详情列表
        String taskListId = cmds.get(0).getTaskListId();

        if (taskListIssueGateway.isIssued(taskListId)) {
            throw new BizException("清单已下发，禁止修改");
        }

        List<TaskDetailE> existDetails = taskDetailGateway.listByTaskListId(taskListId);

        Map<Long, TaskDetailE> existDetailMap = existDetails.stream()
                .collect(Collectors.toMap(TaskDetailE::getId, Function.identity(), (o, n) -> o));

        // 获取要删除的ID
        List<Long> cmdIds = cmds.stream()
                .map(TaskDetailSaveBatchCmd::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        List<Long> toDeleteIds = existDetails.stream()
                .map(TaskDetailE::getId)
                .filter(id -> !cmdIds.contains(id))
                .collect(Collectors.toList());

        BigDecimal totalScore = BigDecimal.ZERO;
        List<TaskDetailE> toAdd = new ArrayList<>();
        List<TaskDetailE> toUpdate = new ArrayList<>();

        for (TaskDetailSaveBatchCmd cmd : cmds) {
            if (cmd.getId() == null) {
                TaskDetailE detailE = new TaskDetailE();
                BeanUtils.copyProperties(cmd, detailE);
                if (StringUtil.isEmpty(cmd.getTaskDetailId())) {
                    detailE.init();
                } else {
                    detailE.setTaskDetailId(cmd.getTaskDetailId());
                }
                toAdd.add(detailE);
            } else {
                TaskDetailE existDetail = existDetailMap.get(cmd.getId());
                if (existDetail == null) {
                    throw new BizException("任务详情不存在，id=" + cmd.getId());
                }
                existDetail.setExecuteContent(cmd.getExecuteContent());
                existDetail.setFeedbackCycleType(cmd.getFeedbackCycleType());
                existDetail.setTaskScore(cmd.getTaskScore());
                toUpdate.add(existDetail);
            }
            if (cmd.getTaskScore() != null) {
                totalScore = totalScore.add(cmd.getTaskScore());
            }
        }

        BigDecimal remainScore = existDetails.stream()
                .filter(d -> !cmdIds.contains(d.getId()) && !toDeleteIds.contains(d.getId()))
                .map(TaskDetailE::getTaskScore)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        totalScore = totalScore.add(remainScore);

        if (totalScore.compareTo(new BigDecimal("100")) > 0) {
            throw new BizException("当前清单总分不能超过100");
        }

        for (Long deleteId : toDeleteIds) {
            taskDetailGateway.deleteById(deleteId);
        }

        if (!toAdd.isEmpty()) {
            taskDetailGateway.batchAdd(toAdd);
        }

        for (TaskDetailE detailE : toUpdate) {
            taskDetailGateway.update(detailE);
        }

        List<TaskDetailDO> latestDetails = taskDetailRepository.listByTaskListId(taskListId);
        return latestDetails.stream().map(detailE -> {
            TaskDetailCO co = new TaskDetailCO();
            BeanUtils.copyProperties(detailE, co);
            return co;
        }).collect(Collectors.toList());
    }
}
