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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.util.StringUtil;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.JgReformNotice;
import com.yeejoin.amos.boot.module.jg.api.entity.JgReformNoticeEq;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgReformNoticeEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgReformNoticeMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgReformNoticeService;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgRegisterInfoService;
import com.yeejoin.amos.boot.module.jg.biz.utils.WordTemplateUtils;
import com.yeejoin.amos.boot.module.ymt.api.entity.RegistrationInfo;
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.EquipmentCategoryMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.OtherInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.RegistrationInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.SupervisoryCodeInfoMapper;
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.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
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 org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 改造告知服务实现类
 *
 * @author system_generator
 * @date 2023-12-19
 */
@Service
@Slf4j
public class JgReformNoticeServiceImpl extends BaseService<JgReformNoticeDto, JgReformNotice, JgReformNoticeMapper> implements IJgReformNoticeService {

    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PROCESS_DEFINITION_KEY = "renovationNoticeNew";
    private static final String TABLE_PAGE_ID = "reformNoticeAdd";


    // 西安行政区划code
    private static final String XIAN = "610100";

    // 咸阳行政区划code
    private static final String XIAN_YANG = "610400";

    @Autowired
    EquipmentCategoryMapper equipmentCategoryMapper;

    @Autowired
    JgReformNoticeEqMapper jgReformNoticeEqMapper;
    @Autowired
    RegistrationInfoMapper tzsJgRegistrationInfoMapper;
    @Autowired
    OtherInfoMapper tzsJgOtherInfoMapper;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    SupervisoryCodeInfoMapper supervisoryCodeInfoMapper;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    private JgReformNoticeMapper jgReformNoticeMapper;

    @Autowired
    private CommonServiceImpl commonService;
    @Autowired
    private CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    IIdxBizJgRegisterInfoService idxBizJgRegisterInfoService;

    @Autowired
    JgInstallationNoticeServiceImpl jgInstallationNoticeService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 根据sequenceNbr查询
     *
     * @param sequenceNbr 主键
     * @return 改造告知
     */
    @Override
    public Map<String, Object> queryBySequenceNbr(Long sequenceNbr) {
        // 改造告知信息
        JgReformNotice notice = jgReformNoticeMapper.selectById(sequenceNbr);
        Map<String, Object> reformNoticeMap = BeanUtil.beanToMap(notice, false ,true);
        reformNoticeMap.put("province", notice.getProvince() + "_" + notice.getProvinceName());
        reformNoticeMap.put("city", notice.getCity() + "_" + notice.getCityName());
        reformNoticeMap.put("county", notice.getCounty() + "_" + notice.getCountyName());
        reformNoticeMap.put("fullAddress", notice.getProvinceName() + notice.getCityName() + notice.getCountyName() + notice.getStreetName() + notice.getAddress());
        reformNoticeMap.put("useUnitCreditCode", notice.getUseUnitCreditCode() + "_" + notice.getUseUnitName());
        reformNoticeMap.put("receiveOrgCode", notice.getReceiveOrgCode() + "_" + notice.getReceiveOrgName());
        if (!ValidationUtil.isEmpty(notice.getStreet()) && !ValidationUtil.isEmpty(notice.getStreetName())) {
            reformNoticeMap.put("street", notice.getStreet() + "_" + notice.getStreetName());
        }
        reformNoticeMap.put("constructionManagerId", notice.getConstructionManagerId() + "_" + notice.getConstructionManager());
        if(Integer.parseInt(notice.getNoticeStatus()) == FlowStatusEnum.TO_BE_FINISHED.getCode()){
            // 完成时显示历史数据
            JSONObject hisData = commonService.queryHistoryData(notice.getSequenceNbr());
            // 兼容老数据
            if(hisData == null){
                // 老数据逻辑
                Map<String, Object> equipMap = setEquipInfoNew(sequenceNbr);
                equipMap.putAll(reformNoticeMap);
                return equipMap;
            } else {
                // 新数据逻辑
                // 格式化基本通用信息的时间类型字段
                CommonServiceImpl.formatTime2StrDateForEquip(hisData);
                hisData.putAll(reformNoticeMap);
                return hisData;
            }
        } else {
            // 显示最新的设备信息
            Map<String, Object> equipMap = setEquipInfoNew(sequenceNbr);
            equipMap.putAll(reformNoticeMap);
            return equipMap;
        }
    }


    private Map<String, Object> setEquipInfoNew(Long sequenceNbr) {
        Map<String, Object> equipMap = new HashMap<>();
        List<Map<String, Object>> equipmentInfos = jgReformNoticeMapper.queryEquipInformation(sequenceNbr);
        if (equipmentInfos != null && !equipmentInfos.isEmpty()) {
            String equId = (String) equipmentInfos.get(0).get("equId");
            if (equId != null) {
                equipMap = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(equId);
                equipMap.put("useUnitCreditCodeUse", equipMap.getOrDefault("useUnitCreditCode", ""));
                equipMap.put("useUnitNameUse", equipMap.getOrDefault("useUnitName", ""));
                equipMap.put("equRegisterCode", equipMap.getOrDefault("equCode", ""));
            }
        }
        return equipMap;
    }

    /**
     * 更新改造告知
     *
     * @param noticeDto 改造告知
     */
    @SuppressWarnings({"rawtypes", "Duplicates"})
    public JgReformNoticeDto updateInstallationNotice(String submitType, JgReformNoticeDto noticeDto, String op) {
        if (Objects.isNull(noticeDto) || StringUtils.isEmpty(submitType)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        // 字段转换
        this.convertField(noticeDto);
        JgReformNotice notice = this.getById(noticeDto.getSequenceNbr());
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 发起流程
            if (!StringUtils.hasText(noticeDto.getInstanceId())) {
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setBusinessKey(noticeDto.getSequenceNbr().toString());
                dto.setCompleteFirstTask(Boolean.TRUE);
                dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                dto.setNextExecuteUserCompanyCode(noticeDto.getReceiveCompanyCode());
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                ProcessTaskDTO processTaskDTO = cmWorkflowService.startBatch(actWorkflowBatchDTO).get(0);
                // 提取节点等信息
                WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
                BeanUtils.copyProperties(noticeDto, notice);
                if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                    notice.setInstanceStatus(notice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                } else {
                    notice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                }
                notice.setPromoter(RequestContext.getExeUserId());
                notice.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
                notice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                notice.setInstanceId(workflowResultDto.getInstanceId());
                notice.setNextTaskId(workflowResultDto.getNextTaskId());
                notice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());

                jgReformNoticeMapper.updateById(notice);
                //删除暂存
                commonService.deleteTaskModel(notice.getSequenceNbr() + "");
                // 如果为保存并提交，则创建代办
                this.buildTask(Collections.singletonList(notice), Collections.singletonList(workflowResultDto));
            } else {
                TaskResultDTO dto = new TaskResultDTO();
                dto.setResultCode("approvalStatus");
                dto.setTaskId(notice.getNextTaskId());
                HashMap<String, Object> commMap = new HashMap<>();
                if (notice.getNoticeStatus().equals("6614") || notice.getNoticeStatus().equals("6615")) {
                    commMap.put("approvalStatus", "提交");
                } else {
                    commMap.put("approvalStatus", op);
                }
                dto.setNextExecuteUserCompanyCode(notice.getReceiveCompanyCode());
                dto.setVariable(commMap);
                ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(notice.getNextTaskId(), dto, op);
                // 提取节点等信息
                WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
                BeanUtils.copyProperties(noticeDto, notice);

                if (!org.apache.commons.lang3.ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                    notice.setInstanceStatus(notice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                } else {
                    notice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                }
                notice.setPromoter(RequestContext.getExeUserId());
                notice.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
                notice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                notice.setNextTaskId(workflowResultDto.getNextTaskId());
                notice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());

                updateById(notice);
                // 上个代办改为已办
                TaskV2Model taskV2Model = this.updateLastTodo(notice, FlowStatusEnum.TO_BE_PROCESSED);
                // 创建新的代办
                this.createNewTodo(notice, workflowResultDto, taskV2Model, FlowStatusEnum.TO_BE_PROCESSED);
            }
            commonService.saveExecuteFlowData2Redis(notice.getInstanceId(),this.buildInstanceRuntimeData(notice));
        } else {
            JgReformNotice bean = new JgReformNotice();
            BeanUtils.copyProperties(noticeDto, bean);
            jgReformNoticeMapper.updateById(bean);
        }
        return noticeDto;
    }


    /**
     * 分页查询
     *
     * @param page  分页对象
     * @param model 查询参数
     * @param type  类型：enterprise-企业端、supervision-监管端
     * @return 改造告知列表
     */
    @Override
    public Page<JgReformNoticeDto> queryForJgReformNoticePage(Page<JgReformNotice> page, JgReformNoticeDto model, String type, ReginParams reginParams) {

        String orgCode = reginParams.getCompany().getCompanyCode();
        Page<JgReformNotice> noticePage = jgReformNoticeMapper.queryForPage(page, model, type, orgCode, reginParams.getUserModel().getUserId());

        // 将Page<JgReformNotice>转化为Page<JgReformNoticeDto>
        Page<JgReformNoticeDto> noticeDtoPage = new Page<>();
        BeanUtils.copyProperties(noticePage, noticeDtoPage, "records");
        List<JgReformNoticeDto> records = noticePage.getRecords().stream().map(notice -> {
            JgReformNoticeDto noticeDto = new JgReformNoticeDto();
            BeanUtils.copyProperties(notice, noticeDto);
            if (Objects.nonNull(notice.getNoticeStatus())) {
                String noticeStatusDesc = FlowStatusEnum.getNameByType(Long.valueOf(notice.getNoticeStatus()));
                noticeDto.setNoticeStatusDesc(noticeStatusDesc);
            }
            return noticeDto;
        }).collect(Collectors.toList());
        noticeDtoPage.setRecords(records);

        return noticeDtoPage;
    }

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

    /**
     * 批量删除
     *
     * @param sequenceNbrs 主键
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteForBatch(Long[] sequenceNbrs) {
        if (Objects.isNull(sequenceNbrs) || sequenceNbrs.length == 0) {
            return false;
        }
        Collection<JgReformNotice> JgReformNotices = this.listByIds(Arrays.asList(sequenceNbrs));
        JgReformNotices.forEach(notice -> {
            // if (StringUtils.hasText(notice.getInspectUnitId())) {
            //     throw new IllegalStateException("所选数据已存在流程，不能删除！");
            // }
            notice.setIsDelete(true);
            commonService.deleteTaskModel(String.valueOf(notice.getSequenceNbr()));
        });

        return this.updateBatchById(JgReformNotices);
    }

    /**
     * 打印改造告知单
     *
     * @param sequenceNbr 主键
     * @return pdf文件路径
     */
    @Override
    public String generateInstallationNoticeReport(Long sequenceNbr) {
        if (Objects.isNull(sequenceNbr)) {
            throw new IllegalArgumentException("参数不能为空");
        }

        JgReformNotice JgReformNotice = this.getById(sequenceNbr);
        List<Map<String, Object>> informationList = jgReformNoticeMapper.queryEquipInformation(sequenceNbr);
        if (Objects.isNull(JgReformNotice) || CollectionUtils.isEmpty(informationList)) {
            throw new IllegalArgumentException("改造告知单不存在");
        }
        Map<String, Object> placeholders = jgInstallationNoticeService.fullFillTemplateObj(informationList, BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getName().substring(0,2));

        String tempFileName = "改造告知单_" + System.currentTimeMillis() + "_temp";
        String url = WordTemplateUtils.templateToPdf(tempFileName, "installation-notification-report.ftl", placeholders);

        // 更新到数据库
        JgReformNotice.setNoticeReportUrl(url);
        this.updateById(JgReformNotice);

        return url;
    }


    @Override
    @SuppressWarnings({"Duplicates", "rawtypes"})
    @Transactional(rollbackFor = Exception.class)
    public List<JgReformNotice>  saveNotice(String submitType, Map<String, Object> JgReformNoticeDtoMap, ReginParams reginParams) {
        JgReformNoticeDto model = JSON.parseObject(JSONObject.toJSONString(JgReformNoticeDtoMap.get(TABLE_PAGE_ID)), JgReformNoticeDto.class);
        convertField(model);
        // 获取告知设备列表
        List<Map<String, Object>> deviceList = model.getDeviceList();
        if (CollectionUtils.isEmpty(deviceList)) {
            throw new BadRequest("请选择设备!");
        }

        // 获取告知单号
        ResponseModel<List<String>> codeResult = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.GZGZ.getCode(), deviceList.size());
        List<String> applyNoList = null;
        if (codeResult != null && !ValidationUtil.isEmpty(codeResult.getResult())) {
            applyNoList = codeResult.getResult();
        }

        if (CollectionUtils.isEmpty(applyNoList)) {
            throw new BadRequest("申请单编号生成失败,请稍后重试!");
        }

        //启动工作流
        List<WorkflowResultDto> workflowResultList = this.startWorkFlow(model.getReceiveCompanyCode(), submitType, deviceList);

        List<JgReformNotice> list = new ArrayList<>();
        List<JgReformNoticeEq> equipList = new ArrayList<>();
        List<String> finalApplyNoList = applyNoList;

        deviceList.forEach(obj -> {
            JgReformNoticeEq jgRelationEquip = new JgReformNoticeEq();
            JgReformNotice dto = new JgReformNotice();
            BeanUtils.copyProperties(model, dto);
            int i = deviceList.indexOf(obj);
            String applyNo = finalApplyNoList.get(i);
            dto.setApplyNo(applyNo);
            dto.setNoticeDate(new Date());
            dto.setCreateUserName(reginParams.getUserModel().getRealName());
            dto.setCreateUserId(reginParams.getUserModel().getUserId());
            dto.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
            dto.setEquCategory(Objects.toString(obj.get("EQU_CATEGORY"), ""));
            dto.setEquListCode(Objects.toString(obj.get("EQU_DEFINE"), ""));
            dto.setSupervisoryCode(Objects.toString(obj.get("SUPERVISORY_CODE"), ""));
            dto.setEquList(Objects.toString(obj.get("EQU_LIST"), ""));
            dto.setFullAddress(Objects.toString(obj.get("ADDRESS"), ""));

            if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                WorkflowResultDto workflowResult = workflowResultList.get(i);
                dto.setNextExecuteIds(workflowResult.getNextExecutorRoleIds());
                dto.setInstanceStatus(workflowResult.getNextExecutorRoleIds() + "," + workflowResult.getExecutorRoleIds());
                dto.setPromoter(reginParams.getUserModel().getUserId());
                dto.setNextTaskId(workflowResult.getNextTaskId());
                dto.setNextExecuteUserIds(workflowResult.getNextExecutorUserIds());
            } else {
                dto.setNextExecuteUserIds(RequestContext.getExeUserId());
            }
            dto.setInstallUnitName(reginParams.getCompany().getCompanyName());
            dto.setInstallUnitCreditCode(reginParams.getCompany().getCompanyCode());
            dto.setEntrustingUnitName(reginParams.getCompany().getCompanyName());
            dto.setEntrustingUnitCreditCode(reginParams.getCompany().getCompanyCode());
            jgRelationEquip.setEquId(String.valueOf(obj.get("SEQUENCE_NBR")));
            jgRelationEquip.setEquipTransferId(applyNo);
            if (!CollectionUtils.isEmpty(workflowResultList)) {
                dto.setInstanceId(workflowResultList.get(i).getInstanceId());
                dto.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
            } else {
                dto.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_SUBMITTED.getCode()));
            }

            dto.setCreateUserId(reginParams.getUserModel().getUserId());
            list.add(dto);
            equipList.add(jgRelationEquip);
        });

        jgReformNoticeMapper.insertBatchSomeColumn(list);

        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            this.buildTask(list, workflowResultList);
        } else {
            this.saveTempReformNotice(list);
        }
        List<JgReformNoticeEq> jgRelationEquipList = equipList.stream().map(jgRelationEquip -> {
            List<JgReformNotice> collect = list.stream().filter(JgReformNotice -> jgRelationEquip.getEquipTransferId().equals(JgReformNotice.getApplyNo())).collect(Collectors.toList());
            Long sequenceNbr = collect.get(0).getSequenceNbr();
            return jgRelationEquip.setEquipTransferId(String.valueOf(sequenceNbr));
        }).collect(Collectors.toList());
        jgReformNoticeEqMapper.insertBatchSomeColumn(jgRelationEquipList);
        this.updateRedisBatch(list);
        return list;
    }

    private void updateRedisBatch(List<JgReformNotice> jgReformNotices) {
        jgReformNotices.stream().filter(n-> StringUtil.isNotEmpty(n.getInstanceId())).forEach(jgReformNotice -> {
            commonService.saveExecuteFlowData2Redis(jgReformNotice.getInstanceId(), this.buildInstanceRuntimeData(jgReformNotice));
        });
    }

    /**
     * 批量暂存
     *
     * @param noticeList 移交信息
     */
    private void saveTempReformNotice(List<JgReformNotice> noticeList) {
        if (CollectionUtils.isEmpty(noticeList)) {
            return;
        }

        List<TaskModelDto> taskModelDtoList = noticeList.stream().map(this::buildTempTaskModelDto).collect(Collectors.toList());
        commonService.buildTaskModel(taskModelDtoList);
    }

    private TaskModelDto buildTempTaskModelDto(JgReformNotice item) {
        return TaskModelDto.builder()
                .model(item)
                .taskContent(String.format("来自%s【%s】的业务办理，【申请单号：%s】", item.getEquList(), Objects.toString(item.getSupervisoryCode(), ""), item.getApplyNo()))
                .taskCode(item.getApplyNo())
                .taskType(BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getCode())
                .relationId(item.getSequenceNbr() + "")
                .build();
    }

    /**
     * 插入代办
     */
    private void buildTask(List<JgReformNotice> list, List<WorkflowResultDto> workflowResultList) {
        if (CollectionUtils.isEmpty(list) || CollectionUtils.isEmpty(workflowResultList)) {
            return;
        }

        List<TaskModelDto> taskModelDtoList = list.stream().map(item ->
                this.buildTaskModelDto(item, workflowResultList.get(0))).collect(Collectors.toList());
        commonService.buildTaskModel(taskModelDtoList);
    }

    /**
     * 组装代办消息
     *
     * @param item              改造告知信息
     * @param workflowResultDto 工作流返回信息
     * @return 代办信息
     */
    private TaskModelDto buildTaskModelDto(JgReformNotice item, WorkflowResultDto workflowResultDto) {
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(item, taskMessageDto);
        return TaskModelDto.builder()
                .flowCreateDate(item.getCreateDate())
                .taskName(workflowResultDto.getNextTaskName())
                .taskCode(item.getApplyNo())
                .relationId(workflowResultDto.getInstanceId())
                .taskType(BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getCode())
                .taskTypeLabel(BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getName())
                .relationId(item.getInstanceId())
                .executeUserIds(workflowResultDto.getNextExecutorUserIds())
                .taskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode())
                .taskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName())
                .flowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode())
                .flowCode(workflowResultDto.getNextTaskId())
                .flowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName())
                .taskContent(String.format("来自%s【%s】的业务办理，【申请单号：%s】", item.getEquList(), item.getSupervisoryCode(), item.getApplyNo()))
                .taskDesc(String.format("来自%s【%s】的业务办理，【申请单号：%s】", item.getEquList(), item.getSupervisoryCode(), item.getApplyNo()))
                .startUserId(item.getCreateUserId())
                .startUser(item.getCreateUserName())
                .startUserCompanyName(item.getCreateUserCompanyName())
                .startDate(item.getCreateDate())
                .model(taskMessageDto)
                .nextExecuteUser(item.getNextExecuteIds())
                .build();
    }

    /**
     * 启动工作流
     *
     * @param submitType 提交类型
     * @param deviceList 设备列表
     * @return 工作流信息
     */
    private List<WorkflowResultDto> startWorkFlow(String receiveOrgCode, String submitType, List<Map<String, Object>> deviceList) {
        if (!SUBMIT_TYPE_FLOW.equals(submitType)) {
            return new ArrayList<>();
        }
        ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
        List<ActWorkflowStartDTO> list = deviceList.stream()
                .map(item -> {
                    ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                    dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                    dto.setBusinessKey(item.get("SEQUENCE_NBR").toString());
                    dto.setCompleteFirstTask(Boolean.TRUE);
                    dto.setNextExecuteUserCompanyCode(receiveOrgCode);
                    return dto;
                })
                .collect(Collectors.toList());

        actWorkflowBatchDTO.setProcess(list);
        List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
        // 组装工作流返回的数据
        return commonService.buildWorkFlowInfo(processTaskDTOS);
    }

    private void convertField(JgReformNoticeDto model) {
        // 处理图片
        // if (!ValidationUtil.isEmpty(model.getProxyStatementAttachmentList())) {
        //     model.setProxyStatementAttachment(JSON.toJSONString(model.getProxyStatementAttachmentList()));
        // }
        // if (!ValidationUtil.isEmpty(model.getInstallContractAttachmentList())) {
        //     model.setInstallContractAttachment(JSON.toJSONString(model.getInstallContractAttachmentList()));
        // }
        if (model == null) {
            return;
        }
        // 分割省市区字段
        String province = model.getProvince();
        if (!ObjectUtils.isEmpty(province)) {
            String[] provinceList = province.split("_");
            if (provinceList.length > 1) {
                model.setProvince(provinceList[0]);
                model.setProvinceName(provinceList[1]);
            }
        }

        String city = model.getCity();
        if (!ObjectUtils.isEmpty(city)) {
            String[] cityList = city.split("_");
            if (cityList.length > 1) {
                model.setCity(cityList[0]);
                model.setCityName(cityList[1]);
            }
        }

        String county = model.getCounty();
        if (!ObjectUtils.isEmpty(county)) {
            String[] countyList = county.split("_");
            if (countyList.length > 1) {
                model.setCounty(countyList[0]);
                model.setCountyName(countyList[1]);
            }
        }

        String street = model.getStreet();
        if (!ObjectUtils.isEmpty(street)) {
            String[] streetList = street.split("_");
            if (streetList.length > 1) {
                model.setStreet(streetList[0]);
                model.setStreetName(streetList[1]);
            }
        }

        // 分割单位
        String useUnitId = model.getUseUnitCreditCode();
        if (!ObjectUtils.isEmpty(useUnitId)) {
            String[] useUnitList = useUnitId.split("_");
            if (useUnitList.length > 1) {
                model.setUseUnitCreditCode(useUnitList[0]);
                model.setUseUnitName(useUnitList[1]);
            }
        }
        String receiveOrgId = model.getReceiveOrgCode();
        if (!ObjectUtils.isEmpty(receiveOrgId)) {
            String[] receiveOrgIdList = receiveOrgId.split("_");
            if (receiveOrgIdList.length > 1) {
                model.setReceiveOrgCode(receiveOrgIdList[0]);
                model.setReceiveOrgName(receiveOrgIdList[1]);
                model.setReceiveCompanyCode(receiveOrgIdList[0]);
            }
        }
        String constructionManagerId = model.getConstructionManagerId();
        if (!ObjectUtils.isEmpty(constructionManagerId)) {
            String[] constructionManagerIdList = constructionManagerId.split("_");
            if (constructionManagerIdList.length > 1) {
                model.setConstructionManagerId(constructionManagerIdList[0]);
                model.setConstructionManager(constructionManagerIdList[1]);
            }
        }
        // String inspectUnitId = model.getInspectUnitId();
        // if (!ObjectUtils.isEmpty(inspectUnitId)) {
        //     String[] inspectUnitIdList = inspectUnitId.split("_");
        //     if (inspectUnitIdList.length > 1) {
        //         model.setInspectUnitId(inspectUnitIdList[0]);
        //         model.setInspectUnitName(inspectUnitIdList[1]);
        //     }
        // }
    }

    private String convertImageUrl(List<Map<String, String>> urlList) {
        String urls = "";
        if (!CollectionUtils.isEmpty(urlList)) {
            urls = urlList.stream().map(map -> map.get("url")).collect(Collectors.joining(","));
        }
        return urls;
    }

    /**
     * 撤回操作
     *
     * @param noticeDto 改造信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancel(JgReformNoticeDto noticeDto) {
        String instanceId = noticeDto.getInstanceId();
        String nextTaskId = noticeDto.getNextTaskId();
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForRevocationFlow(nextTaskId, instanceId);
            // 查询 改造信息
            JgReformNotice notice = baseMapper.selectById(noticeDto.getSequenceNbr());
            // 回滚工作流
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(noticeDto.getInstanceId());
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            notice.setPromoter("");
            notice.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            notice.setNoticeStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getCode()));
            notice.setNextTaskId(workflowResultDto.getNextTaskId());
            notice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            baseMapper.updateById(notice);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(notice));
            jsonObject.put("nextExecuteUser", notice.getNextExecuteIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getCode());
            jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
            jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());
            commonService.rollbackTask(notice.getInstanceId(), jsonObject);
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(notice));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 通过和驳回
     *
     * @param dto 改造信息
     * @param op  通过或驳回
     */
    public void accept(JgReformNoticeDto dto, String op) {
        String instanceId = dto.getInstanceId();
        String nextTaskId = dto.getNextTaskId();
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            JgReformNotice jgReformNotice = baseMapper.selectById(dto.getSequenceNbr());

            jgReformNotice.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
            // 组装设备注册代码
            String ym = null;
            try {
                ym = DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN_MM);
            } catch (ParseException e) {
                log.error("日期转换失败：{}", e.getMessage());
            }

            TaskResultDTO workDto = new TaskResultDTO();
            workDto.setResultCode("approvalStatus");
            workDto.setTaskId(jgReformNotice.getNextTaskId());
            HashMap<String, Object> commMap = new HashMap<>();
            if (jgReformNotice.getNoticeStatus().equals("6614") || jgReformNotice.getNoticeStatus().equals("6615")) {
                commMap.put("approvalStatus", "提交");
            } else {
                commMap.put("approvalStatus", op);
            }
            workDto.setNextExecuteUserCompanyCode("1".equals(op) ? jgReformNotice.getInstallUnitCreditCode() : jgReformNotice.getReceiveOrgCode());
            workDto.setVariable(commMap);
            workDto.setComment(dto.getRemark());
            ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(jgReformNotice.getNextTaskId(), workDto, op);
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            jgReformNotice.setPromoter(reginParams.getUserModel().getUserId());
            jgReformNotice.setRemark(dto.getRemark());
            TaskV2Model taskV2Model;
            if ("0".equals(op)) {
                if (StringUtils.isEmpty(workflowResultDto.getNextExecutorRoleIds())) {
                    LambdaQueryWrapper<JgReformNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(JgReformNoticeEq::getEquipTransferId, dto.getSequenceNbr());
                    JgReformNoticeEq jgRelationEquip = jgReformNoticeEqMapper.selectOne(queryWrapper);
                    // 通过时记录历史数据
                    this.saveHisDataBeforeUpdate(jgReformNotice, jgRelationEquip.getEquId());
                    LambdaQueryWrapper<RegistrationInfo> queryWrapper2 = new LambdaQueryWrapper<>();
                    queryWrapper2.eq(RegistrationInfo::getRecord, jgRelationEquip.getEquId());
                    RegistrationInfo tzsJgRegistrationInfo = tzsJgRegistrationInfoMapper.selectOne(queryWrapper2);
                    String equCode = Optional.ofNullable(tzsJgRegistrationInfo.getEquDefine())
                            .orElse(tzsJgRegistrationInfo.getEquCategory());
                    String registrationCode = equCode + jgReformNotice.getReceiveCompanyCode() + ym;
                    ResponseModel<String> responseModel = tzsServiceFeignClient.deviceRegistrationCode(registrationCode);
                    String deviceRegistrationCode = responseModel.getResult();
                    jgReformNotice.setInformNumber(deviceRegistrationCode);
                    jgReformNotice.setAcceptDate(new Date());
                    jgReformNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
                    jgReformNotice.setPromoter("");
                    this.updateLastTodo(jgReformNotice, FlowStatusEnum.TO_BE_FINISHED);
                    this.updateById(jgReformNotice);
                    this.generateInstallationNoticeReport(jgReformNotice.getSequenceNbr());
                } else {
                    jgReformNotice.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
                    if (!ObjectUtils.isEmpty(jgReformNotice.getInstanceStatus())) {
                        jgReformNotice.setInstanceStatus(jgReformNotice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        jgReformNotice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                    }
                    jgReformNotice.setPromoter(RequestContext.getExeUserId());
                    jgReformNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                    jgReformNotice.setNextTaskId(workflowResultDto.getNextTaskId());
                    // 上个代办改为已办
                    taskV2Model = this.updateLastTodo(jgReformNotice, FlowStatusEnum.TO_BE_FINISHED);
                    // 创建新的代办
                    this.createNewTodo(jgReformNotice, workflowResultDto, taskV2Model, FlowStatusEnum.TO_BE_PROCESSED);
                    jgReformNoticeMapper.updateById(jgReformNotice);
                }
            } else {
                jgReformNotice.setPromoter("");
                jgReformNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.REJECTED.getCode()));
                jgReformNotice.setSupervisoryCode(dto.getSupervisoryCode());
                jgReformNotice.setEquList(dto.getEquList());
                jgReformNotice.setNextTaskId(workflowResultDto.getNextTaskId());
                jgReformNotice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                //jgReformNotice.setInstanceId(workflowResultDto.getInstanceId());

                // 上个代办改为驳回
                taskV2Model = this.updateLastTodo(jgReformNotice, FlowStatusEnum.REJECTED);
                this.createNewTodo(jgReformNotice, workflowResultDto, taskV2Model, FlowStatusEnum.REJECTED);
                jgReformNoticeMapper.updateById(jgReformNotice);
            }
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgReformNotice));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }


    private void saveHisDataBeforeUpdate(JgReformNotice jgReformNotice, String equId) {
        Map<String, Object> map = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(equId);
        commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_MODIFICATION_NOTIFICATION.getName(), new JSONObject(map), equId, jgReformNotice.getSequenceNbr().toString());
    }

    public InstanceRuntimeData buildInstanceRuntimeData(JgReformNotice jgReformNotice) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jgReformNotice.getNextExecuteUserIds())
                .promoter(jgReformNotice.getPromoter())
                .nextTaskId(jgReformNotice.getNextTaskId())
                .build();
    }

    /**
     * 上个代办改为已办
     *
     * @param jgReformNotice 设备信息
     * @return 代办信息
     */
    private TaskV2Model updateLastTodo(JgReformNotice jgReformNotice, FlowStatusEnum statusEnum) {
        return commonService.updateTaskModel(MapBuilder.<String, Object>create()
                .put("taskStatus", statusEnum.getCode())
                .put("taskStatusLabel", statusEnum.getName())
                .put("flowStatus", statusEnum.getCode())
                .put("flowStatusLabel", statusEnum.getName())
                .put("relationId", jgReformNotice.getInstanceId())
                .put("model", jgReformNotice)
                .build());
    }

    /**
     * 创建新代办
     *
     * @param transfer          设备信息
     * @param workflowResultDto 工作流信息
     * @param taskV2Model       代办信息
     */
    private void createNewTodo(JgReformNotice transfer, WorkflowResultDto workflowResultDto, TaskV2Model taskV2Model, FlowStatusEnum statusEnum) {
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(transfer, taskMessageDto);
        TaskModelDto taskModelDto = TaskModelDto.builder()
                .flowCreateDate(taskV2Model.getFlowCreateDate())
                .taskName(workflowResultDto.getNextTaskName())
                .taskCode(taskV2Model.getTaskCode())
                .taskType(taskV2Model.getTaskType())
                .taskTypeLabel(taskV2Model.getTaskTypeLabel())
                .relationId(taskV2Model.getRelationId())
                .executeUserIds(workflowResultDto.getNextExecutorUserIds())
                .taskStatusLabel(statusEnum.getName())
                .flowStatus(statusEnum.getCode())
                .flowCode(workflowResultDto.getNextTaskId())
                .flowStatusLabel(statusEnum.getName())
                .taskContent(String.format("来自%s【%s】的业务办理，【申请单号：%s】", transfer.getEquList(), Objects.toString(transfer.getSupervisoryCode(), ""), transfer.getApplyNo()))
                .taskDesc(String.format("来自%s【%s】的业务办理，【申请单号：%s】", transfer.getEquList(), Objects.toString(transfer.getSupervisoryCode(), ""), transfer.getApplyNo()))
                .startUserCompanyName(transfer.getCreateUserCompanyName())
                .startUserId(taskV2Model.getStartUserId())
                .startUser(taskV2Model.getStartUser())
                .startDate(taskV2Model.getStartDate())
                .model(taskMessageDto)
                .pageType(statusEnum.getCode() == 6614 ? "edit" : "look")
                .nextExecuteUser(workflowResultDto.getNextExecutorRoleIds())
                .build();
        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
    }
}