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

import com.alibaba.fastjson.JSONObject;
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.FlowStatusEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.pdu.api.ApiRespPdu;
import com.mortals.xhx.common.pdu.flow.*;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.feign.flowable.IApiFlowDefinitionFeign;
import com.mortals.xhx.feign.flowable.IApiFlowInstanceFeign;
import com.mortals.xhx.feign.flowable.IApiFlowTaskFeign;
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.FlowableDefinitionEntity;
import com.mortals.xhx.module.form.model.FormEntity;
import com.mortals.xhx.module.form.service.FormService;
import com.mortals.xhx.module.task.dao.TaskFormDao;
import com.mortals.xhx.module.task.model.TaskFormEntity;
import com.mortals.xhx.module.task.model.TaskProcessQuery;
import lombok.extern.apachecommons.CommonsLog;
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.task.dao.TaskProcessDao;
import com.mortals.xhx.module.task.model.TaskProcessEntity;
import com.mortals.xhx.module.task.service.TaskProcessService;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service("taskProcessService")
@CommonsLog
public class TaskProcessServiceImpl extends AbstractCRUDServiceImpl<TaskProcessDao, TaskProcessEntity, Long>  implements TaskProcessService {

    @Autowired
    private IApiFlowTaskFeign apiFlowTaskFeign;

    @Autowired
    private IApiFlowInstanceFeign iApiFlowInstanceFeign;
    @Autowired
    private DeployFormService deployFormService;
    @Autowired
    private FormService formService;

    @Autowired
    private InterceptorConfig config;

    @Override
    public Result<TaskProcessEntity> getProcessList(TaskProcessQuery query, PageInfo pageInfo, Context context) {

        Result<TaskProcessEntity> result = new Result<>();
        FlowTaskPdu flowTaskPdu = new FlowTaskPdu();
        flowTaskPdu.setUserId(context.getUser().getLoginName());
        try {
            if (!ObjectUtils.isEmpty(query)) {
                BeanUtils.copyProperties(query, flowTaskPdu, BeanUtil.getNullPropertyNames(query));
            }
            ApiRespPdu<Result<FlowTaskPdu>> resp = apiFlowTaskFeign.myProcess(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<TaskProcessEntity> collect = resp.getData().getList().stream().map(item -> {
                    TaskProcessEntity taskProcessEntity = new TaskProcessEntity();
                    BeanUtils.copyProperties(item, taskProcessEntity, BeanUtil.getNullPropertyNames(item));
                    taskProcessEntity.setProcDefVersion("v" + item.getProcDefVersion());
                    if (ObjectUtils.isEmpty(item.getFinishTime())) {
                        taskProcessEntity.setFlowStatus(FlowStatusEnum.FLOW_RUNNING.getValue());
                    } else {
                        taskProcessEntity.setFlowStatus(FlowStatusEnum.FLOW_FINISH.getValue());
                    }
                    return taskProcessEntity;
                }).collect(Collectors.toList());
                result.setList(collect);
                result.setPageInfo(resp.getData().getPageInfo());
            } else {
                result.setList(Collections.emptyList());
            }
        } catch (Exception e) {
            throw new AppException("获取流程定义列表异常：" + e.getMessage());
        }

        return result;
    }

    @Override
    public List<FlowViewerPdu> getFlowViewer(String procInsId) {

        List<FlowViewerPdu> flowViewerList = null;
        try {

            ApiRespPdu<List<FlowViewerPdu>> resp = iApiFlowInstanceFeign.getFlowViewer(procInsId);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取流程定义列表异常：" + resp.getMsg());
                throw new AppException("获取流程定义列表异常：" + resp.getMsg());
            }
            flowViewerList = resp.getData();
        } catch (Exception e) {
            throw new AppException("获取流程定义列表异常：" + e.getMessage());
        }

        return flowViewerList;
    }

    @Override
    public Map<String, Object> getProcessVariables(String taskId) {
        try {
            log.error("获取流程变量 taskId：" + taskId);
            ApiRespPdu<Map<String, Object>> resp = apiFlowTaskFeign.processVariables(taskId);
            log.info("获取流程变量 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取流程变量异常：" + resp.getMsg());
                throw new AppException("获取流程变量异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException("获取流程变量异常：" + e.getMessage());
        }

    }

    @Override
    public FlowNextPdu getNextFlowNode(String data, Context context) {
        try {
            FlowTaskVoPdu flowTaskVoPdu = JSONObject.parseObject(data, FlowTaskVoPdu.class);
            ApiRespPdu<FlowNextPdu> resp = apiFlowTaskFeign.getNextFlowNode(flowTaskVoPdu);
            log.info("获取下一节点 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取下一节点异常：" + resp.getMsg());
                throw new AppException("获取下一节点异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException("获取下一节点异常：" + e.getMessage());
        }
    }

    @Override
    public Result<FlowTaskPdu> getFinishList(TaskProcessQuery query, PageInfo pageInfo, Context context) {
        return null;
    }

    @Override
    public Map<String, Object> flowRecord(String procInsId, String deployId, Context context) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            ApiRespPdu<List<FlowTaskPdu>> resp = apiFlowTaskFeign.flowRecord(procInsId, deployId);
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取办理列表异常：" + resp.getMsg());
                throw new AppException("获取办理列表异常：" + resp.getMsg());
            }

            if (!ObjectUtils.isEmpty(resp.getData())) {
                map.put("flowList", resp.getData());
            }
            // 第一次申请获取初始化表单
            if (!ObjectUtils.isEmpty(deployId)) {
                DeployFormQuery deployFormQuery = new DeployFormQuery();
                deployFormQuery.setDeployId(deployId);
                FormEntity formEntity = deployFormService.find(deployFormQuery, context).stream().findFirst().map(item -> formService.get(item.getFormId(), context)).orElseGet(() -> null);
                if (ObjectUtils.isEmpty(formEntity)) {
                    throw new AppException("请先配置流程表单");
                }
                map.put("formData", JSONObject.parseObject(formEntity.getFormContent()));
            }

            return map;
        } catch (Exception e) {
            throw new AppException("获取办理列表异常：" + e.getMessage());
        }

    }

    @Override
    public String stopProcess(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.stopProcess(flowTaskVoPdu);
            log.info("取消申请 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("取消申请异常：" + resp.getMsg());
                throw new AppException("取消申请异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String complete(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.complete(flowTaskVoPdu);
            log.info("审核任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("审核任务异常：" + resp.getMsg());
                throw new AppException("审核任务异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String reject(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.reject(flowTaskVoPdu);
            log.info("拒绝任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("拒绝任务异常：" + resp.getMsg());
                throw new AppException("拒绝异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String taskReturn(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.taskReturn(flowTaskVoPdu);
            log.info("回退任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("回退任务异常：" + resp.getMsg());
                throw new AppException("回退任务异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String delete(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.delete(flowTaskVoPdu);
            log.info("取消任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("取消任务异常：" + resp.getMsg());
                throw new AppException("取消异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String claim(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.claim(flowTaskVoPdu);
            log.info("签收任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("签收任务异常：" + resp.getMsg());
                throw new AppException("签收异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String unClaim(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.unClaim(flowTaskVoPdu);
            log.info("拒绝签收任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("拒绝签收任务异常：" + resp.getMsg());
                throw new AppException("拒绝签收异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String delegateTask(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.delegateTask(flowTaskVoPdu);
            log.info("委派任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("委派任务异常：" + resp.getMsg());
                throw new AppException("委派异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public String assignTask(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<String> resp = apiFlowTaskFeign.assignTask(flowTaskVoPdu);
            log.info("转办任务 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("转办任务异常：" + resp.getMsg());
                throw new AppException("转办异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }

    @Override
    public List<FlowUserTaskPdu> getReturnList(FlowTaskVoPdu flowTaskVoPdu, Context context) {
        try {
            ApiRespPdu<List<FlowUserTaskPdu>> resp = apiFlowTaskFeign.findReturnTaskList(flowTaskVoPdu);
            log.info("获取所有可回退的节点 resp：" + JSONObject.toJSONString(resp));
            if (YesNoEnum.NO.getValue() == resp.getCode()) {
                log.error("获取所有可回退的节点异常：" + resp.getMsg());
                throw new AppException("拒获取所有可回退的节点异常：" + resp.getMsg());
            }
            return resp.getData();
        } catch (Exception e) {
            throw new AppException(e.getMessage());
        }
    }
}