package com.junmp.junmpProcess.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.junmp.junmpProcess.entity.ProcessTemplates;
import com.junmp.junmpProcess.mapper.ProcessTemplatesMapper;
import com.junmp.junmpProcess.mapper.TemplateGroupMapper;
import com.junmp.junmpProcess.service.ISysFormService;
import com.junmp.junmpProcess.service.Repository.ProcessTemplateService;
import com.junmp.junmpProcess.utils.IdWorker;
import com.junmp.junmpProcess.utils.SpringContextHolder;
import com.junmp.junmpProcess.vo.ProcessVO;
import com.junmp.junmpProcess.vo.TemplateGroupVo;
import com.junmp.junmpProcess.vo.UpdateProcessVO;
import com.junmp.jyzb.api.bean.query.processReq.FormReq;
import com.junmp.v2.common.bean.request.BaseRequest;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.page.PageResult;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static com.junmp.junmpProcess.utils.BpmnConvert.toBpmn;

@Service
public class SysFormServiceImpl extends ServiceImpl<ProcessTemplatesMapper, ProcessTemplates> implements ISysFormService {
    @Resource
    private IdWorker idWorker;
    @Autowired
    private ProcessTemplateService processTemplateService;
    @Resource
    private RepositoryService repositoryService;
    /**
    * @Author: Zhaojw
    * @Description: 创建新流程
    * @DateTime: 2023/9/27 10:59
    * @Params:
    * @Return
    */
    @Override
    public String createNewForm(FormReq req) {
        ProcessTemplates processTemplates = ProcessTemplates.builder().build();
        String templateId = idWorker.nextId()+"";
        processTemplates.setTemplateId(templateId);
        processTemplates.setFormName(req.getFormName());
        processTemplates.setRemark(req.getRemark());
        processTemplates.setIsStop(true);
        Date date= new Date();
        processTemplates.setUpdated(date);
        processTemplates.setConfig(req.getConfig());
        processTemplateService.save(processTemplates);
        return templateId;
    }


    @Override
    public Boolean createBpmn(ProcessVO processVO) throws JsonProcessingException {
        //流程定义
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode processJsonNode = objectMapper.readTree(processVO.getProcessJson());
        JsonNode formJsonNode = objectMapper.readTree(processVO.getFormJson());
        String formName=processVO.getFormName().toString();
        ProcessTemplates processTemplates = ProcessTemplates.builder().build();
        String templateId = idWorker.nextId()+"";
        processTemplates.setTemplateId(templateId);

        processTemplates.setFormJson(formJsonNode.toString());
        processTemplates.setProcessJson(processJsonNode.toString());
        processTemplates.setFormName(processVO.getFormName());
        processTemplates.setIsStop(false);
        Date date= new Date();

        processTemplates.setUpdated(date);
        processTemplateService.save(processTemplates);
        //将json转换为bpmn

        BpmnModel bpmnModel = toBpmn(processJsonNode,formJsonNode,formName,templateId);
        Deployment deploy = repositoryService.createDeployment()
                .addBpmnModel(formName+".bpmn20.xml", bpmnModel)
                .name(formName)
                .category(templateId)
                .deploy();

        return true;
    }

    @Override
    public Boolean updateForm(UpdateProcessVO process) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode processJsonNode = objectMapper.readTree(process.getProcessJson());
        JsonNode formJsonNode = objectMapper.readTree(process.getFormJson());
        String formName="";
        ProcessTemplates processTemplates = processTemplateService.getById(process.getTemplateId());
        if (ObjectUtil.isNotEmpty(process.getFormName()))
        {
            formName= process.getFormName().toString();
            processTemplates.setFormName(process.getFormName());
        }
        else
        {
            formName = processTemplates.getFormName();
        }
//        processTemplates.setFormJson(formJsonNode.toString());//暂时用不到，以后会用

        processTemplates.setProcessJson(process.getProcessJson().toString());
        processTemplates.setUpdated(new Date());
        processTemplateService.updateById(processTemplates);//更新表单明细表信息
        BpmnModel bpmnModel = toBpmn(processJsonNode,formJsonNode,formName,process.getTemplateId());


        Deployment deploy = repositoryService.createDeployment()
                .addBpmnModel(formName+".bpmn20.xml", bpmnModel)
                .name(formName)
                .category(process.getTemplateId())
                .deploy();
        return true;
    }

    @Override
    public Boolean updateFormName(UpdateProcessVO process) {
        ProcessTemplates processTemplates = processTemplateService.getById(process.getTemplateId());
        processTemplates.setFormName(process.getFormName());
        processTemplates.setRemark(process.getRemark());
        processTemplates.setUpdated(new Date());
        processTemplates.setConfig(process.getConfig());
//        processTemplates.
        return processTemplateService.updateById(processTemplates);//更新表单明细表信息
    }

    public  Boolean CheckConfig(String config)
    {
        ProcessTemplates process=   this.getOne(new LambdaQueryWrapper<ProcessTemplates>()
                .eq(ProcessTemplates::getConfig, config)
               );
        if (process!=null)
        {
        return  false;
        }
        else
        {
            return  true;
        }
    }
    public  Boolean DeleteFrom(String fromId)
    {
        ProcessTemplates process=   this.getOne(new LambdaQueryWrapper<ProcessTemplates>()
                .eq(ProcessTemplates::getFormId, fromId)
        );
        if (process!=null)
        {
       boolean res=     this.removeById(process);
       if (res)
       {
           return  true;
       }
       else {
           return  false;
       }

        }
        else
        {
            return  false;
        }
    }
    public PageResult<TemplateGroupVo> getFormList(BaseRequest br)
    {
        Map<String, Object> params = br.getParams();
        LambdaQueryWrapper<ProcessTemplates> wrapper = new LambdaQueryWrapper<ProcessTemplates>();
        wrapper.like(ObjectUtil.isNotEmpty(params.get("formName")),ProcessTemplates::getFormName,params.get("formName"));
        Object orgId = params.get("orgId");
        if (ObjectUtil.isNotEmpty(orgId)){
            wrapper.and(q -> q.eq(ProcessTemplates::getOrgId, params.get("orgId"))
                    .or()
                    .isNull(ProcessTemplates::getOrgId));
        }

        wrapper.orderByDesc(ProcessTemplates::getUpdated);
        TemplateGroupMapper templateGroupMapper = SpringContextHolder.getBean(TemplateGroupMapper.class);
        Page<ProcessTemplates> allformAndGroups =this.page(PageFactory.getDefaultPage(br.getPageNo(),br.getPageSize()),wrapper);
//        templateGroupMapper.getAllFormAndGroups();
        Map<Integer, List<ProcessTemplates>> coverMap = new LinkedHashMap<>();
        allformAndGroups.getRecords().forEach(fg -> {
            List<ProcessTemplates> bos = coverMap.get(fg.getGroupId());
            if (CollectionUtil.isEmpty(bos)) {
                List<ProcessTemplates> list = new ArrayList<>();
                list.add(fg);
                coverMap.put(fg.getGroupId(), list);
            } else {
                bos.add(fg);
            }
        });
        PageResult<TemplateGroupVo> pageResult=new  PageResult<TemplateGroupVo>();

        coverMap.forEach((key, val) -> {
            List<TemplateGroupVo> templates = new ArrayList<>();
            val.forEach(v -> {
                if (ObjectUtil.isNotNull(v.getTemplateId())) {
                    String defId="";
                    ProcessDefinition ProDef=repositoryService.createProcessDefinitionQuery()
                            .processDefinitionKey("Process_"+v.getTemplateId())
                            .latestVersion()
                            .singleResult();
                    if(ProDef!=null)
                    {
                        defId=ProDef.getId();
                    }
                    templates.add(TemplateGroupVo.builder()
                            .formId(v.getTemplateId())
                            .config(v.getConfig())
                            .remark(v.getRemark())
                            .formName(v.getFormName())
                            .orgId(String.valueOf(v.getOrgId()))
                            .isStop(v.getIsStop())
                            .updated(DateFormatUtils.format(v.getUpdated(),"yyyy年MM月dd日 HH时:mm分:ss秒"))
                            .templateId(v.getTemplateId())
                            .processDefinitionId(defId)
                            .build());
                }
            });
            pageResult.setRecords( templates);
        });
        pageResult.setPageSize(allformAndGroups.getSize());
        pageResult.setTotalRows( allformAndGroups.getTotal());
        pageResult.setPageNo(allformAndGroups.getPages());
        pageResult.setTotalPage(PageUtil.totalPage(Convert.toInt(pageResult.getTotalRows()), Convert.toInt(pageResult.getPageSize())));
        return  pageResult;
    }
}
