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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
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.FlowStatusEnum;
import com.yeejoin.amos.boot.module.hygf.api.dto.TaskModelDto;
import com.yeejoin.amos.boot.module.hygf.api.util.JsonUtils;
import com.yeejoin.amos.boot.module.hygf.biz.feign.TaskV2FeignService;
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;

    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 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) {
        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) && !result.isEmpty()) {
                    break;
                }
            }
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            TaskV2Model model = new TaskV2Model();
            BeanUtil.copyProperties(obj, model);
            String urlParams = "";
            try {
                urlParams = "&" + toQueryParams(obj.getModel());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            List<Map> urlList = JsonUtils.getResourceList(urlInfo);
            for (Map map : urlList) {
                // 获取暂存的可编辑页面url
                if (flag && map.get("type").equals(obj.getTaskType()) && map.get("pageType").equals("draft")) {
                    model.setRoutePath(map.get("url").toString() + urlParams);
                    break;
                }
                // 其他逻辑均按详情页面获取
                else if (map.get("type").equals(obj.getTaskType()) && map.get("pageType").equals(null == obj.getPageType() ? "look" : obj.getPageType())) {
                    model.setRoutePath(map.get("url").toString().replace("{roleIds}", obj.getNextExecuteUser()) + urlParams + "&nextExecuteUserIds=" + model.getExecuteUserIds());
                    break;
                }
            }
            // 是true则为暂存 除公共部分统一处理
            if (flag) {
                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);

        }
        taskV2FeignService.batchAdd(taskV2Models);
    }

    /**
     * 待办编辑接口
     * 参数
     * 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[] roleIds = model.getRoutePath().split("roleIds=");
//        String[] userIds = roleIds[1].split("&userId");
//        String url = roleIds[0]+"roleIds="+"55555"+"&userId"+ userIds[1];
//        String tarUrl = url.replaceFirst("&executeUserIds=", "");
//        tarUrl+"&executeUserIds="
        // model.setRoutePath( roleIds[0]+"roleIds="+"55555"+"&userId"+userIds[1]);
        // 当流程完成时将所有待办状态统一修改为已完成
        if (collect.get(0).getFlowStatusLabel().equals(FlowStatusEnum.TO_BE_FINISHED.getName())) {
            String urlParams = "";
            try {
                urlParams = "&" + toQueryParams(params.get("model"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            List<Map> urlList = JsonUtils.getResourceList(urlInfo);
            for (Map map : urlList) {
                if (map.get("type").equals(collect.get(0).getTaskType()) && map.get("pageType").equals("look")) {
                    urlParams = map.get("url").toString().replace("{roleIds}", "") + urlParams + "&taskStatus" + collect.get(0).getTaskStatus() + "&nextExecuteUserIds=";
                    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);
    }

    /**
     * 待办编辑接口       【如果没有代办直接返回空，业务判断】   ---- 在用，误删
     * 参数
     * taskStatus
     * taskStatusLabel 操作名称  1驳回 2通过 3重新提交
     * flowStatusLabel  任务状态枚举code
     * 流程实例id  instanceId
     * flowCode 任务id
     **/
    public TaskV2Model updateTaskModelNew(Map<String, Object> params) {
        String exeUserId = RequestContext.getExeUserId();
        List<TaskV2Model> result = taskV2FeignService.selectListByRelationId(params.get("relationId").toString()).getResult();

        // TaskV2Model model = result.stream().filter(e->e.getFlowCode().equals(params.get("flowCode").toString())).sorted((r1, r2) -> r2.getSequenceNbr().compareTo(r2.getSequenceNbr())) // 按时间降序排序
        //         .findFirst()
        //         .orElse(null);
        List<TaskV2Model> collect = result.stream().sorted((r1, r2) -> r2.getSequenceNbr().compareTo(r1.getSequenceNbr())).collect(Collectors.toList());
        if (null == collect || collect.size() == 0) {
            TaskV2Model model = new TaskV2Model();
            model.setFlowStatus(Integer.valueOf(params.get("flowStatus").toString()));
            model.setFlowStatusLabel(params.get("flowStatusLabel").toString());
            model.setTaskStatus(Integer.valueOf(params.get("taskStatus").toString()));
            model.setTaskStatusLabel(params.get("taskStatusLabel").toString());
            return model;
        }
        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());
        // 当流程完成时将所有待办状态统一修改为已完成
        if (collect.get(0).getFlowStatusLabel().equals(FlowStatusEnum.TO_BE_FINISHED.getName())) {
            String urlParams = "";
            try {
                urlParams = "&" + toQueryParams(params.get("model"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            List<Map> urlList = JsonUtils.getResourceList(urlInfo);
            for (Map map : urlList) {
                if (map.get("type").equals(collect.get(0).getTaskType()) && map.get("pageType").equals("look")) {
                    urlParams = map.get("url").toString().replace("{roleIds}", "") + urlParams + "&nextExecuteUserIds=";
                    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());
        }
        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) : "";
    }
}