package com.yeejoin.amos.boot.module.jyjc.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.dao.mapper.DataDictionaryMapper;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.common.api.dto.AttachmentDto;
import com.yeejoin.amos.boot.module.jyjc.api.entity.JyjcOpeningApplication;
import com.yeejoin.amos.boot.module.jyjc.api.enums.BizTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.OpenBizTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcBaseMapper;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcOpeningApplicationMapper;
import com.yeejoin.amos.boot.module.jyjc.api.model.*;
import com.yeejoin.amos.boot.module.jyjc.api.service.IJyjcOpeningApplicationService;
import com.yeejoin.amos.boot.module.jyjc.biz.config.BaseException;
import com.yeejoin.amos.boot.module.jyjc.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jyjc.biz.service.TaskModelServiceImpl;
import com.yeejoin.amos.boot.module.ymt.api.dto.TzBaseEnterpriseInfoDto;
import com.yeejoin.amos.boot.module.ymt.api.dto.TzBaseUnitLicenceDto;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzsUserInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.vo.TzsUserInfoVo;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

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


/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-12-13
 */
@Service
@Slf4j
public class JyjcOpeningApplicationServiceImpl extends BaseService<JyjcOpeningApplicationModel, JyjcOpeningApplication, JyjcOpeningApplicationMapper> implements IJyjcOpeningApplicationService {

    @Autowired
    CommonserviceImpl commonserviceImpl;
    @Autowired
    private TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    JyjcOpeningApplicationMapper jyjcOpeningApplicationMapper;

    @Resource(type = JyjcBaseMapper.class)
    private JyjcBaseMapper baseMapper;

    @Value("${process-definition-key.jyjc.openapplication:}")
    private String processDefinitionKey;

    @Value("${jy.user-post:66151}")
    private String jyUserPost;

    @Value("${jy.cert.type.code:1233-1}")
    private String jyCertTypeCode;

    @Value("${jc.user-post:66152}")
    private String jcUserPost;

    @Value("${jc.cert.type.code:1233-2}")
    private String jcCertTypeCode;

    @Value("classpath:/json/bizTypeInfo.json")
    private org.springframework.core.io.Resource bizTypeInfo;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private TzBaseEnterpriseInfoMapper enterpriseInfoMapper;

    @Autowired
    private TzsUserInfoMapper userInfoMapper;

    @Autowired
    CommonserviceImpl commonservice;

    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;

    @Autowired
    TaskModelServiceImpl commonServiceImpl;

    @Autowired
    DataDictionaryMapper dataDictionaryMapper;

    private static Map<String, DictionarieValueModel> permissionLevelMap;

    private static List<DictionarieValueModel> permissionItemList;

    private final static String INDUSTRY_SUPERVISOR_DICT_TYPE = "HYZGBM";

    /**
     * 人员级别字典KEY
     */
    private final static String RYJB_JYJC_DICT_KEY = "RYJB_JYJC";

    /**
     * 所有人员资质检验检测项目key
     */
    private final static String  ZZXM_JYJC_DICT_KEY  = "ZZXM_JYJC_ALL";



    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public JyjcOpeningApplicationModel saveOrUpdateModel(JyjcOpeningApplicationModel model, Boolean enableStartFlow) {
        boolean isUpdate = false;
        String instanceId = null;
        JyjcOpeningApplication entity = null;
        if (model.getSequenceNbr() != null) {
            entity = jyjcOpeningApplicationMapper.selectById(model.getSequenceNbr());
            if (entity != null) {
                instanceId = entity.getWorkflowProstanceId();
                isUpdate = true;
            }
        }
        List<String> codes = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.JY.getCode(), 1).getResult();
        model.setApplicationSeq(codes.get(0));
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        model.setPromoter(reginParams.getUserModel().getUserId());
        if (!isUpdate) {
            CompanyBo companyBo = commonserviceImpl.getReginParamsOfCurrentUser().getCompany();
            model.setUnitCode(companyBo.getCompanyCode());
            model.setUnitCodeName(companyBo.getCompanyName());
            model.setCreateUserId(reginParams.getUserModel().getUserId());
            this.createWithModel(model);
        }
        if (enableStartFlow) {
            model.setStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
            model.setApplyTime(new Date());
            if (StringUtils.isBlank(instanceId)) {
                // 未开启过工作流则进行开启 startProcess
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                ArrayList<ActWorkflowStartDTO> list = new ArrayList<>();
                dto.setProcessDefinitionKey(processDefinitionKey);
                dto.setBusinessKey("1");
                dto.setCompleteFirstTask(Boolean.TRUE);
                // 接受机构
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
                if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                    WorkflowResultDto workflowResultDto = resultDto.get(0);
                    model.setWorkflowProstanceId(workflowResultDto.getInstanceId());
                    model.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
                    model.setNextTaskId(workflowResultDto.getNextTaskId());
                    model.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    // 创建代办
                    buildTask(model, workflowResultDto);
                }
            } else {
                // 存在流程，执行
                HashMap<String, Object> map = new HashMap<>();
                map.put("sequenceNbr", model.getSequenceNbr());
                map.put("op", "0");
                map.put("comments", "提交");
                JyjcOpeningApplication jyjcOpeningApplication = executeFlow(map);
                model.setNextTaskId(jyjcOpeningApplication.getNextTaskId());
            }

        } else {
            // 只有第一次改为待提交
            if (entity == null) {
                model.setStatus(FlowStatusEnum.TO_BE_SUBMITTED.getCode() + "");
                // 暂存生成代办逻辑
                ArrayList<TaskModelDto> list = new ArrayList<>();
                TaskModelDto dto = new TaskModelDto();
                TaskMessageDto taskMessageDto = new TaskMessageDto();
                BeanUtil.copyProperties(model, taskMessageDto);
                // 数据参数
                dto.setModel(taskMessageDto);
                // 摘要
                dto.setTaskContent(String.format("检验检测业务开通办理，【申请单号：%s】", model.getApplicationSeq()));
                // 申请单号
                dto.setTaskCode(model.getApplicationSeq());
                // 业务类型
                dto.setTaskType(BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
                // 业务主键
                dto.setRelationId(String.valueOf(model.getSequenceNbr()));
                dto.setNextExecuteUser("");
                list.add(dto);
                commonServiceImpl.buildTaskModel(list);
            }
        }
        model.setStatusName(FlowStatusEnum.getNameByType(Long.parseLong((model.getStatus()))));
        return this.updateWithModel(model);

    }

    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public JyjcOpeningApplicationModel resubmit(JyjcOpeningApplicationModel model) {
        model.setStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode() + "");
        model = this.updateWithModel(model);
        executeFlow(MapBuilder.<String, Object>create().put("op", "0").put("instanceId", model.getWorkflowProstanceId()).put("comments", "").build());
        return model;
    }


    /**
     * 完成的时候废弃其他已完成的申请单
     *
     * @param unitCode    unitCode
     * @param sequenceNbr sequenceNbr
     * @param openBizType 按照单位及开通业务类型进进行作废
     * @throws
     * @author yangyang
     * @date 2023/12/22 09:23
     */
    private void doDiscard(String unitCode, Long sequenceNbr, String openBizType) {
        List<Long> ids = this.lambdaQuery().select(JyjcOpeningApplication::getSequenceNbr)
                .eq(JyjcOpeningApplication::getUnitCode, unitCode)
                .eq(JyjcOpeningApplication::getOpenBizType, openBizType)
                .ne(JyjcOpeningApplication::getSequenceNbr, sequenceNbr)
                .eq(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getCode())
                .list().stream().filter(o -> !o.getSequenceNbr().equals(sequenceNbr))
                .map(JyjcOpeningApplication::getSequenceNbr).collect(Collectors.toList());
        if (ValidationUtil.isEmpty(ids)) {
            return;
        }
        LambdaUpdateWrapper<JyjcOpeningApplication> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_DISCARD.getCode())
                .set(JyjcOpeningApplication::getStatusName, FlowStatusEnum.TO_BE_DISCARD.getName())
                .set(JyjcOpeningApplication::getRemark, "到期作废")
                .in(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, ids);
        this.update(updateWrapper);
    }

    public Boolean doDiscard(Long sequenceNbr, String remark) {
        if (sequenceNbr == null) {
            throw new BadRequest("sequenceNbr不能为空！");
        }
        JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
        if (jyjcOpeningApplication == null) {
            return false;
        }
        if (!String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()).equals(jyjcOpeningApplication.getStatus())) {
            throw new BadRequest("只有已完成的申请单才可以作废！");
        }
        UpdateWrapper<JyjcOpeningApplication> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .set("status", FlowStatusEnum.TO_BE_DISCARD.getCode())
                .set("status_name", FlowStatusEnum.TO_BE_DISCARD.getName())
                .set("remark", remark)
                .eq("SEQUENCE_NBR", sequenceNbr);
        return this.update(updateWrapper);
    }


    /**
     * 列表查询 示例
     */
    public List<JyjcOpeningApplicationModel> queryForJyjcOpeningApplicationList() {
        return this.queryForList("", false);
    }

    public Page<JyjcOpeningApplicationModel> queryForJyjcOpeningApplicationPage(Page<JyjcOpeningApplication> page, JyjcOpeningApplicationRequstDto dto) {
        ReginParams reginParams = commonserviceImpl.getReginParamsOfCurrentUser();
        String currentUserId = reginParams.getUserModel().getUserId();
        String level = reginParams.getCompany().getLevel();
        if (BaseController.COMPANY_TYPE_COMPANY.equals(level)) {
            dto.setType("enterprise");
            dto.setUnitCode(reginParams.getCompany().getCompanyCode());
        } else {
            dto.setType("supervision");
        }
        String applyStartTime = "";
        String applyEndTime = "";
        if (ObjectUtils.isNotEmpty(dto.getApplyTime())) {
            String date = dto.getApplyTime();
            applyStartTime = date + " 00:00:00";
            applyEndTime = date + " 23:59:59";
        }
        Page<JyjcOpeningApplicationModel> result = jyjcOpeningApplicationMapper.selectJyjcOpeningApplicationList(page, dto, applyStartTime, currentUserId, applyEndTime);
        for (JyjcOpeningApplicationModel record : result.getRecords()) {
            record.setIdentityType(dto.getType());
            record.setOpenBizTypeName(this.getOpenBizTypeName(record.getOpenBizType()));
        }
        return result;
    }


    private String getOpenBizTypeName(String openBizType) {
        return Optional.ofNullable(OpenBizTypeEnum.getOneByCode(openBizType))
                .map(OpenBizTypeEnum::getName)
                .orElse("");
    }


    /**
     * 获取详情跳转
     *
     * @param
     * @return {@link }
     * @throws
     * @author yangyang
     */
    public JyjcOpeningApplicationModel queryDetail(Long sequenceNbr) {
        ReginParams reginParams = commonserviceImpl.getReginParamsOfCurrentUser();
        if (ValidationUtil.isEmpty(reginParams.getCompany())) {
            throw new RuntimeException("未指定人员归属单位信息");
        }
        String unitCode;
        JyjcOpeningApplicationModel jyjcOpeningApplicationModel;
        if (null != sequenceNbr) {
            jyjcOpeningApplicationModel = this.queryBySeq(sequenceNbr);
            unitCode = jyjcOpeningApplicationModel.getUnitCode();
            // 设置检验、检测资质信息
            setBaseUnitLicences(unitCode, jyjcOpeningApplicationModel, true);
            // 设置检验、检测人员信息
            setJYJCUserList(unitCode, jyjcOpeningApplicationModel, true);
        } else {
            jyjcOpeningApplicationModel = new JyjcOpeningApplicationModel();
            jyjcOpeningApplicationModel.setResultType("input");
            jyjcOpeningApplicationModel.setOpenBizType(OpenBizTypeEnum.JY.getCode());
            unitCode = reginParams.getCompany().getCompanyCode();
            // 设置检验、检测资质信息，前端需要按照开通的业务类型自行过滤，全部数据
            setBaseUnitLicences(unitCode, jyjcOpeningApplicationModel, false);
            // 设置检验、检测人员信息，前端需要按照开通的业务类型自行过滤，全部数据
            setJYJCUserList(unitCode, jyjcOpeningApplicationModel, false);
            // 设置业务有效期的默认值与yjcOpeningApplicationModel.setOpenBizType(OpenBizTypeEnum.JY.getCode())对应
            setDefaultExpiryDate(jyjcOpeningApplicationModel);
        }
        // 设置企业信息
        setBaseEnterpriseInfo(unitCode, jyjcOpeningApplicationModel);
        return jyjcOpeningApplicationModel;
    }

    private void setBaseEnterpriseInfo(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel) {
        LambdaQueryWrapper<TzBaseEnterpriseInfo> enterpriseInfoQueryWrapper = new LambdaQueryWrapper<>();
        enterpriseInfoQueryWrapper.eq(TzBaseEnterpriseInfo::getUseCode, unitCode);
        TzBaseEnterpriseInfo baseUnitLicenceEntity = enterpriseInfoMapper.selectOne(enterpriseInfoQueryWrapper);
        // 获取企业资质
        if (baseUnitLicenceEntity != null) {
            jyjcOpeningApplicationModel.setUseContact(baseUnitLicenceEntity.getUseContact());
            jyjcOpeningApplicationModel.setContactPhone(baseUnitLicenceEntity.getContactPhone());
            jyjcOpeningApplicationModel.setUnitAddress(baseUnitLicenceEntity.getAddress());
            if (StringUtils.isNotBlank(baseUnitLicenceEntity.getIndustrySupervisor())) {
                DataDictionary dict = dataDictionaryMapper.getByCode(baseUnitLicenceEntity.getIndustrySupervisor(), INDUSTRY_SUPERVISOR_DICT_TYPE);
                if (dict != null) {
                    jyjcOpeningApplicationModel.setIndustrySupervisor(dict.getName());
                } else {
                    jyjcOpeningApplicationModel.setIndustrySupervisor(baseUnitLicenceEntity.getIndustrySupervisor());
                }
            }
            jyjcOpeningApplicationModel.setGeographic(JyjcGeographicModel.builder().latitude(baseUnitLicenceEntity.getLatitude()).longitude(baseUnitLicenceEntity.getLongitude()).build());
            jyjcOpeningApplicationModel.setLongitude(baseUnitLicenceEntity.getLongitude());
            jyjcOpeningApplicationModel.setLatitude(baseUnitLicenceEntity.getLatitude());
            if (ObjectUtils.isNotEmpty(baseUnitLicenceEntity.getUnitBusinessLicense())) {
                jyjcOpeningApplicationModel.setUnitBusinessLicense(JSONArray.parseArray(baseUnitLicenceEntity.getUnitBusinessLicense(), AttachmentDto.class));
            }
        }
    }

    private void setDefaultExpiryDate(JyjcOpeningApplicationModel jyjcOpeningApplicationModel) {
        Optional<TzBaseUnitLicenceDto> op = jyjcOpeningApplicationModel.getBaseUnitLicences().stream().filter(l -> l.getCertTypeCode().equals(jyjcOpeningApplicationModel.getOpenBizType())).min(Comparator.comparing(TzBaseUnitLicenceDto::getExpiryDate));
        op.ifPresent(licenceDto -> jyjcOpeningApplicationModel.setExpiryDate(licenceDto.getExpiryDate()));
    }

    private void setBaseUnitLicences(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel, boolean isNeedFilter) {
        List<TzBaseUnitLicenceDto> baseUnitLicences = baseMapper.selectBaseUnitLicenceList(MapBuilder.<String, Object>create().put("unitCode", unitCode).put("licenceType", "jyjc").build());
        baseUnitLicences.forEach(licenceDto -> {
            licenceDto.setCertTypeCode(this.castCode2Str(licenceDto.getCertTypeCode()));
        });
        if (isNeedFilter) {
            baseUnitLicences = baseUnitLicences.stream().filter(u -> u.getCertTypeCode().equals(jyjcOpeningApplicationModel.getOpenBizType())).collect(Collectors.toList());
            jyjcOpeningApplicationModel.setBaseUnitLicences(baseUnitLicences);
        } else {
            jyjcOpeningApplicationModel.setBaseUnitLicences(baseUnitLicences);
        }
    }

    private String castCode2Str(String certTypeCode) {
        // 新注册逻辑，逻辑在1处维护，便于代码维护【jy、jc对应前端的业务类型】
        if (jcCertTypeCode.equals(certTypeCode)) {
            // 检测类型资质
            return "jc";
        }
        if (jyCertTypeCode.equals(certTypeCode)) {
            // 检验类型资质
            return "jy";
        }
        // 之前老数据逻辑，逻辑在1处维护，便于代码维护【jy、jc对应前端的业务类型】
        return "";
    }

    private void setJYJCUserList(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel, boolean isNeedFilter) {
        LambdaQueryWrapper<TzsUserInfo> userInfoQueryWrapper = new LambdaQueryWrapper<>();
        userInfoQueryWrapper.eq(TzsUserInfo::getUnitCode, unitCode);
        if (StringUtils.isBlank(jyjcOpeningApplicationModel.getWorkflowProstanceId())) {
            // 如果未开启流程则只查询未被删除的用户
            userInfoQueryWrapper.eq(BaseEntity::getIsDelete, false);
        }
        List<TzsUserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);
        if (!ValidationUtil.isEmpty(userInfos)) {
            List<TzsUserInfoVo> tzsUserInfoVos = userInfos.stream().map(userInfo -> {
                TzsUserInfoVo vo = new TzsUserInfoVo();
                BeanUtils.copyProperties(userInfo, vo, "identification", "profile", "permissionItem" ,"appointDoc");
                if (!ObjectUtils.isEmpty(userInfo.getPermissionItem())) {
                    vo.setPermissionItem(JSON.parseArray(userInfo.getPermissionItem()));
                    vo.setPermissionItemName(this.castItemCode2Name(userInfo.getPermissionItem()));
                }
                if (!ObjectUtils.isEmpty(userInfo.getPost())) {
                    vo.setPost(JSON.parseArray(userInfo.getPost()));
                }
                if (!ObjectUtils.isEmpty(userInfo.getAppointDoc())) {
                    vo.setAppointDoc(JSON.parseArray(userInfo.getAppointDoc()));
                }
                vo.setPermissionLevelName(this.getDictNameByCode(userInfo.getPermissionLevel()));
                return vo;
            }).filter(o -> o.getPost() != null && (o.getPost().contains(jyUserPost) || o.getPost().contains(jcUserPost))).peek(u -> {
                // 设置岗位类型，逻辑在1端处理，便于代码维护，前端直接使用即可【jy、jc对应前端的业务类型】
                if (u.getPost().contains(jyUserPost) && u.getPost().contains(jcUserPost)) {
                    // 即时检验又是检测人员
                    u.setStrPost("jy,jc");
                }
                if (u.getPost().contains(jyUserPost) && !u.getPost().contains(jcUserPost)) {
                    // 检验人员
                    u.setStrPost("jy");
                }
                if (!u.getPost().contains(jyUserPost) && u.getPost().contains(jcUserPost)) {
                    // 检测人员
                    u.setStrPost("jc");
                }
            }).collect(Collectors.toList());
            if (isNeedFilter) {
                tzsUserInfoVos = tzsUserInfoVos.stream().filter(u -> u.getPost().contains(jyjcOpeningApplicationModel.getOpenBizType())).collect(Collectors.toList());
                jyjcOpeningApplicationModel.setUserInfos(tzsUserInfoVos);
            } else {
                jyjcOpeningApplicationModel.setUserInfos(tzsUserInfoVos);
            }
        }
    }

    private String castItemCode2Name(String permissionItem) {
        if(permissionItemList == null){
            FeignClientResult<List<DictionarieValueModel>> itemDicts = Systemctl.dictionarieClient.dictValues(ZZXM_JYJC_DICT_KEY);
            permissionItemList = itemDicts.getResult();
        }
        return permissionItemList.stream().filter(i-> permissionItem.contains(i.getDictDataKey())).map(this::buildItemWithCode).collect(Collectors.joining(","));
    }

    private String buildItemWithCode(DictionarieValueModel d) {
        return String.format("%s[%s]",d.getDictDataValue(), d.getDictDataKey());
    }

    private String getDictNameByCode(String permissionLevel) {
        if(StringUtils.isEmpty(permissionLevel)){
            return "";
        }
        if(permissionLevelMap == null){
            FeignClientResult<List<DictionarieValueModel>> levelDicts = Systemctl.dictionarieClient.dictValues(RYJB_JYJC_DICT_KEY);
            permissionLevelMap = levelDicts.getResult().stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, Function.identity(),(k1, k2)->k2));
        }
        return Optional.ofNullable(permissionLevelMap.get(permissionLevel).getDictDataValue()).orElse("");
    }


    /**
     * 接收/驳回通知检验单
     */
    public JyjcOpeningApplication executeFlow(Map<String, Object> params) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        Long sequenceNbr = Long.parseLong(params.get("sequenceNbr") + "");
        String op = params.get("op").toString();
        JyjcOpeningApplication data = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
        //组装信息
        TaskResultDTO dto = new TaskResultDTO();
        dto.setResultCode("approvalStatus");
        dto.setTaskId(data.getNextTaskId());
        dto.setComment(params.get("comments").toString());
        HashMap<String, Object> map = new HashMap<>();
        map.put("approvalStatus", op);
        if (String.valueOf(FlowStatusEnum.ROLLBACK.getCode()).equals(data.getStatus()) || String.valueOf(FlowStatusEnum.REJECTED.getCode()).equals(data.getStatus())) {
            map.put("approvalStatus", "提交");
        }
        dto.setVariable(map);
        ProcessTaskDTO complete = new ProcessTaskDTO();
        if ("0".equals(op)) {
            complete = cmWorkflowService.complete(data.getNextTaskId(), dto);
        } else {
            complete = cmWorkflowService.reject(data.getNextTaskId(), dto);

        }

        ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
        processTaskDTOS.add(complete);
        List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
        if (!org.springframework.util.ObjectUtils.isEmpty(resultDto) && !org.springframework.util.ObjectUtils.isEmpty(resultDto.get(0))) {
            WorkflowResultDto workflowResultDto = resultDto.get(0);
            if (!ObjectUtils.isEmpty(workflowResultDto.getNextTaskId())) {
                if ("1".equals(op)) {
                    // 驳回
                    data.setStatus(String.valueOf(FlowStatusEnum.REJECTED.getCode()));
                    data.setStatusName(String.valueOf(FlowStatusEnum.REJECTED.getName()));
                    data.setPromoter("");

                } else {
                    data.setStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                    data.setStatusName(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getName()));
                    data.setPromoter(reginParams.getUserModel().getUserId());
                }
                // 更新代办
                updateTask(data, workflowResultDto, op);
                data.setNextTaskId(workflowResultDto.getNextTaskId());
            } else {

                // 流程结束
                data.setStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
                //更新办理日期
                data.setAcceptDate(new Date());
                // 更新代办
                HashMap<String, Object> taskParams = new HashMap<>();
                taskParams.put("relationId", data.getWorkflowProstanceId());
                taskParams.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                taskParams.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                taskParams.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                taskParams.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                taskParams.put("model", data);
                commonServiceImpl.updateTaskModel(taskParams);
                data.setStatusName(FlowStatusEnum.TO_BE_FINISHED.getName());
            }
        }
        jyjcOpeningApplicationMapper.updateById(data);
        // 已完成 作废逻辑
        if (String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()).equals(data.getStatus())) {
            doDiscard(data.getUnitCode(), data.getSequenceNbr(), data.getOpenBizType());
        }
        return data;
    }


    /**
     * 撤回流程办理单
     */
    public JyjcOpeningApplication stopFlow(String sequenceNbr) {
        JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
        //撤回流程
        ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(jyjcOpeningApplication.getWorkflowProstanceId());
        ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
        processTaskDTOS.add(processTaskDTO);
        jyjcOpeningApplication.setStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getCode()));
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jyjcOpeningApplication));
        List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
        if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
            WorkflowResultDto workflowResultDto = resultDto.get(0);
            jsonObject.put("nextExecuteUser", workflowResultDto.getNextExecutorRoleIds());
            jyjcOpeningApplication.setNextTaskId(workflowResultDto.getNextTaskId());
            jyjcOpeningApplication.setStatusName(FlowStatusEnum.ROLLBACK.getName());
        }
        jsonObject.put("nextTaskId", jyjcOpeningApplication.getNextTaskId());
        jsonObject.put("taskType", BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
        jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
        jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());
        // 撤回删除代办
        commonServiceImpl.rollbackTask(jyjcOpeningApplication.getWorkflowProstanceId(), jsonObject);
        // 更新数据
        jyjcOpeningApplicationMapper.updateById(jyjcOpeningApplication);
        return jyjcOpeningApplication;
    }


    public List<Map<String, Object>> selectForFlowStatusList() {
        return Arrays.stream(FlowStatusEnum.values()).map(this::mapPointTypeToMap).collect(Collectors.toList());
    }

    private Map<String, Object> mapPointTypeToMap(FlowStatusEnum e) {
        Map<String, Object> record = new HashMap<>();
        record.put("key", e.getCode());
        record.put("label", e.getName());
        return record;
    }

    public Boolean deleteBatchByIds(List<Long> ids) {
        List<JyjcOpeningApplication> jyjcOpeningApplicationList = jyjcOpeningApplicationMapper.selectList(new QueryWrapper<JyjcOpeningApplication>()
                .in("sequence_nbr"));
        List<String> status = Arrays.asList(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()), String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
        jyjcOpeningApplicationList = jyjcOpeningApplicationList.stream().filter(jyjcOpeningApplication -> status.contains(jyjcOpeningApplication.getStatus())).collect(Collectors.toList());
        if (jyjcOpeningApplicationList.isEmpty()) {
            throw new BadRequest("除撤回跟驳回的流程之外其余流程不可删除，请核对数据后重新提交！");
        }
        deleteBatchByIds(ids);
        return true;
    }

    public List<TzBaseEnterpriseInfoDto> getInspectionUnitList() {
        List<TzBaseEnterpriseInfoDto> tzBaseEnterpriseInfos = enterpriseInfoMapper.getInspectionUnitList(CommonserviceImpl.UNIT_TYPE);
        if (ValidationUtil.isEmpty(tzBaseEnterpriseInfos)) {
            return Collections.EMPTY_LIST;
        }
        List<String> unitCodes = this.lambdaQuery().select(JyjcOpeningApplication::getUnitCode).list().stream().map(JyjcOpeningApplication::getUnitCode).collect(Collectors.toList());
        // 根据开通机构过滤
        return tzBaseEnterpriseInfos.stream().filter(o -> StringUtils.isNotBlank(o.getUseCode()) && unitCodes.contains(o.getUseCode())).collect(Collectors.toList());
    }

    public List<Long> selectOverdueData() {
        return jyjcOpeningApplicationMapper.selectOverdueData();

    }


    private void buildTask(JyjcOpeningApplicationModel model, WorkflowResultDto workflowResultDto) {
        ReginParams reginParams = commonserviceImpl.getReginParamsOfCurrentUser();
        // 代办消息
        ArrayList<TaskModelDto> list = new ArrayList<>();
        TaskModelDto dto = new TaskModelDto();
        dto.setTaskType(BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
        dto.setTaskTypeLabel(BizTypeEnum.BUSINESS_OPEN.getName());
        dto.setFlowCreateDate(model.getRecDate());
        dto.setTaskName(workflowResultDto.getNextTaskName());
        dto.setTaskCode(workflowResultDto.getNextTaskCode());
        dto.setTaskContent(String.format("检验检测业务开通办理，【申请单号：%s】", model.getApplicationSeq()));
        dto.setRelationId(workflowResultDto.getInstanceId());
        dto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        dto.setTaskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
        dto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
        dto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setStartUserId(reginParams.getUserModel().getUserId());
        dto.setStartUser(reginParams.getUserModel().getRealName());
        dto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
        dto.setStartDate(new Date());
        model.setWorkflowProstanceId(workflowResultDto.getInstanceId());
        model.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
        JyjcOpeningApplicationModel urlParms = new JyjcOpeningApplicationModel();
        BeanUtil.copyProperties(model, urlParms, "unitCode", "unitAddress", "unitCodeName", "detectionRegion", "detectionRegionName", "applicationSeq", "resultType", "expiryDate", "acceptDate", "remark", "applyTime", "baseUnitLicences", "userInfos", "useContact", "contactPhone", "industrySupervisor", "longitude", "latitude", "geographic", "unitBusinessLicense");
        dto.setModel(urlParms);
        dto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
        dto.setPageType("look");
        list.add(dto);
        commonServiceImpl.buildTaskModel(list);
    }

    private void updateTask(JyjcOpeningApplication model, WorkflowResultDto workflowResultDto, String op) {
        // 更新代办状态
        HashMap<String, Object> params = new HashMap<>();
        params.put("relationId", model.getWorkflowProstanceId());
        params.put("flowStatus", model.getStatus());
        params.put("flowStatusLabel", model.getStatus());
        params.put("taskStatus", model.getStatus());
        params.put("taskStatusLabel", model.getStatus());
        TaskV2Model taskV2Model = commonServiceImpl.updateTaskModel(params);
        // 创建新的代办
        if (!ObjectUtils.isEmpty(taskV2Model)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            BeanUtils.copyProperties(taskV2Model, taskModelDto);
            JyjcOpeningApplication urlParms = new JyjcOpeningApplication();
            BeanUtil.copyProperties(model, urlParms, "unitCode", "unitAddress", "unitCodeName", "detectionRegion", "detectionRegionName", "applicationSeq", "resultType", "expiryDate", "acceptDate", "remark", "applyTime", "baseUnitLicences", "userInfos", "useContact", "contactPhone", "industrySupervisor", "longitude", "latitude", "geographic", "unitBusinessLicense");
            taskModelDto.setModel(urlParms);
            taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
            taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            if ("0".equals(op)) {
                taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                taskModelDto.setTaskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            } else {
                taskModelDto.setTaskStatusLabel(FlowStatusEnum.REJECTED.getName());
                taskModelDto.setTaskStatus(FlowStatusEnum.REJECTED.getCode());
                taskModelDto.setFlowStatus(FlowStatusEnum.REJECTED.getCode());
                taskModelDto.setFlowStatusLabel(FlowStatusEnum.REJECTED.getName());
                taskModelDto.setPageType("edit");
            }

            taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
            commonServiceImpl.buildTaskModel(Collections.singletonList(taskModelDto));
        } else {
            JyjcOpeningApplicationModel applicationModel = new JyjcOpeningApplicationModel();
            BeanUtil.copyProperties(model, applicationModel);
            buildTask(applicationModel, workflowResultDto);
        }

    }
}