package com.mortals.xhx.daemon.demo;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mortals.framework.model.PageInfo;
import com.mortals.xhx.feign.flowable.IApiFlowInstanceFeign;
import com.mortals.xhx.feign.flowable.IApiFlowModelFeign;
import com.mortals.xhx.flowable.model.ModelInfoVo;
import com.mortals.xhx.flowable.processinstance.ProcessDeleteReq;
import com.mortals.xhx.flowable.runtime.StartProcessInstanceReq;
import com.mortals.xhx.common.model.RequestTaskReq;
import com.mortals.xhx.common.pdu.api.ApiReqPdu;
import com.mortals.xhx.common.pdu.api.ApiRespPdu;
import com.mortals.xhx.feign.flowable.IApiFlowDefinitionFeign;
import com.mortals.xhx.feign.flowable.IApiFlowFeign;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * @author karlhoo
 */
@CommonsLog
@RestController
@RequestMapping("test")
public class RequestDispatchController {
    @Autowired
    private IApiFlowFeign apiFlowFeign;
    @Autowired
    private IApiFlowDefinitionFeign apiFlowDefinitionFeign;
    @Autowired
    private IApiFlowInstanceFeign apiFlowInstanceFeign;
    @Autowired
    private IApiFlowModelFeign apiFlowModelFeign;


    /**
     * eeeee
     *
     * @param multipartFile
     * @return
     */
    @RequestMapping(value = "/importXml", method = RequestMethod.POST)
    public ApiRespPdu importXml(@RequestParam("file") MultipartFile multipartFile) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            String xml = IoUtil.readUtf8(multipartFile.getInputStream());
            log.info(xml);

            respPdu.setData(xml);

            //respPdu = apiFlowDefinitionFeign.save("test", "请假", xml,"test");

        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }


    /**
     * 流程启动
     *
     * @param req
     * @return
     */
    @PostMapping("/instanceStart")
    public ApiRespPdu map(@RequestBody StartProcessInstanceReq req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {

            ApiRespPdu<String> respPdu1 = apiFlowInstanceFeign.startProcessInstanceByKey(req);

            respPdu.setData(JSON.toJSONString(respPdu1, SerializerFeature.DisableCircularReferenceDetect));
        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }


    /**
     * eeeee
     *
     * @param multipartFile
     * @return
     */
    @RequestMapping(value = "/importXmlToModel", method = RequestMethod.POST)
    public ApiRespPdu importXmlToModel(@RequestParam("file") MultipartFile multipartFile) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            String xml = IoUtil.readUtf8(multipartFile.getInputStream());
            log.info(xml);


            ModelInfoVo modelInfoVo = new ModelInfoVo();
            modelInfoVo.setModelXml(xml);
            modelInfoVo.setModelId("123");
            modelInfoVo.setFileName("测试流程.bpmn20.xml");
            modelInfoVo.setModelKey("1231");
            modelInfoVo.setPlatformSn("platform_java");
            modelInfoVo.setCategoryCode("财务部");

            respPdu = apiFlowModelFeign.saveBpmnModel(modelInfoVo);
            // respPdu = apiFlowModelFeign.addBpmnModel(modelInfoVo);




        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }


    /**
     * 流程启动
     *
     * @param req
     * @return
     */
    @PostMapping("/instanceReadImage")
    public ApiRespPdu instanceReadImage(@RequestBody ProcessDeleteReq req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {

            //ApiRespPdu<String> resp = apiFlowInstanceFeign.getFlowImage(req.getProcessInstanceId());

            // respPdu.setData(JSON.toJSONString(resp, SerializerFeature.DisableCircularReferenceDetect));
        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }




    /**
     * adfafafd
     *
     * @param req
     * @return
     */
    @PostMapping("/readXml")
    public ApiRespPdu readXml(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            respPdu = apiFlowDefinitionFeign.readXml(req.getTransmission().getDeployId());
        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }

    /**
     * adfasfd
     *
     * @param req
     * @return
     */
    @PostMapping("/readImage")
    public ApiRespPdu readImage(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            respPdu = apiFlowDefinitionFeign.readImage(req.getTransmission().getDeployId());

            String data = respPdu.getData();
            byte[] decode = Base64.decode(data);

            FileUtil.writeBytes(decode, "E://pic//1.png");


        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }

    /**
     * fafda
     *
     * @param req
     * @return
     */
    @PostMapping("/delete")
    public ApiRespPdu delete(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            respPdu = apiFlowDefinitionFeign.delete(req.getTransmission().getDeployId());
        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }

    /**
     * afdasfdasfd
     *
     * @param req
     * @return
     */
    @PostMapping("/list")
    public ApiRespPdu list(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        try {
            PageInfo pageInfo = new PageInfo();
            //ApiRespPdu<Result<FlowProcDefPdu>> list = apiFlowDefinitionFeign.list(new FlowProcDefPdu() ,pageInfo);
            //respPdu.setData(JSON.toJSONString(list.getData()));
        } catch (Exception e) {
            log.error("error", e);
        }
        return respPdu;
    }

    /**
     * dfasfdaf
     *
     * @param req
     * @return
     */
    @PostMapping("task/acceptor")
    public ApiRespPdu taskAcceptor(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        log.info("receive api  request:" + JSON.toJSONString(req));
        String processDiagram = apiFlowFeign.getProcessDiagram(req.getTransmission().getProcessInstanceId());
        log.info("receive api base64  receive:" + processDiagram);

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();

        respPdu.setData(processDiagram);
        return respPdu;
    }

    /**
     * fasfdasfd
     *
     * @param req
     * @return
     */
    @PostMapping("task/deploy")
    public ApiRespPdu deploy(@RequestBody ApiReqPdu<RequestTaskReq> req) {

        log.info("receive api  request:" + JSON.toJSONString(req));
        ApiRespPdu<String> deploy = apiFlowFeign.deploy(req.getTransmission().getModelId());
        log.info("receive api base64  receive:" + JSON.toJSONString(deploy));

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        respPdu.setData(JSON.toJSONString(deploy));
        return respPdu;
    }

    /**
     * dfafdasfda
     *
     * @param req
     * @return
     */
    @PostMapping("task/start")
    public ApiRespPdu start(@RequestBody ApiReqPdu<RequestTaskReq> req) {
        log.info("receive api  request:" + JSON.toJSONString(req));

        ApiRespPdu<String> start = apiFlowFeign.start(req.getTransmission().getDeployId(), req.getTransmission().getUserId(), req.getTransmission().getDataKey());
        log.info("receive api start  receive:" + JSON.toJSONString(start));

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        respPdu.setData(JSON.toJSONString(start));
        return respPdu;
    }

    /**
     * afasdfasf
     *
     * @param req
     * @return
     */
    @PostMapping("task/complete")
    public ApiRespPdu taskComplete(@RequestBody ApiReqPdu<RequestTaskReq> req) {
        log.info("receive api  request:" + JSON.toJSONString(req));

        //任务完成，设置审核人，完成当前任务

        HashMap<String, Object> map = new HashMap<>();
        map.put("test", "1111");

        apiFlowFeign.taskByAssignee(req.getTransmission().getTaskId(), req.getTransmission().getAssignee(), map);

        ApiRespPdu<String> start = apiFlowFeign.start(req.getTransmission().getDeployId(), req.getTransmission().getUserId(), req.getTransmission().getDataKey());
        log.info("receive api complete  receive:" + JSON.toJSONString(start));

        ApiRespPdu<String> respPdu = new ApiRespPdu<>();
        respPdu.setData(JSON.toJSONString(start));
        return respPdu;
    }


    /**
     * 测试 发起审核流程
     *
     * @param req
     * @return
     */
    @PostMapping("process/start")
    public ApiRespPdu processStart(@RequestBody ApiReqPdu<RequestTaskReq> req) {
        log.info("receive processStart  request:" + JSON.toJSONString(req));

        ApiRespPdu<String> start = apiFlowFeign.start(req.getTransmission().getDeployId(), req.getTransmission().getUserId(), req.getTransmission().getDataKey());

        log.info("receive api complete  receive:" + JSON.toJSONString(start));


        //流程发起成功后 数据与流程进行绑定 并更新当前业务数据审核状态

//        ApiRespPdu<List<Map<String, Object>>> maps = apiFlowFeign.getRuntimeBusinessKeyByUser("admin");
//        Map<String, Object> taskMap = maps.getData().stream().findAny().orElseGet(() -> null);
//        String taskId = (String) taskMap.get("taskId");

        String taskId = getTaskId("admin");
        log.info("taskId:" + taskId);

        ApiRespPdu<String> resp = apiFlowFeign.getTaskInfo(taskId);
        String processId = resp.getData();

        //下个流程有分配人为变量，所以要提前设置变量值
        apiFlowFeign.setVariable(taskId, "reviewer", "bbb");

        // 设置 assigneeList 参数
        //这个参数是在进入会签节点之前就设置了
        List<String> assigneeList = new ArrayList<>();
        assigneeList.add("a1");
        assigneeList.add("a2");
        assigneeList.add("a3");
        assigneeList.add("a4");
        assigneeList.add("a5");
        assigneeList.add("a6");
        apiFlowFeign.setListVariable(taskId, "assigneeList", assigneeList);

        Map<String, Object> map = new HashMap<>();

        //由第一个审核人进行审核  由用户获取自己的当前任务列表
        log.info("first assign admin 进行审核");
        ApiRespPdu<String> respPdu = apiFlowFeign.taskByAssignee(taskId, "admin", map);
        log.info("assign first flow:" + JSON.toJSONString(respPdu));

        //由第二个人进行审核 从新获取审核人的任务实例

        log.info("second assign b1 进行审核");
        respPdu = apiFlowFeign.taskByAssignee(getTaskId("bbb"), "bbb", map);
        log.info("assign second flow:" + JSON.toJSONString(respPdu));

        log.info("third assign  分支进行审核");
        ApiRespPdu<List<Map<String, Object>>> runtimeBusinessKeyByGroup = apiFlowFeign.getRuntimeBusinessKeyByGroup(new ArrayList<>(Arrays.asList("test-1")));

        Map<String, Object> thirdTaskMap = runtimeBusinessKeyByGroup.getData().stream().findAny().orElseGet(() -> null);
        taskId = (String) thirdTaskMap.get("taskId");
        log.info("sep_2 taskId:" + taskId);

        // 流程完成所需的条件参数
        map = new HashMap<>();
        map.put("assignee", "a2");
        // 完成任务，taskId 任务节点 ID
        respPdu = apiFlowFeign.taskByAssignee(taskId, "admin", map);
        log.info("assign four flow:" + JSON.toJSONString(respPdu));


        log.info("four assign  审核");
        apiFlowFeign.taskByAssignee(getTaskId("a2"), "a2", new HashMap<>());


        log.info("a1 assign  会签审核");
        apiFlowFeign.taskByAssignee(getTaskId("a1"), "a1", new HashMap<>());

        log.info("a2 assign  会签审核");
        apiFlowFeign.taskByAssignee(getTaskId("a2"), "a2", new HashMap<>());

        log.info("a3 assign  会签审核");
        apiFlowFeign.taskByAssignee(getTaskId("a3"), "a3", new HashMap<>());

        log.info("a4 assign  会签审核");
        apiFlowFeign.taskByAssignee(getTaskId("a4"), "a4", new HashMap<>());

        //终止流程

        log.info("processId:" + processId);
        if (!ObjectUtils.isEmpty(processId)) {
            ApiRespPdu<Boolean> booleanApiRespPdu = apiFlowFeign.checkProcessInstanceFinish(processId);
            if (booleanApiRespPdu.getData()) {
                log.info("process finish ！");
            } else {
                log.info("process unfinish ！");
            }

        }
        // apiFlowFeign.deleteProcess(resp.getData());


        return respPdu;
    }

    public String getTaskId(String userId) {

        ApiRespPdu<List<Map<String, Object>>> map = apiFlowFeign.getRuntimeBusinessKeyByUser(userId);


        if (map.getData().size() > 0) {
            Map<String, Object> taskMap = map.getData().get(map.getData().size() - 1);

            // Map<String, Object> taskMap = map.getData().stream().fin().orElseGet(() -> null);
            String taskId = (String) taskMap.get("taskId");
            log.info(" map:" + JSON.toJSONString(taskMap));
            return taskId;
        }

        return null;

    }


    public static void main(String[] args) {

        StartProcessInstanceReq req = new StartProcessInstanceReq();
        req.setBusinessKey("12321");
        req.setCreator("12412");
        req.setFormName("421313");
        req.setPlatformSn("jdjd");
        req.setUserCode("sde3312");

        HashMap<String, Object> map = new HashMap<>();
        map.put("test", "ddddd");
        map.put("3323", "啊打发");
        req.setVariables(map);

        System.out.println(JSON.toJSONString(req));


        ProcessDeleteReq processDeleteReq = new ProcessDeleteReq();
        //processDeleteReq.setProcessInstanceId("123123123");
        System.out.println(JSON.toJSONString(processDeleteReq));


    }

}
