package com.casic.missiles.service.Impl.equipment;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.casic.missiles.core.base.service.IBaseExportService;
import com.casic.missiles.core.model.auth.AuthUser;
import com.casic.missiles.core.shiro.ShiroKit;
import com.casic.missiles.dto.IdDTO;
import com.casic.missiles.dto.ReturnDTO;
import com.casic.missiles.dto.ReturnUtil;
import com.casic.missiles.dto.equipment.AcceptanceCheck;
import com.casic.missiles.dto.equipment.AcceptanceCheckRequest;
import com.casic.missiles.dto.flowable.AllApproveDTO;
import com.casic.missiles.dto.flowable.ToBeApprovedDTO;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.ExportEnum;
import com.casic.missiles.enums.PrefixCodeEnum;
import com.casic.missiles.enums.equipment.EquipmentApplyTypeEnum;
import com.casic.missiles.enums.system.ApprovalStatusEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.equipment.EquipmentAcceptanceCheckMapper;
import com.casic.missiles.mapper.equipment.EquipmentApplyEquipmentMapper;
import com.casic.missiles.mapper.equipment.EquipmentApplyFileMapper;
import com.casic.missiles.mapper.equipment.EquipmentApplyMapper;
import com.casic.missiles.model.equipment.EquipmentApply;
import com.casic.missiles.model.equipment.EquipmentApplyEquipment;
import com.casic.missiles.model.equipment.EquipmentApplyFile;
import com.casic.missiles.service.IBaseApprovalService;
import com.casic.missiles.service.equipment.IEquipmentAcceptanceCheckService;
import com.casic.missiles.service.equipment.IEquipmentApplyEquipmentService;
import com.casic.missiles.service.equipment.IEquipmentApplyFileService;
import com.casic.missiles.utils.DictCodeUtils;
import com.casic.missiles.utils.NumberGeneratorUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service("IEquipmentAcceptanceCheckService")
public class EquipmentApplyAcceptanceCheckServiceImpl implements IEquipmentAcceptanceCheckService {

    @Resource
    private EquipmentApplyMapper equipmentApplyMapper;

    @Resource
    private EquipmentAcceptanceCheckMapper acceptanceCheckMapper;

    @Resource
    private IBaseApprovalService baseApprovalService;

    @Resource
    private EquipmentApplyEquipmentMapper equipmentApplyEquipmentMapper;

    @Resource
    private EquipmentApplyFileMapper equipmentApplyFileMapper;

    @Resource
    private IEquipmentApplyEquipmentService equipmentApplyEquipmentService;

    @Resource
    private IEquipmentApplyFileService equipmentApplyFileService;

    @Resource
    private IBaseExportService iBaseExportService;

    @Resource
    private TaskService taskService;

    @Resource
    private RuntimeService runtimeService;

    @Override
    public Page<AcceptanceCheck> acceptanceCheckList(Page<AcceptanceCheck> page, AcceptanceCheckRequest request) throws Exception {
        boolean searchBusinessKey = true;
        List<String> businessKeys = new ArrayList<>();
        List<String> rejectBusinessKey = new ArrayList<>();// 未通过-驳回
        Map<String,String> taskMap = new HashMap<>(); // businessKey-taskId, 待审批列表用
        Map<String,Integer> decisionItemMap = new HashMap<>(); // 可选决策项map
        String status = request.getApprovalStatus();
        switch (status){
            // 待审批 获取业务id,以及taskId
            case ApprovalStatusEnum.TO_BE_APPROVED:
                List<ToBeApprovedDTO> toBeApprovedList = baseApprovalService.getToBeApprovedList(request.getFormId());
                businessKeys = toBeApprovedList.stream().map(ToBeApprovedDTO::getBusinessKey).distinct().collect(Collectors.toList());
                toBeApprovedList.forEach(toBeApprovedDTO -> {taskMap.put(toBeApprovedDTO.getBusinessKey(),toBeApprovedDTO.getTaskId());});
                toBeApprovedList.forEach(toBeApprovedDTO -> {decisionItemMap.put(toBeApprovedDTO.getBusinessKey(),toBeApprovedDTO.getDecisionItem());});
                break;
            // 审批中
            case ApprovalStatusEnum.IN_APPROVED:
                businessKeys = baseApprovalService.getInApprovedList(request.getFormId());
                break;
            // 已通过
            case ApprovalStatusEnum.PASSED:
                businessKeys = baseApprovalService.getPassedList(request.getFormId());
                break;
            // 未通过
            case ApprovalStatusEnum.FAILED:
                businessKeys = baseApprovalService.getFailedList(request.getFormId()); //未通过-拒绝
                rejectBusinessKey = baseApprovalService.getFailedRejectList(request.getFormId()); //未通过-驳回
                businessKeys.addAll(rejectBusinessKey);
                break;
            // 已取消
            case ApprovalStatusEnum.CANCELED:
                businessKeys = baseApprovalService.getCanceledList(request.getFormId());
                break;
            case ApprovalStatusEnum.ALL:
                List<AllApproveDTO> allList = baseApprovalService.getAllList(request.getFormId());
                businessKeys = allList.stream().map(AllApproveDTO::getBusinessKey).distinct().collect(Collectors.toList());
                allList.forEach(allApprovedDTO -> {taskMap.put(allApprovedDTO.getBusinessKey(),allApprovedDTO.getStatus());});
                break;
            default:
                // 草稿箱，直接查表，不用查工作流
                searchBusinessKey = false;
                break;
        }
        // 判断是否需要通过业务id查询数据
        if(searchBusinessKey){
            if(CollectionUtils.isEmpty(businessKeys)){
                return page;
            }else {
                // 审批状态
                request.setApprovalStatus(null);
                request.setBusinessKeys(businessKeys);
            }
        }
        // 申请类型-保养验收单
        request.setApplyType(EquipmentApplyTypeEnum.REPAIR_APPLY);
        Page<AcceptanceCheck> resultPage = acceptanceCheckMapper.acceptanceCheckList(page, request);
        for (AcceptanceCheck equipmentApply : resultPage.getRecords()) {
            if(searchBusinessKey){
                // 不是全查或草稿箱，赋值对应审批状态
                equipmentApply.setApprovalStatus(status);
                // 未通过-驳回状态
                if(status.equals(ApprovalStatusEnum.FAILED) && rejectBusinessKey.contains(equipmentApply.getId().toString())){
                    equipmentApply.setApprovalStatus(ApprovalStatusEnum.FAILED_REJECT);
                }
            }
            // 待审批状态-赋值taskId
            if(ApprovalStatusEnum.TO_BE_APPROVED.equals(status)){
                equipmentApply.setTaskId(taskMap.get(equipmentApply.getId().toString()));
                equipmentApply.setDecisionItem(decisionItemMap.get(equipmentApply.getId().toString()));
            }
            if(ApprovalStatusEnum.ALL.equals(status)){
                equipmentApply.setApprovalStatus(taskMap.get(String.valueOf(equipmentApply.getId())));
            }
            DictCodeUtils.convertDictCodeToName(equipmentApply);
        }
        return resultPage;
    }

    @Override
    public Object acceptanceCheckInfo(IdDTO idDTO) throws Exception {
        // 通过id查询出检修保养基本信息
        AcceptanceCheck acceptanceCheckInfo = acceptanceCheckMapper.acceptanceCheckInfo(idDTO.getId());
        // 通过验收单id查询出对应的检修设备列表
        List<EquipmentApplyEquipment> checkList = equipmentApplyEquipmentMapper.queryCheckList(String.valueOf(acceptanceCheckInfo.getId()));
        for (EquipmentApplyEquipment applyEquipment : checkList) {
            // 替换字典值
            DictCodeUtils.convertDictCodeToName(applyEquipment);
        }
        acceptanceCheckInfo.setCheckList(checkList);
        // 通过申请id获取对应附件列表
        QueryWrapper<EquipmentApplyFile> wrapper = new QueryWrapper<>();
        wrapper.eq("apply_id",idDTO.getId());
        List<EquipmentApplyFile> equipmentApplyFiles = equipmentApplyFileMapper.selectList(wrapper);
        acceptanceCheckInfo.setFileList(equipmentApplyFiles);
        return acceptanceCheckInfo;
    }

    @Override
    @Transactional
    public ReturnDTO addAcceptanceCheck(EquipmentApply equipmentApply) {
        Long maxNo = equipmentApplyMapper.selectMaxNo();
        // 生成编号
        String applyNo = NumberGeneratorUtil.getContactNo(PrefixCodeEnum.REPAIR_MAINTAIN_PREFIX, maxNo);
        equipmentApply.setApplyNo(applyNo);
        // 草稿箱状态
        equipmentApply.setApprovalStatus(ApprovalStatusEnum.DRAFT);
        if(StringUtils.isEmpty(equipmentApply.getCreateUser()) && ShiroKit.getUser() != null){
            equipmentApply.setCreateUser(ShiroKit.getUser().getId().toString());
        }
        // 新增基本信息
        if(equipmentApplyMapper.insert(equipmentApply)>0){
            // 修改设备列表
//            equipmentApplyEquipmentService.updateBatchById(equipmentApply.getEquipmentList());
            boolean equipmentSaveBatchFlg = true;
            // 新增设备信息
            if(!CollectionUtils.isEmpty(equipmentApply.getEquipmentList())){
                for (EquipmentApplyEquipment eq : equipmentApply.getEquipmentList()) {
                    eq.setId(null);
                    eq.setApplyId(String.valueOf(equipmentApply.getId()));
                }
                equipmentSaveBatchFlg = equipmentApplyEquipmentService.saveBatch(equipmentApply.getEquipmentList());
            }
            if(!equipmentSaveBatchFlg) throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            // 新增附件列表
            if(null != equipmentApply.getFileList() && equipmentApply.getFileList().size() != 0){
                equipmentApply.getFileList().forEach(bean->bean.setApplyId(equipmentApply.getId()));
                boolean flag = equipmentApplyFileService.saveBatch(equipmentApply.getFileList());
                if(!flag) throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            }
            return ReturnUtil.success(equipmentApply.getId());
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    @Transactional
    public ReturnDTO updateAcceptanceCheckInfo(EquipmentApply equipmentApply) {
        // 编辑验收报验单基本信息
        int updateFlag = equipmentApplyMapper.updateById(equipmentApply);
        // 编辑检修设备列表
        boolean updateBatchFlag= equipmentApplyEquipmentService.updateBatchById(equipmentApply.getEquipmentList());
        if(updateFlag>0 && updateBatchFlag){
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    public void exportList(AcceptanceCheckRequest request, HttpServletResponse response) {
        try {
            List<AcceptanceCheck> resultList;
            // 判断是否为通过ids导出
            if(!CollectionUtils.isEmpty(request.getIds())){
                AcceptanceCheckRequest checkRequest = new AcceptanceCheckRequest();
                checkRequest.setIds(request.getIds());
                resultList = acceptanceCheckMapper.acceptanceCheckList(checkRequest);
            }else{
                request.setBusinessKeys(EquipmentStateManageServiceImpl.getBusinessKeys(request.getApprovalStatus(), request.getFormId(),baseApprovalService));
                if(!request.getApprovalStatus().equals(ApprovalStatusEnum.DRAFT)){
                    request.setApprovalStatus(null);
                }
                resultList = acceptanceCheckMapper.acceptanceCheckList(request);
            }
            iBaseExportService.exportExcel(response, AcceptanceCheck.class,resultList, ExportEnum.METER_ACCEPTANCE_CHECK.getSheetName());
        } catch (IOException e) {
            log.error("样品导出出现异常，异常信息为:", e);
            e.printStackTrace();
        }

    }

    @Override
    @Transactional
    public ReturnDTO failUpdate(EquipmentApply equipmentApply) {
        AuthUser user = ShiroKit.getUser();
        Assert.isFalse(Objects.isNull(user), () -> {
            throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED);
        });
        // 编辑验收报验单基本信息
        int updateFlg = equipmentApplyMapper.updateById(equipmentApply);
        // 编辑检修设备列表
        boolean updateBatchFlag= equipmentApplyEquipmentService.updateBatchById(equipmentApply.getEquipmentList());
        if(updateFlg>0 && updateBatchFlag){
            baseApprovalService.failUpdate(equipmentApply.getProcessId());
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

}
