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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.hygf.api.Enum.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.FlowKeyTodoEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.FlowStatusEnum;
import com.yeejoin.amos.boot.module.hygf.api.dto.TaskModelDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.WorkflowResultDto;
import com.yeejoin.amos.boot.module.hygf.api.util.JsonUtils;
import com.yeejoin.amos.boot.module.hygf.biz.feign.TaskV2FeignService;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 公共服务实现类
 *
 * @author hzz
 * @date 2024-06-20
 */
@Service
@Slf4j
public class CommonServiceImpl {
    @Autowired
    private TaskV2FeignService taskV2FeignService;
    @Autowired
    private RedisUtils redisUtils;
    @Value("classpath:/json/urlInfo.json")
    private Resource urlInfo;
    @Autowired
    private AmosRequestContext amosRequestContext;

    private static String toQueryParams2(JSONObject jsonObject) {
        StringBuilder sb = new StringBuilder();
        Set<String> keys = jsonObject.keySet();
        keys.forEach(key -> {
            Object value = jsonObject.get(key);
            if (sb.length() > 0) {
                sb.append('&');
            }
            try {
                if (value != null && !"".equals(value)) {
                    sb.append(URLEncoder.encode(key, "UTF-8")).append('=').append(URLEncoder.encode(value.toString(), "UTF-8"));
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        });
        return sb.toString();
    }

    public List<TaskModelDto> buildTaskModelDto(Object model, WorkflowResultDto workflowResultDto, BusinessTypeEnum businessType) {
        List<TaskModelDto> taskModelDtoList = new ArrayList<>();
        TaskModelDto taskModelDto = new TaskModelDto();
        FlowKeyTodoEnum flowKeyTodoEnum = FlowKeyTodoEnum.getEumByFlowNodeKey(workflowResultDto.getNextNodeKey());
        if (!Objects.isNull(flowKeyTodoEnum)) {
            taskModelDto.setFlowStatus(flowKeyTodoEnum.getCode());
            taskModelDto.setFlowStatusLabel(flowKeyTodoEnum.getDealName());
        }
        taskModelDto.setRoutePath(null);
        taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
        taskModelDto.setFlowCreateDate(new Date());
        taskModelDto.setPageType(null);
        taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecuteUserIds());
        taskModelDto.setModel(model);
        taskModelDto.setRelationId(workflowResultDto.getInstanceId());
        taskModelDto.setStartUserId(workflowResultDto.getStartUserId());
        taskModelDto.setStartUser(workflowResultDto.getStartUser());
        taskModelDto.setStartDate(workflowResultDto.getStartDate());
        taskModelDto.setStartUserCompanyName(workflowResultDto.getStartUserCompanyName());
        taskModelDto.setTaskName(workflowResultDto.getNextNodeName());
        taskModelDto.setTaskCode(workflowResultDto.getNextNodeKey());
        taskModelDto.setTaskType(businessType.getCode());
        taskModelDto.setTaskTypeLabel(businessType.getName());
        taskModelDto.setTaskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
        taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
//        taskModelDto.setTaskDesc();
//        taskModelDto.setTaskContent();
        taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorIds());
        taskModelDtoList.add(taskModelDto);
        return taskModelDtoList;
    }

    public void deleteTaskModel(String id) {
        List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(id).getResult();
        if (!result.isEmpty()) {
            List<Long> idList = result.stream().map(TaskV2Model::getSequenceNbr).collect(Collectors.toList());
            String ids = idList.stream().map(Object::toString).collect(Collectors.joining(","));
            taskV2FeignService.delete(ids);
        }
    }

    /**
     * 待办新增接口
     **/
    public void buildTaskModel(List<TaskModelDto> list) {
        //执行人为空使用系统机器人账号
        if (StrUtil.isEmpty(RequestContext.getExeUserId())) {
            RequestContext.setExeUserId(amosRequestContext.getUserId());
            RequestContext.setToken(amosRequestContext.getToken());
            RequestContext.setAgencyCode("JXIOP");
        }
        List<TaskV2Model> taskV2Models = new ArrayList<>();
        for (TaskModelDto obj : list) {
            // 判断是否是暂存 新增若无下一节点执行人即为暂存
            boolean flag = StringUtils.isEmpty(obj.getNextExecuteUser());
            if (flag) {
                List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(obj.getRelationId()).getResult();
                if (CollectionUtil.isNotEmpty(result)) {
                    break;
                }
            }
            //处理开始流程人员为空的问题
            dealStartUser(obj);
            TaskV2Model model = new TaskV2Model();
            BeanUtil.copyProperties(obj, model);
            String urlParams = "&formType=edit";
            try {
                urlParams = "&" + toQueryParams(obj.getModel());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            List<Map> urlList = JsonUtils.getResourceList(urlInfo);
            for (Map map : urlList) {
                if (map.get("type").equals(obj.getTaskCode())) {
                    model.setRoutePath(map.get("url").toString() + urlParams);
                    break;
                }
            }
            // 是true则为暂存 除公共部分统一处理
            if (flag) {
                Object redisUserInfo = redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken()));
                if (Objects.isNull(redisUserInfo)) {
                    break;
                }
                ReginParams reginParams = JSONObject.parseObject(redisUserInfo.toString(), ReginParams.class);
                model.setFlowStatus(FlowStatusEnum.TO_BE_SUBMITTED.getCode());
                model.setFlowStatusLabel(FlowStatusEnum.TO_BE_SUBMITTED.getName());
                model.setStartUserId(RequestContext.getExeUserId());
                model.setStartUser(reginParams.getUserModel().getRealName());
                model.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
                model.setStartDate(new Date());
                model.setExecuteUserIds(RequestContext.getExeUserId());
                model.setFlowCreateDate(new Date());
                model.setTaskStatus(FlowStatusEnum.TO_BE_SUBMITTED.getCode());
                model.setTaskTitle("有一条待提交的草稿");
                model.setTaskName(BusinessTypeEnum.getNameByType(obj.getTaskType()));
                model.setTaskTypeLabel(BusinessTypeEnum.getNameByType(obj.getTaskType()));
                //     model.setTaskContent("【申请单号:"+obj.getTaskCode()+"】待提交");
            } else {
                model.setTaskStatus(0);
                model.setTaskTitle(obj.getStartUser() + "发起了" + obj.getTaskName());
            }
            model.setFlowInstanceId(model.getRelationId());
            model.setTaskSource("workFlow");
            model.setExtras(JSON.toJSONString(obj.getModel()));
            // model.setTerminal(params.getOrDefault("terminal","WEB").toString());
            model.setCreateDate(new Date());
            model.setRecUserId(RequestContext.getExeUserId());
            model.setAgencyCode(RequestContext.getAgencyCode());
            taskV2Models.add(model);

        }
        //如果使用的是机器人则使用机器人的token、appkey、product进行调用
        if (amosRequestContext.getUserId().equals(RequestContext.getExeUserId())) {
            taskV2FeignService.batchAddNew(amosRequestContext.getAppKey(), amosRequestContext.getProduct(), amosRequestContext.getToken(), taskV2Models);
        } else {
            taskV2FeignService.batchAdd(taskV2Models);
        }
    }

    private void dealStartUser(TaskModelDto obj) {
        if (StrUtil.isEmpty(obj.getStartUser())) {
            List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(obj.getRelationId()).getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                List<TaskV2Model> collect = result.stream().filter(item -> item.getStartUser() != null).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)) {
                    TaskV2Model taskV2Model = collect.get(0);
                    obj.setStartUserId(taskV2Model.getStartUserId());
                    obj.setStartUser(taskV2Model.getStartUser());
                    obj.setStartDate(taskV2Model.getStartDate());
                    obj.setStartUserCompanyName(taskV2Model.getStartUserCompanyName());
                }
            }
        }
    }

    /**
     * 待办编辑接口
     * 参数
     * taskStatus
     * taskStatusLabel 操作名称  6614驳回 6616已完成 6612待受理
     * flowStatusLabel  任务状态枚举code
     * 流程实例id  instanceId
     * flowCode 任务id
     **/
    public TaskV2Model updateTaskModel(Map<String, Object> params) {
        String exeUserId = RequestContext.getExeUserId();
        List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(params.get("relationId").toString()).getResult();
        List<TaskV2Model> collect = result.stream().sorted((r1, r2) -> r2.getSequenceNbr().compareTo(r1.getSequenceNbr())).collect(Collectors.toList());

        if (collect.isEmpty()) {
            return null;
        }
        collect.get(0).setFlowStatus(Integer.valueOf(params.get("flowStatus").toString()));
        collect.get(0).setFlowStatusLabel(params.get("flowStatusLabel").toString());
        collect.get(0).setTaskStatus(Integer.valueOf(params.get("taskStatus").toString()));
        collect.get(0).setTaskStatusLabel(params.get("taskStatusLabel").toString());
        collect.get(0).setEndUserId(exeUserId);
        collect.get(0).setEndDate(new Date());
        // 当流程完成时将所有待办状态统一修改为已完成
        String urlParams = "&formType=detail";
        if (collect.get(0).getFlowStatusLabel().equals(FlowStatusEnum.TO_BE_FINISHED.getName())) {
            try {
                urlParams = "&" + toQueryParams(params.get("model"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            List<Map> urlList = JsonUtils.getResourceList(urlInfo);
            for (Map map : urlList) {
                //此处单独处理经销商审核 审核完成后跳转列表页面
                if("jxs_03".equals(collect.get(0).getTaskCode())){
                    urlParams = "/mixuap?appId=1678340647909617665&id=1678365817248444417"+ urlParams;
                    break;
                }
                if (map.get("type").equals(collect.get(0).getTaskCode())) {
                    urlParams = map.get("url").toString() + urlParams;
                    break;
                }
            }
            collect.get(0).setRoutePath(urlParams);
            for (TaskV2Model taskV2Model : collect) {
                taskV2Model.setTaskStatusLabel((FlowStatusEnum.TO_BE_FINISHED.getName()));
                taskV2Model.setTaskStatus(FlowStatusEnum.TO_BE_FINISHED.getCode());
                taskV2Model.setFlowStatusLabel((FlowStatusEnum.TO_BE_FINISHED.getName()));
                taskV2Model.setFlowStatus(FlowStatusEnum.TO_BE_FINISHED.getCode());
            }
            taskV2FeignService.batchUpdate(collect);
        } else {
            collect.get(0).setRoutePath(collect.get(0).getRoutePath().replace("roleIds=", "roleIds=55555&fq="));
            taskV2FeignService.update(collect.get(0), collect.get(0).getSequenceNbr());
        }
        // 修改model并返回 用于组装新待办
        collect.get(0).setEndUserId(null);
        collect.get(0).setTaskStatus(null);
        collect.get(0).setEndDate(null);
        collect.get(0).setSequenceNbr(null);
        collect.get(0).setCreateDate(new Date());
        collect.get(0).setStartDate(new Date());
        return collect.get(0);
    }


    /**
     * 待办 撤回
     *
     * @param id  工作流实例id
     * @param obj 自己的实体：taskType为BusinessTypeEnum code；nextExecuteUser
     */
    public void rollbackTask(String id, JSONObject obj) {

        List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(id).getResult();
        List<TaskV2Model> list = result.stream().sorted((r1, r2) -> r2.getSequenceNbr().compareTo(r1.getSequenceNbr())).collect(Collectors.toList());
        TaskV2Model model = list.get(0);
        taskV2FeignService.delete(String.valueOf(model.getSequenceNbr()));

        String urlParams = "";
        urlParams = "&" + toQueryParams2(obj);
        List<Map> urlList = JsonUtils.getResourceList(urlInfo);

        if (list.size() > 1) {
            TaskV2Model lastTaskModel = list.get(1);
            lastTaskModel.setEndUserId(null);
            lastTaskModel.setEndDate(null);
            lastTaskModel.setTaskStatus(FlowStatusEnum.TO_SUBMITTED.getCode());
            lastTaskModel.setTaskStatusLabel("重新提交");
            lastTaskModel.setFlowCode(obj.get("nextTaskId").toString());
            if (obj.get("flowStatus") != null) {
                lastTaskModel.setFlowStatus(Integer.valueOf(obj.get("flowStatus").toString()));
            }
            if (obj.get("flowStatusLabel") != null) {
                lastTaskModel.setFlowStatusLabel(obj.get("flowStatusLabel").toString());
            }

            for (Map map : urlList) {
                if (map.get("type").equals(obj.get("taskType")) && map.get("pageType").equals(obj.getOrDefault("pageType", "edit"))) {
                    lastTaskModel.setRoutePath(map.get("url").toString().replace("{roleIds}", obj.get("nextExecuteUser").toString()) + urlParams);
                    break;
                }
            }
            taskV2FeignService.update(lastTaskModel, lastTaskModel.getSequenceNbr());
        } else if (list.size() == 1) {
            model.setExecuteUserIds(model.getStartUserId());
            model.setTaskStatusLabel("重新提交");
            model.setTaskStatus(FlowStatusEnum.TO_SUBMITTED.getCode());
            model.setSequenceNbr(null);
            if (obj.get("flowStatus") != null) {
                model.setFlowStatus(Integer.valueOf(obj.get("flowStatus").toString()));
            }
            if (obj.get("flowStatusLabel") != null) {
                model.setFlowStatusLabel(obj.get("flowStatusLabel").toString());
            }
            for (Map map : urlList) {
                if (map.get("type").equals(obj.get("taskType")) && map.get("pageType").equals("edit")) {
                    model.setRoutePath(map.get("url").toString().replace("{roleIds}", obj.get("nextExecuteUser").toString()) + urlParams);
                    break;
                }
            }
            taskV2FeignService.create(model);
        }
    }

    public <T> String toQueryParams(T obj) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();

        for (Class<?> clazz = obj.getClass(); !clazz.equals(Object.class); clazz = clazz.getSuperclass()) {
            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                if (!Modifier.isStatic(field.getModifiers())) {
                    field.setAccessible(true);

                    try {
                        Object value = field.get(obj);

                        if (value != null && !"".equals(value)) {
                            String encodedValue = URLEncoder.encode(value.toString(), "UTF-8");
                            sb.append(field.getName()).append('=').append(encodedValue).append('&');
                        }
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : "";
    }
}