package com.izouma.jmrh.service;

import com.izouma.jmrh.domain.Approval;
import com.izouma.jmrh.domain.ApprovalProcess;
import com.izouma.jmrh.domain.User;
import com.izouma.jmrh.enums.ApprovalProcessStatus;
import com.izouma.jmrh.enums.ApprovalStatus;
import com.izouma.jmrh.exception.BusinessException;
import com.izouma.jmrh.repo.ApprovalProcessRepo;
import com.izouma.jmrh.repo.ApprovalRepo;
import com.izouma.jmrh.repo.ApproverRepo;
import com.izouma.jmrh.repo.UserRepo;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class ApprovalProcessService {

    private ApprovalProcessRepo approvalProcessRepo;
    private ApprovalRepo        approvalRepo;
    private UserRepo            userRepo;

    public Page<ApprovalProcess> my(Long userId, Integer status, Pageable pageable) {
        if (status != null && status == 0) {
            return approvalProcessRepo.findByUserIdAndStatusInOrderByCreatedAtDesc(userId, Arrays
                    .asList(ApprovalProcessStatus.PENDING), pageable);
        } else if (status != null && status == 1) {
            return approvalProcessRepo.findByUserIdAndStatusInOrderByCreatedAtDesc(userId, Arrays
                    .asList(ApprovalProcessStatus.PASS, ApprovalProcessStatus.DENY), pageable);
        } else if (status != null && status == 2) {
            return approvalProcessRepo
                    .findByUserIdAndApprovalStatusOrderByCreatedAtDesc(userId, ApprovalStatus.FINISH, pageable);
        }
        return approvalProcessRepo.findByUserIdOrderByCreatedAtDesc(userId, pageable);
    }

    @Transactional
    public void startProcess(Long id) {
        ApprovalProcess process = approvalProcessRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        Approval approval = process.getApproval();

        if (process.getStatus() != ApprovalProcessStatus.PENDING || process.getLevel() != 0) {
            throw new BusinessException("状态错误");
        }

        process.setApprovalTime(LocalDateTime.now());
        process.setStatus(ApprovalProcessStatus.PASS);

        List<User> users = userRepo.findAllById(approval.getApprover1());
        approval.setStatus(ApprovalStatus.LEVEL_1);
        approval.setCurrentApprover(users.stream().map(User::getUsername).collect(Collectors.joining("，")));
        approvalRepo.save(approval);

        for (User user : users) {
            ApprovalProcess approvalProcess = approvalProcessRepo.save(ApprovalProcess.builder()
                    .approvalId(approval.getId())
                    .approver(user.getUsername())
                    .level(1)
                    .userId(user.getId())
                    .status(ApprovalProcessStatus.PENDING)
                    .build());
        }
    }

    public void next(Long id, boolean pass, String remark, List<Long> nextApprovers) {
        ApprovalProcess process = approvalProcessRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        process.setApprovalTime(LocalDateTime.now());
        process.setStatus(pass ? ApprovalProcessStatus.PASS : ApprovalProcessStatus.DENY);
        process.setRemark(remark);
        approvalProcessRepo.save(process);

        Approval approval = process.getApproval();
        Set<Long> approvers = new HashSet<>(nextApprovers);
        switch (process.getLevel()) {
            case 1:
                if (approval.getApprover2() != null) {
                    approvers.addAll(approval.getApprover2());
                }
                approval.setApprover2(new ArrayList<>(approvers));
                break;
            case 2:
                if (approval.getApprover3() != null) {
                    approvers.addAll(approval.getApprover3());
                }
                approval.setApprover3(new ArrayList<>(approvers));
                break;
            case 3:
                if (approval.getApprover4() != null) {
                    approvers.addAll(approval.getApprover4());
                }
                approval.setApprover4(new ArrayList<>(approvers));
                break;
            case 4:
                if (approval.getApprover5() != null) {
                    approvers.addAll(approval.getApprover5());
                }
                approval.setApprover5(new ArrayList<>(approvers));
                break;
        }

        long num = approvalProcessRepo.countByApprovalIdAndLevelAndStatus(approval.getId(), process
                .getLevel(), ApprovalProcessStatus.PENDING);
        if (num == 0) {
            if (approval.getStatus() == ApprovalStatus.LEVEL_5) {
                approval.setStatus(ApprovalStatus.FINISH);
            } else {
                if (approvers.isEmpty()) {
                    approval.setStatus(ApprovalStatus.FINISH);
                } else {
                    List<User> users = userRepo.findAllById(approvers);
                    for (User user : users) {
                        approvalProcessRepo.save(ApprovalProcess.builder()
                                .userId(user.getId())
                                .approver(user.getUsername())
                                .approvalId(approval.getId())
                                .status(ApprovalProcessStatus.PENDING)
                                .level(process.getLevel() + 1)
                                .build());
                    }
                    approval.setCurrentApprover(users.stream().map(User::getUsername).collect(Collectors.joining(",")));
                }
            }
        }
        approvalRepo.save(approval);
    }
}
