package com.zkqy.execution.produce.dispersed.service.impl;

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

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.zkqy.common.core.domain.AjaxResult;
import com.zkqy.common.core.domain.entity.SysRole;

import com.zkqy.common.utils.SecurityUtils;
import com.zkqy.common.utils.http.Sending;
import com.zkqy.execution.produce.dispersed.runbpm.PreExecutionToolClass;
import com.zkqy.execution.produce.dispersed.entity.BpmExecuteProcess;
import com.zkqy.execution.produce.dispersed.mapper.BpmExecuteProcessMapper;
import com.zkqy.execution.produce.dispersed.service.IBpmExecuteNodeMiddleService;
import com.zkqy.execution.produce.dispersed.service.IBpmExecuteProcessService;
import com.zkqy.system.entity.CommonEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * 流程执行任务Service业务层处理
 *
 * @author hzh
 * @date 2023-11-01
 */
@Service
public class BpmExecuteProcessServiceImpl implements IBpmExecuteProcessService {

    @Autowired // 执行流程
    private BpmExecuteProcessMapper runBpmExecuteProcessMapper;

    @Autowired  //预备执行流程工具类
    private PreExecutionToolClass ipreExecutionToolClass;

    @Autowired //执行流程用户、节点关联脚本中间Service接口
    private IBpmExecuteNodeMiddleService bpmExecuteNodeMiddleService;


    @Autowired
    private Sending sending;

    /**
     * 查询流程执行任务
     *
     * @param id 流程执行任务主键
     * @return 流程执行任务
     */
    @Override
    public BpmExecuteProcess selectBpmExecuteProcessById(Long id) {
        return runBpmExecuteProcessMapper.selectBpmExecuteProcessById(id);
    }

    /**
     * 查询流程执行任务列表
     *
     * @param bpmExecuteProcess 流程执行任务
     * @return 流程执行任务
     */
    @Override
    public List<CommonEntity> selectBpmExecuteProcessList(BpmExecuteProcess bpmExecuteProcess) throws Exception {
        // 得到当前执行管道的列表关联信息
        Map<String, Object> params = new HashMap<>();
        params.put("isEnablePaging", "false");  // 不弃启用分页
        params.put("dictType", "plan_execution_data"); // 排需要的必要参数
        ResponseEntity tenantDict = sending.sendGetTenantDict(params);
        if (tenantDict.getStatusCodeValue() == 200) {
            Map<String, Object> tenantRetMap = (Map<String, Object>) JSON.parse(tenantDict.getBody().toString());
            List<Map<String, Object>> tenantRetList = (List<Map<String, Object>>) tenantRetMap.get("rows");
            Map<String, Object> objectMap = new HashMap<>();  // 查询执行管道的参数
            tenantRetList.forEach(item -> {
                objectMap.put(item.get("dictLabel").toString(), item.get("dictValue"));
            });
            List<SysRole> sysRoles = SecurityUtils.getLoginUser().getUser().getRoles();
            List<String> roles = new ArrayList<>();
            if (sysRoles.size() != 0) {
                roles.addAll(sysRoles.stream().map(SysRole::getRoleKey).collect(Collectors.toList()));
            }
            // 根据当前的用户id得到可以执行的流程节点
            objectMap.put("userId", SecurityUtils.getUserId());
            // 得到当前发起请求的用户角色列表
            objectMap.put("taskRealRoleList", roles);
            objectMap.putAll(convertEntityToMap(bpmExecuteProcess));
            // 首先根据当前登陆用户得到他可以执行的所有节点
            List<CommonEntity> commonEntities = runBpmExecuteProcessMapper.queryExecuteProcess(objectMap);
            // 查询异常脚本信息
            return bpmExecuteNodeMiddleService.addExceptionScript(commonEntities);
        }
        return null;
    }

    /**
     * 新增流程执行任务
     *
     * @param bpmExecuteProcess 流程执行任务
     * @return 结果
     */
    @Override
    public int insertBpmExecuteProcess(BpmExecuteProcess bpmExecuteProcess) {
        return runBpmExecuteProcessMapper.insertBpmExecuteProcess(bpmExecuteProcess);
    }

    /**
     * 修改流程执行任务
     *
     * @param bpmExecuteProcess 流程执行任务
     * @return 结果
     */
    @Override
    public int updateBpmExecuteProcess(BpmExecuteProcess bpmExecuteProcess) {
        return runBpmExecuteProcessMapper.updateBpmExecuteProcess(bpmExecuteProcess);
    }

    /**
     * 批量删除流程执行任务
     *
     * @param ids 需要删除的流程执行任务主键
     * @return 结果
     */
    @Override
    public int deleteBpmExecuteProcessByIds(Long[] ids) {
        return runBpmExecuteProcessMapper.deleteBpmExecuteProcessByIds(ids);
    }

    /**
     * 删除流程执行任务信息
     *
     * @param id 流程执行任务主键
     * @return 结果
     */
    @Override
    public int deleteBpmExecuteProcessById(Long id) {
        return runBpmExecuteProcessMapper.deleteBpmExecuteProcessById(id);
    }

    /**
     * 共通投产流程接口
     *
     * @param commonEntity 共通实体 ->预执行流程任务实体
     * @return
     */
    @Override
    public AjaxResult productionScheduling(CommonEntity commonEntity) {
        // 得到流程key 和 投产数据条的id  （做关联查询）
        // intoProduction.getTaskProcessKey();
        return AjaxResult.success(ipreExecutionToolClass.ReadyToExecute(commonEntity));
    }

    /**
     * 根据FormId查询表单结构信息
     *
     * @param fid
     * @return
     */
    @Override
    public String getFromInfo(String fid) {
        Map<String, String> fromInfo = runBpmExecuteProcessMapper.getFromInfo(fid);
        return JSONObject.toJSONString(fromInfo);
    }


    /**
     * 根据groupKey查询表格组对应的表格信息
     *
     * @param groupKey
     * @return
     */
    @Override
    public String getGroupTableInfo(String groupKey) {
        //存tableInfo信息的Arraylist数组
        List<HashMap> mapList = new ArrayList<>();
        //查询表格组信息
        Map<String, String> groupInfo = runBpmExecuteProcessMapper.getGroupInfo(groupKey);
        //拿到表格组的TableInfo信息
        String groupTableInfo = groupInfo.get("groupTableInfo");
        //json字符传转数组
        JSONArray jsonArray = JSON.parseArray(groupTableInfo);
        //循环表格组里的tableInfo信息
        jsonArray.forEach(item -> {
            JSONObject jsonObject = JSONObject.parseObject(item.toString());
            HashMap hashMap = new HashMap();
            jsonObject.forEach((k, v) -> {
                hashMap.put(k, v);
            });
            String tableKey = jsonObject.get("tableKey").toString();
            //根据TableKey查询tableInfo
            Map<String, String> tableInfo = runBpmExecuteProcessMapper.getTableInfo(tableKey);
            //根据tableInfo信息拿到sqlKey信息
            String sqlKey = tableInfo.get("sqlKey");
            //根据sqlKey查询tableSQL信息
            Map<String, String> tableSqlInfo = runBpmExecuteProcessMapper.getTableSqlInfo(sqlKey);
            String tableSql = tableSqlInfo.get("tableSql").toString();
            String tableCondition = tableSqlInfo.get("tableCondition").toString();
            //拿到动态表格编号
            String tId = String.valueOf(tableInfo.get("tId"));
            List<Map<String, String>> tableConditionMap = runBpmExecuteProcessMapper.getTableCondition(tId);
            List<String> tableConditionList = new ArrayList<>();
            tableConditionMap.forEach(e -> {
                System.out.println(e);
                tableConditionList.add(e.get("conditionDefaultValue"));
            });
            //根据动态表格编号查询这个表格的条件信息
            //tableInfo转JSON
            hashMap.put("tableInfo", JSONObject.toJSONString(tableInfo));
            hashMap.put("tableSql", tableSql + " where " + tableCondition);
            hashMap.put("condition", JSONObject.toJSONString(tableConditionList));
            //添加到集合里
            mapList.add(hashMap);
        });
        return JSONObject.toJSONString(mapList);
    }

    // 将实体对象转换为Map的方法
    public static Map<String, Object> convertEntityToMap(Object entity) {
        Map<String, Object> map = new HashMap<>();

        // 获取实体对象的所有字段
        Field[] fields = entity.getClass().getDeclaredFields();

        // 遍历字段并将字段名和对应的值放入Map中
        for (Field field : fields) {
            try {
                field.setAccessible(true); // 设置字段为可访问
                Object value = field.get(entity);
                map.put(field.getName(), value);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        return map;
    }


}























