package com.weaver.seconddev.chapanda.prop.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.weaver.ebuilder.datasource.api.entity.ExecuteSqlEntity;
import com.weaver.ebuilder.datasource.api.entity.SqlParamEntity;
import com.weaver.ebuilder.datasource.api.enums.SourceType;
import com.weaver.ebuilder.datasource.api.enums.SqlParamType;
import com.weaver.ebuilder.datasource.api.query.dto.dw.DynamicParamDto;
import com.weaver.ebuilder.datasource.api.query.dto.dw.FieldQuery;
import com.weaver.ebuilder.datasource.api.query.dto.dw.GroupQuery;
import com.weaver.ebuilder.datasource.api.query.dto.dw.TableQuery;
import com.weaver.ebuilder.datasource.api.service.DataSetService;
import com.weaver.ebuilder.datasource.api.service.impl.EbFormDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * DatabaseUtil 是一个数据库工具类，提供了一些执行 SQL 查询和操作的方法。
 */


@Component
public class DatabaseUtils {

    private final static Logger log = LoggerFactory.getLogger(DatabaseUtils.class);

    @Autowired
    private DataSetService dataSetService;

    @Autowired
    private EbFormDataService dataService;


    /**
     * 执行 SQL 并返回结果。
     *
     * @param entity 包含执行 SQL 的相关信息的对象
     * @return 包含查询结果的 Map 对象
     * @throws RuntimeException 当 SQL 执行失败时抛出异常
     */
    public Map<String, Object> executeSql(ExecuteSqlEntity entity) {
        Map<String, Object> map = dataSetService.executeSql(entity);
        if ("FAIL".equals(CommonUtils.null2String(map.get("status")).toUpperCase(Locale.ROOT))) {
            log.error("sql执行失败=>{}", JSONObject.toJSONString(map));
            throw new RuntimeException("sql执行异常");
        } else {
            return map;
        }
    }

    /**
     * 执行分页 SQL 查询并返回结果。
     *
     * @param entity   包含执行 SQL 和分页信息的对象
     * @param pageNo   当前页码
     * @param pageSize 每页的数据条数
     * @return 包含查询结果的 Map 对象
     * @throws RuntimeException 当 SQL 执行失败时抛出异常
     */
    public Map<String, Object> executeSql(ExecuteSqlEntity entity, int pageNo, int pageSize) {
        entity.setPageNo(pageNo);
        entity.setPageSize(pageSize);
        Map<String, Object> map = dataSetService.executeForQuery(entity);
        if ("FAIL".equals(CommonUtils.null2String(map.get("status")).toUpperCase(Locale.ROOT))) {
            log.error("sql执行失败=>{}", JSONObject.toJSONString(map));
            throw new RuntimeException("sql执行异常");
        } else {
            return map;
        }
    }

    /**
     * 创建一个包含执行 SQL 的对象。
     *
     * @param sql     需要执行的 SQL
     * @param groupId 数据源分组的 ID
     * @paramDesc 数据源分组的 ID 获取方式 【select APPLICATION_MARK,APPLICATION_name from eteams.ds_mark_service_relation】
     * @return 包含执行 SQL 的对象
     */
    public ExecuteSqlEntity getExecuteSqlEntity(String sql, String groupId) {
        log.error("sql=>{}", sql);
        ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
        executeSqlEntity.setSql(base64(sql));
        executeSqlEntity.setGroupId(groupId);
        executeSqlEntity.setSourceType(SourceType.LOGIC);
        executeSqlEntity.setGroupKey("0");
        return executeSqlEntity;
    }

    /**
     * 对 SQL 进行 Base64 编码。
     *
     * @param sql 需要进行编码的 SQL
     * @return 编码后的字符串
     */
    public String base64(String sql) {
        return Base64.encode(sql);
    }

    /**
     * 获取数据源列表。
     *
     * @param map 包含数据源列表信息的 Map 对象
     * @return 数据源列表的 Map 对象
     */
    public List<Map<String, Object>> getDataSourceList(Map<String, Object> map) {
        List<Map<String, Object>> entity = new ArrayList();
        if ("OK".equals(CommonUtils.null2String(map.get("status")).toUpperCase(Locale.ROOT)) && map.get("count") != null && CommonUtils.getIntValue(map.get("count")) > 0) {
            entity = (List) map.get("records");
        }

        return keyToLowerCase((List) entity);
    }

    public Map<String, Object> getOneDataSource(Map<String, Object> map) {
        List<Map<String, Object>> entity = getDataSourceList(map);
        return (Map)(CollectionUtil.isNotEmpty(entity) ? (Map)entity.get(0) : new HashMap());
    }

    /**
     * 将 Map 对象中的键转换为小写。
     *
     * @param orgMapList 需要转换键的 Map 对象列表
     * @return 转换后的 Map 对象列表
     */
    public List<Map<String, Object>> keyToLowerCase(List<Map<String, Object>> orgMapList) {
        List<Map<String, Object>> resultList = new ArrayList();
        Iterator var2 = orgMapList.iterator();

        while (var2.hasNext()) {
            Map<String, Object> stringObjectMap = (Map) var2.next();
            resultList.add(keyToLowerCase(stringObjectMap));
        }

        return resultList;
    }

    /**
     * 将 Map 对象中的键转换为小写。
     *
     * @param orgMap 需要转换键的 Map 对象
     * @return 转换后的 Map 对象
     */
    public Map<String, Object> keyToLowerCase(Map<String, Object> orgMap) {
        Map<String, Object> resultMap = new HashMap();
        if (orgMap != null && !orgMap.isEmpty()) {
            Set<Map.Entry<String, Object>> entrySet = orgMap.entrySet();
            Iterator var3 = entrySet.iterator();

            while (var3.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry) var3.next();
                String key = (String) entry.getKey();
                Object value = entry.getValue();
                resultMap.put(key.toLowerCase(), value);
            }
            return resultMap;
        } else {
            return resultMap;
        }
    }


    /**
     * 根据数据库类型 找到对应数据库
     *
     * @param sourceType sourceType 枚举类
     *                   ETEAMS  :数据仓库
     *                   FORM: ebuilder表单
     *                   LOGIC: 各模块提供业务数据(逻辑表)
     *                   EXTERNAL： 外部数据源
     * @return
     */
    public List<Map<String, Object>> getDataGroups(String sourceType, Boolean flag) {
        GroupQuery query = new GroupQuery();
        query.setSourceType(SourceType.valueOf(sourceType));
        query.setShowSqlDataset(flag);


        DynamicParamDto dynamicParamDto = new DynamicParamDto();
        dynamicParamDto.setUserId(10000L);
        dynamicParamDto.setTenantKey("tk");

        query.setDynamicParamDto(dynamicParamDto);

        return dataSetService.getDataGroups(query);
    }


    /**
     * 获取数据表
     *
     * @param sourceType
     * @param groupId
     * @param pageNum
     * @param pageSize
     * @return
     */
    public Map<String, Object> getDataSets(String sourceType, String groupId, Integer pageNum, Integer pageSize) {

        TableQuery tableQuery = new TableQuery();
        tableQuery.setSourceType(SourceType.valueOf(sourceType));
        tableQuery.setGroupId(groupId);
        //非必传
        //tableQuery.setName(name);
        tableQuery.setPageNo(pageNum);
        tableQuery.setPageSize(pageSize);
        return dataSetService.getDataSetsByPage(tableQuery);
    }

    /**
     * 获取表字段
     * sourceType  :LOGIC
     * sourceId  :  8494845523559165780
     * groupId  :   weaver-crm-service
     *
     * @param
     * @return
     */
    public List<Map<String, Object>> getFields(String sourceType, String sourceId, String groupId) {
        FieldQuery query = new FieldQuery();
        query.setSourceType(SourceType.valueOf(sourceType));
        query.setSourceId(sourceId);
        query.setGroupId(groupId);
        return dataSetService.getFields(query);
    }

    /**
     * 执行sql
     * sourceType  :LOGIC
     * groupId  :   weaver-ebuilder-app-service
     * sql :      select * from ebda_app limit  10
     *
     * @param
     * @return
     */
    public Map<String, Object> execute(String sourceType, String groupId, String sql) {
        //执行sql  参数sourceType   groupId  sql
        ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
        executeSqlEntity.setSql(base64(sql));
        executeSqlEntity.setGroupId(groupId);
        executeSqlEntity.setSourceType(SourceType.valueOf(sourceType));
        return dataSetService.executeSql(executeSqlEntity);
    }


    public Map<String, Object> executeUpdate(String sourceType, String groupId, String sql) {
        //执行sql  参数sourceType   groupId  sql
        ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
        executeSqlEntity.setSql(base64(sql));
        executeSqlEntity.setGroupId(groupId);
        executeSqlEntity.setSourceType(SourceType.valueOf(sourceType));
        return dataSetService.executeForUpdate(executeSqlEntity);
    }


    public Map<String, Object> executeForQuery(String sourceType, String groupId, String sql,List<SqlParamEntity> sqlparam) {
        //执行sql  参数sourceType   groupId  sql sqlparam
        ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
        executeSqlEntity.setSql(base64(sql));
        executeSqlEntity.setGroupId(groupId);
        executeSqlEntity.setSourceType(SourceType.valueOf(sourceType));
        executeSqlEntity.setParams(sqlparam);
        return dataSetService.executeSql(executeSqlEntity);

    }

    /***
     *
     * @param sourceType
     * @param groupId
     * @param sql
     * @param sqlparam
     * @return
     */
    public Map<String, Object> executeForUpdate(String sourceType, String groupId, String sql,List<SqlParamEntity> sqlparam) {
        //执行sql  参数sourceType   groupId  sql sqlparam
        ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
        executeSqlEntity.setSql(base64(sql));
        executeSqlEntity.setGroupId(groupId);
        executeSqlEntity.setSourceType(SourceType.valueOf(sourceType));
        executeSqlEntity.setParams(sqlparam);
        return dataSetService.executeForUpdate(executeSqlEntity);
    }

    /***
     *
     * @param sql
     * @param pageNo
     * @param pageSize
     * @return
     */
    public String getMysqlPagedSql(String sql,int pageNo, int pageSize) {
        if(pageNo<=0){
            pageNo = 1;
        }

        if(pageSize<=0){
            pageSize = 20;
        }

        int start = (pageNo-1)*pageSize;
        int end = pageNo*pageSize;

        return new StringBuffer().append(sql).append(
                " LIMIT "+start+","+(end-start)).toString();
    }

    /**
     * 获取sql入参
     * @param list
     * @return
     */
    public List<SqlParamEntity> querySqlParamEntity(List<String> list){
        List<SqlParamEntity> sqlparam = new ArrayList<SqlParamEntity>();
        for (String str : list){
            SqlParamEntity sqlParamEntity = new SqlParamEntity();
            sqlParamEntity.setParamType(SqlParamType.VARCHAR);
            sqlParamEntity.setValue(str);
            sqlparam.add(sqlParamEntity);
        }
        return sqlparam;
    }

    /***
     *
     * @param sourceType
     * @param groupId
     * @param dataSql
     * @param paramList
     * @return
     */
    public List<Map<String, Object>> getSqlList(String sourceType,String groupId,String dataSql,List<String> paramList){
        List<SqlParamEntity> sqlParamList = querySqlParamEntity(paramList);
        Map<String, Object> result = executeForQuery(sourceType, groupId, dataSql, sqlParamList);
        List<Map<String, Object>> recordList = getDataSourceList(result);
        return recordList;
    }

    /***
     *
     * @param sourceType
     * @param groupId
     * @param dataSql
     * @param paramList
     * @return
     */
    public Map<String, Object> getSqlMap(String sourceType,String groupId,String dataSql,List<String> paramList){
        Map<String, Object> recordMap = new HashMap<String, Object>();
        List<SqlParamEntity> sqlParamList = querySqlParamEntity(paramList);
        Map<String, Object> result = executeForQuery(sourceType, groupId, dataSql, sqlParamList);
        List<Map<String, Object>> recordList = getDataSourceList(result);
        if(recordList.size() > 0){
            recordMap = recordList.get(0);
        }
        return recordMap;
    }



}
