package com.mortals.xhx.module.flowable.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.xhx.base.framework.config.InterceptorConfig;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.pdu.api.ApiRespPdu;
import com.mortals.xhx.common.pdu.flow.DefinitionVoPdu;
import com.mortals.xhx.common.pdu.flow.FlowProcDefPdu;
import com.mortals.xhx.common.pdu.flow.FlowSaveXmlPdu;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.feign.flowable.IApiFlowDefinitionFeign;
import com.mortals.xhx.module.deploy.model.DeployFormEntity;
import com.mortals.xhx.module.deploy.model.DeployFormQuery;
import com.mortals.xhx.module.deploy.service.DeployFormService;
import com.mortals.xhx.module.flowable.model.FlowableDefinitionQuery;
import com.mortals.xhx.module.form.model.FormEntity;
import com.mortals.xhx.module.form.model.FormQuery;
import com.mortals.xhx.module.form.service.FormService;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.module.flowable.dao.FlowableDefinitionDao;
import com.mortals.xhx.module.flowable.model.FlowableDefinitionEntity;
import com.mortals.xhx.module.flowable.service.FlowableDefinitionService;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>Title: 流程定义表</p>
 * <p>Description: FlowableDefinitionService service接口 </p>
 * <p>Copyright: Copyright &reg;  </p>
 *
 * @version 1.0.0
 */
@Service("flowableDefinitionService")
public class FlowableDefinitionServiceImpl extends AbstractCRUDServiceImpl<FlowableDefinitionDao, FlowableDefinitionEntity, Long> implements FlowableDefinitionService {
    @Autowired
    private DeployFormService deployFormService;
    @Autowired
    private FormService formService;
    @Autowired
    private IApiFlowDefinitionFeign apiFlowDefinitionFeign;
    @Autowired
    private InterceptorConfig config;

    @Override
    public Result<FlowableDefinitionEntity> getDefinList(FlowableDefinitionQuery query, PageInfo pageInfo, Context context) {
        Result<FlowableDefinitionEntity> result = new Result<>();
        FlowProcDefPdu flowProcDefPdu = new FlowProcDefPdu();
        try {
            if (!ObjectUtils.isEmpty(query)) {
                BeanUtils.copyProperties(query, flowProcDefPdu, BeanUtil.getNullPropertyNames(query));
            }
            ApiRespPdu<Result<FlowProcDefPdu>> resp = apiFlowDefinitionFeign.list(context.getUser().getId().toString(),config.getTenantId(),pageInfo);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取流程定义列表异常：" + resp.getMsg());
                throw new AppException("获取流程定义列表异常：" + resp.getMsg());
            }

            if (!ObjectUtils.isEmpty(resp.getData())) {
                List<FlowableDefinitionEntity> collect = resp.getData().getList().stream().map(item -> {
                    FlowableDefinitionEntity definitionEntity = new FlowableDefinitionEntity();
                    BeanUtils.copyProperties(item, definitionEntity, BeanUtil.getNullPropertyNames(item));
                    definitionEntity.setVersion("v" + item.getVersion());

                    definitionEntity.setProcDefId(item.getId());
                    //查询关联的form表单
                    DeployFormQuery deployFormQuery = new DeployFormQuery();
                    deployFormQuery.setDeployId(item.getDeploymentId());
                    DeployFormEntity deployFormEntity = deployFormService.find(deployFormQuery, null).stream().findFirst().orElseGet(() -> null);
                    if (!ObjectUtils.isEmpty(deployFormEntity)) {
                        FormEntity formEntity = formService.get(deployFormEntity.getFormId(), context);
                        if (!ObjectUtils.isEmpty(formEntity)) {
                            definitionEntity.setFormId(deployFormEntity.getFormId());
                            definitionEntity.setFormName(formEntity.getFormName() == null ? "" : formEntity.getFormName());
                        }
                    }
                    return definitionEntity;
                }).collect(Collectors.toList());
                result.setList(collect);
                result.setPageInfo(resp.getData().getPageInfo());
            } else {
                result.setList(Collections.emptyList());
            }
            return result;

        } catch (Exception e) {
            log.error("获取流程定义列表异常", e);
            throw new AppException("获取流程定义列表异常：" + e.getMessage());
        }
    }

    @Override
    public String readImage(String deployId) {
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.readImage(deployId);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取流程图片异常：" + resp.getMsg());
                throw new AppException("获取流程图片异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("获取流程图片异常", e);
            throw new AppException("获取流程图片异常：" + e.getMessage());
        }
    }

    @Override
    public String readXml(String deployId) {
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.readXml(deployId);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取流程XML异常：" + resp.getMsg());
                throw new AppException("获取流程XML异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("获取流程XML异常", e);
            throw new AppException("获取流程XML异常：" + e.getMessage());
        }
    }

    @Override
    public String saveXml(FlowSaveXmlPdu flowSaveXmlPdu,Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.save(flowSaveXmlPdu.getName(), flowSaveXmlPdu.getCategory(), flowSaveXmlPdu.getXml(),config.getTenantId());
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("保存流程XML异常：" + resp.getMsg());
                throw new AppException("保存流程XML异常：" + resp.getMsg());
            }
            return resp.getData();

        } catch (Exception e) {
            log.error("保存流程XML异常", e);
            throw new AppException("保存流程XML异常：" + e.getMessage());
        }
    }

    @SneakyThrows
    @Override
    public String start(String procDefId, String data, Context context) {

        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> variables = mapper.readValue(data, Map.class);
//        Map<String, Object> variables = new HashMap<>();
//        variables.put("data", data);
        String busiKey = "busiKey";
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.start(procDefId, config.getTenantId(),context.getUser().getId().toString(), busiKey, variables);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("流程实例化异常：" + resp.getMsg());
                throw new AppException("流程实例化异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("流程实例化异常", e);
            throw new AppException("流程实例化异常：" + e.getMessage());
        }
    }

    @Override
    public String updateState(DefinitionVoPdu definitionVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.updateState(definitionVoPdu.getState(),definitionVoPdu.getDeployId(),config.getTenantId());
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("流程挂起/激活异常：" + resp.getMsg());
                throw new AppException("流程挂起/激活异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("流程挂起/激活异常", e);
            throw new AppException("流程挂起/激活异常：" + e.getMessage());
        }
    }

    @Override
    public String deleteDefinition(DefinitionVoPdu definitionVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowDefinitionFeign.delete(definitionVoPdu.getDeployId());
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("删除流程异常：" + resp.getMsg());
                throw new AppException("删除流程异常异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("删除流程异常异常", e);
            throw new AppException(e.getMessage());
        }
    }
}