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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.core.application.service.AbstractDictService;
import com.casic.missiles.core.model.auth.AuthUser;
import com.casic.missiles.core.shiro.ShiroKit;
import com.casic.missiles.dto.BaseApprovalSubmitRequest;
import com.casic.missiles.dto.ReturnDTO;
import com.casic.missiles.dto.ReturnUtil;
import com.casic.missiles.dto.business.siteExecutive.BusinessSiteExecutiveDetail;
import com.casic.missiles.dto.business.siteExecutive.SiteExecutiveApprovalListRequest;
import com.casic.missiles.dto.business.siteExecutive.SiteExecutiveApprovalListResponse;
import com.casic.missiles.dto.flowable.AllApproveDTO;
import com.casic.missiles.dto.flowable.ApprovalDeleteRequest;
import com.casic.missiles.dto.flowable.ToBeApprovedDTO;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.PrefixCodeEnum;
import com.casic.missiles.enums.meter.MeterDictEnum;
import com.casic.missiles.enums.system.ApprovalStatusEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.business.BusinessSiteExecutiveInfoMapper;
import com.casic.missiles.model.business.BusinessOrder;
import com.casic.missiles.model.business.BusinessSiteExecutiveInfo;
import com.casic.missiles.model.equipment.EquipmentFixedAssets;
import com.casic.missiles.model.response.ResponseData;
import com.casic.missiles.modular.system.service.IUserService;
import com.casic.missiles.service.IBaseApprovalService;
import com.casic.missiles.service.business.IBusinessOrderService;
import com.casic.missiles.service.business.IBusinessSiteExecutiveInfoEquipmentRelationService;
import com.casic.missiles.service.business.IBusinessSiteExecutiveInfoService;
import com.casic.missiles.service.business.IBusinessSiteExecutiveStaffRelationService;
import com.casic.missiles.service.flowable.ApprovalOperateService;
import com.casic.missiles.utils.ConvertUtils;
import com.casic.missiles.utils.DictCodeUtils;
import com.casic.missiles.utils.NumberGeneratorUtil;
import com.casic.missiles.utils.PageUtil;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 现场检测表 服务实现类
 * </p>
 *
 * @author wangpeng
 * @since 2023-03-25
 */
@Service
public class BusinessSiteExecutiveInfoServiceImpl extends ServiceImpl<BusinessSiteExecutiveInfoMapper, BusinessSiteExecutiveInfo> implements IBusinessSiteExecutiveInfoService {
    @Autowired
    private BusinessSiteExecutiveInfoMapper siteExecutiveInfoMapper;
    @Autowired
    private IBaseApprovalService baseApprovalService;
    @Resource
    private AbstractDictService dictService;
    @Autowired
    private IUserService userService;
    @Resource
    private RuntimeService runtimeService;
    @Autowired
    private ApprovalOperateService approvalOperateService;
    @Autowired
    private IBusinessOrderService orderService;
    @Autowired
    private IBusinessSiteExecutiveInfoEquipmentRelationService siteExecutiveEquipmentRelationService;
    @Autowired
    private IBusinessSiteExecutiveStaffRelationService siteExecutiveStaffRelationService;

    @Override
    public List<SiteExecutiveApprovalListResponse> siteExecutiveApprovalListPage(SiteExecutiveApprovalListRequest request, Page<SiteExecutiveApprovalListResponse> page) throws Exception {
        AuthUser user = ShiroKit.getUser();
        Assert.isFalse(Objects.isNull(user), () -> {
            throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED);
        });
        request.setCreateUserId(user.getId());
        List<SiteExecutiveApprovalListResponse> responseList = handleApprovalStatus(page, request);
        if (CollectionUtils.isEmpty(responseList)) {
            return new ArrayList<>();
        }
        for (SiteExecutiveApprovalListResponse response : responseList) {
            DictCodeUtils.convertDictCodeToName(response);
        }
        return responseList;
    }

    @Override
    public ReturnDTO siteExecutiveInfoSubmit(BaseApprovalSubmitRequest request) {
        //已取消后的提交需先删除原有实例
        if (StringUtils.isNotEmpty(request.getProcessId())) {
            runtimeService.updateBusinessStatus(request.getProcessId(), ApprovalStatusEnum.DELETED);
            runtimeService.deleteProcessInstance(request.getProcessId(), "删除");
        }
        //1.根据表单id获取流程定义id
        String formId = request.getFormId();
        //2.根据流程定义id启动流程实例
        ReturnDTO returnDTO = baseApprovalService.processSubmit(formId, request.getId());
        if (ResponseData.DEFAULT_SUCCESS_CODE != returnDTO.getCode()) {
            return returnDTO;
        }
        ProcessInstance processInstance = (ProcessInstance) returnDTO.getData();
        BusinessSiteExecutiveInfo siteExecutiveInfo = new BusinessSiteExecutiveInfo();
        siteExecutiveInfo.setId(request.getId());
        siteExecutiveInfo.setApprovalStatus(ApprovalStatusEnum.UN_DRAFT); //非草稿状态
        siteExecutiveInfo.setProcessId(processInstance.getId());
        siteExecutiveInfo.setUpdateTime(DateUtil.formatDateTime(new Date()));
        int row = this.baseMapper.updateById(siteExecutiveInfo);
        if (row <= 0) {
            throw new BusinessException(BusinessExceptionEnum.SITE_EXECUTIVE__SUBMIT_FAILED.getCode(), BusinessExceptionEnum.SITE_EXECUTIVE__SUBMIT_FAILED.getMessage());
        }
        return ReturnUtil.success();
    }

    @Override
    public ReturnDTO saveSiteExecutiveInfo(BusinessSiteExecutiveInfo siteExecutiveInfo) {
        initSiteExecutiveInfo(siteExecutiveInfo);
        if (this.baseMapper.insert(siteExecutiveInfo) > 0) {
            //加入现场检测人员绑定
            if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getMeterStaffList()) && siteExecutiveInfo.getMeterStaffList().size() > 0) {
                siteExecutiveStaffRelationService.saveBatch(siteExecutiveInfo.getId(), siteExecutiveInfo.getMeterStaffList());
            }
            //加入所用设备绑定
            if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getEquipmentInfoList()) && siteExecutiveInfo.getEquipmentInfoList().size() > 0) {
                siteExecutiveEquipmentRelationService.saveBatch(siteExecutiveInfo.getId(), siteExecutiveInfo.getEquipmentInfoList());
            }
            return ReturnUtil.success(siteExecutiveInfo.getId());
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    public ReturnDTO failUpdate(BusinessSiteExecutiveInfo siteExecutiveInfo) {
        AuthUser user = ShiroKit.getUser();
        Assert.isFalse(Objects.isNull(user), () -> {
            throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED);
        });
        if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getDirectorId())) {
            siteExecutiveInfo.setDirectorName(userService.getById(siteExecutiveInfo.getDirectorId()).getName());
        }
        if (this.baseMapper.updateById(siteExecutiveInfo) > 0) {
            baseApprovalService.failUpdate(siteExecutiveInfo.getProcessId());
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    public ReturnDTO approvalDelete(ApprovalDeleteRequest request) {
        ReturnDTO returnDTO = approvalOperateService.delete(request);
        if (ResponseData.DEFAULT_SUCCESS_CODE == returnDTO.getCode()) {
            //删除数据库记录
            if (this.baseMapper.deleteById(request.getId()) > 0) {
                return ReturnUtil.success();
            }
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    public ReturnDTO deleteBatchSiteExecutive(List<Long> ids) {

        if (baseMapper.deleteBatchIds(ids) > 0) {
            //删除检测人员绑定关系
            siteExecutiveStaffRelationService.deleteBySiteExecutiveIds(ids);
            //删除监测设备绑定关系
            siteExecutiveEquipmentRelationService.deleteBySiteExecutiveIds(ids);
            return ReturnUtil.success();
        }
        return ReturnUtil.failed("删除失败");
    }

    @Override
    public ReturnDTO draftUpdate(BusinessSiteExecutiveInfo siteExecutiveInfo) {
        if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getDirectorId())) {
            siteExecutiveInfo.setDirectorName(userService.getById(siteExecutiveInfo.getDirectorId()).getName());
        }
        if (this.baseMapper.updateById(siteExecutiveInfo) > 0) {
            //加入检测人员绑定
            if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getMeterStaffList()) && siteExecutiveInfo.getMeterStaffList().size() > 0) {
                siteExecutiveStaffRelationService.saveBatch(siteExecutiveInfo.getId(), siteExecutiveInfo.getMeterStaffList());
            }
            //加入所用设备绑定
            if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getEquipmentInfoList()) && siteExecutiveInfo.getEquipmentInfoList().size() > 0) {
                siteExecutiveEquipmentRelationService.saveBatch(siteExecutiveInfo.getId(), siteExecutiveInfo.getEquipmentInfoList());
            }
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    private void initSiteExecutiveInfo(BusinessSiteExecutiveInfo siteExecutiveInfo) {
        Long maxNo = this.baseMapper.selectMaxCode();
        String siteExecutiveNo = NumberGeneratorUtil.getContactNo(PrefixCodeEnum.SITE_EXECUTIVE_PREFIX, maxNo);
        AuthUser authUser = ShiroKit.getUser();
        siteExecutiveInfo.setApprovalStatus(ApprovalStatusEnum.DRAFT);
        if (ObjectUtil.isNotEmpty(siteExecutiveInfo.getDirectorId())) {
            siteExecutiveInfo.setDirectorName(userService.getById(siteExecutiveInfo.getDirectorId()).getName());
        }
        siteExecutiveInfo.setCreateUser(authUser.getId());
        siteExecutiveInfo.setSiteExecutiveNo(siteExecutiveNo);
        siteExecutiveInfo.setCreateTime(DateUtil.formatDateTime(new Date()));
    }

    @Override
    public BusinessSiteExecutiveDetail siteExecutiveInfoDetail(Long id) throws Exception {
        BusinessSiteExecutiveDetail businessSiteExecutiveDetail = new BusinessSiteExecutiveDetail();
        BusinessSiteExecutiveInfo siteExecutiveInfo = this.baseMapper.selectById(id);
        if (siteExecutiveInfo != null) {
            //查询是否有关联的检测人员
            siteExecutiveInfo.setMeterStaffList(siteExecutiveStaffRelationService.getStaffsByExecutiveInfoId(id));
            //查询是否有关联的监测设备
            siteExecutiveInfo.setEquipmentInfoList(siteExecutiveEquipmentRelationService.getEquipmentsByExecutiveInfoId(id));
            if (StringUtils.isNotEmpty(siteExecutiveInfo.getTaskSource())) {
                siteExecutiveInfo.setTaskSourceName(dictService.getDictNameByCode(MeterDictEnum.TASK_SOURCE, siteExecutiveInfo.getTaskSource()));
            }
        }
        businessSiteExecutiveDetail = ConvertUtils.sourceToTarget(siteExecutiveInfo, BusinessSiteExecutiveDetail.class);
        BusinessOrder businessOrder = orderService.orderDetail(businessSiteExecutiveDetail.getOrderId());
        populateBusinessSiteExecutiveDetail(businessSiteExecutiveDetail, businessOrder);
        for (EquipmentFixedAssets equipmentFixedAssets : businessSiteExecutiveDetail.getEquipmentInfoList()) {
            DictCodeUtils.convertDictCodeToName(equipmentFixedAssets);
        }
        return businessSiteExecutiveDetail;
    }

    private void populateBusinessSiteExecutiveDetail(BusinessSiteExecutiveDetail businessSiteExecutiveDetail, BusinessOrder businessOrder) {
        businessSiteExecutiveDetail.setCustomerAddress(businessOrder.getCustomerAddress());
        businessSiteExecutiveDetail.setCustomerName(businessOrder.getCustomerName());
        businessSiteExecutiveDetail.setCustomerPhone(businessOrder.getCustomerPhone());
        businessSiteExecutiveDetail.setDeliverer(businessOrder.getDeliverer());
        businessSiteExecutiveDetail.setDelivererTel(businessOrder.getDelivererTel());
        businessSiteExecutiveDetail.setOrderCode(businessOrder.getOrderCode());
        businessSiteExecutiveDetail.setCustomerNo(businessOrder.getCustomerNo());
    }

    private List<SiteExecutiveApprovalListResponse> handleApprovalStatus(Page<SiteExecutiveApprovalListResponse> page, SiteExecutiveApprovalListRequest request) {
        List<SiteExecutiveApprovalListResponse> approvalList = new ArrayList<>();
        List<String> businessKeys = new ArrayList<>();
        List<BusinessSiteExecutiveInfo> list;
        switch (request.getApprovalStatus()) {
            //草稿
            case ApprovalStatusEnum.DRAFT:
                approvalList = siteExecutiveInfoMapper.selectDraftListForApproval(page, request);
                approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.DRAFT);
                break;
            //待审批，该状态维护在flowable中
            case ApprovalStatusEnum.TO_BE_APPROVED:
                List<ToBeApprovedDTO> toBeApprovedList = baseApprovalService.getToBeApprovedList(request.getFormId());
                if (!CollectionUtils.isEmpty(toBeApprovedList)) {
                    businessKeys = toBeApprovedList.stream().map(ToBeApprovedDTO::getBusinessKey).distinct().collect(Collectors.toList());
                }
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.TO_BE_APPROVED);
                    //DTO根据业务主键补全taskId
                    approvalList.forEach(approval -> {
                        toBeApprovedList.forEach(toBeApprovedDTO -> {
                            if (String.valueOf(approval.getId()).equals(toBeApprovedDTO.getBusinessKey())) {
                                approval.setTaskId(toBeApprovedDTO.getTaskId());
                                //补全可选决策项
                                approval.setDecisionItem(toBeApprovedDTO.getDecisionItem());
                            }
                        });
                    });
                }
                break;
            //审批中，该状态维护在flowable中
            case ApprovalStatusEnum.IN_APPROVED:
                businessKeys = baseApprovalService.getInApprovedList(request.getFormId());
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.IN_APPROVED);
                }
                break;
            //已通过，该状态维护在flowable
            case ApprovalStatusEnum.PASSED:
                businessKeys = baseApprovalService.getPassedList(request.getFormId());
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.PASSED);
                }
                break;
            //未通过（包括拒绝、驳回，拒绝为直接删除实例，驳回为驳回到起点），该状态维护在flowable
            case ApprovalStatusEnum.FAILED:
                businessKeys = baseApprovalService.getFailedList(request.getFormId()); //未通过-拒绝
                List<String> rejectBusinessKey = baseApprovalService.getFailedRejectList(request.getFormId()); //未通过-驳回
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.FAILED);
                }
                List<SiteExecutiveApprovalListResponse> rejectApprovalList = new ArrayList<>();
                if (!CollectionUtils.isEmpty(rejectBusinessKey)) {
                    rejectApprovalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, rejectBusinessKey);
                    rejectApprovalList = handleApprovalListResponse(rejectApprovalList, ApprovalStatusEnum.FAILED_REJECT);
                }
                //合并未通过-拒绝和未通过-驳回
                approvalList.addAll(rejectApprovalList);
                //分页处理
                if(!CollectionUtils.isEmpty(approvalList)) {
                    Page pages = PageUtil.getPages((int) page.getCurrent(), (int) page.getSize(), approvalList);
                    page.setTotal(approvalList.size());
                    approvalList = pages.getRecords();
                }
                break;
            //已取消，该状态维护在flowable
            case ApprovalStatusEnum.CANCELED:
                businessKeys = baseApprovalService.getCanceledList(request.getFormId());
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleApprovalListResponse(approvalList, ApprovalStatusEnum.CANCELED);
                }
                break;
            //全部
            //区分管理员和普通用户
            //普通用户获取自己发起的(审批中、已通过、未通过、已取消)，管理员获取全部(审批中、已通过、未通过、已取消)
            case ApprovalStatusEnum.ALL:
                List<AllApproveDTO> AllApproveList = baseApprovalService.getAllList(request.getFormId());
                if (!CollectionUtils.isEmpty(AllApproveList)) {
                    businessKeys = AllApproveList.stream().map(AllApproveDTO::getBusinessKey).collect(Collectors.toList());
                }
                if (!CollectionUtils.isEmpty(businessKeys)) {
                    approvalList = siteExecutiveInfoMapper.selectBatchForApproval(page, request, businessKeys);
                    approvalList = handleAllApprovalListResponse(approvalList, AllApproveList);
                }
                break;
        }
        return approvalList;
    }

    private List<SiteExecutiveApprovalListResponse> handleApprovalListResponse(List<SiteExecutiveApprovalListResponse> approvalList, String status) {
//        approvalList = ConvertUtils.sourceToTarget(list, SiteExecutiveApprovalListResponse.class);
        approvalList.stream().forEach(result -> {
            //审批状态两种获取方式：1、在此处设置，2、在flowable中设置业务状态，暂采取1
            result.setApprovalStatusName(dictService.getDictNameByCode(MeterDictEnum.APPROVAL_STATUS, status));
        });
        return approvalList;
    }

    private List<SiteExecutiveApprovalListResponse> handleAllApprovalListResponse(List<SiteExecutiveApprovalListResponse> approvalList, List<AllApproveDTO> allApproveList) {
        Map<String, String> taskMap = new HashMap<>();
//        approvalList = ConvertUtils.sourceToTarget(list, SiteExecutiveApprovalListResponse.class);
        allApproveList.forEach(allApprove -> {
            taskMap.put(allApprove.getBusinessKey(), allApprove.getStatus());
        });
        //状态补全
        approvalList.forEach(approval -> {
            approval.setApprovalStatusName(dictService.getDictNameByCode(MeterDictEnum.APPROVAL_STATUS, taskMap.get(String.valueOf(approval.getId()))));
            approval.setApprovalStatus(taskMap.get(String.valueOf(approval.getId())));
        });
        //排序
        return approvalList.stream().sorted(Comparator.comparing(SiteExecutiveApprovalListResponse::getCreateTime).reversed()).collect(Collectors.toList());
    }
}
