package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.entity.*;
import com.ruoyi.system.entity.vo.DragTableGroupVo;
import com.ruoyi.system.entity.vo.DragTableVo;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IDragTableBtnRelevanceService;
import com.ruoyi.system.service.IDragTableGroupService;
import com.ruoyi.system.service.ITableSqlService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author hmc
 * @date 2023-11-01 14:27
 * @Description:
 */

@Service
public class DragTableGroupServiceImpl implements IDragTableGroupService {

    @Autowired
    private DragTableGroupMapper dragTableGroupMapper;

    @Autowired
    private DragTableMapper dragTableMapper;

    @Autowired
    private DragTableServiceImpl dragTableService;

    @Autowired
    private DragTableConditionMapper dragTableConditionMapper;

    @Autowired
    private TableSqlMapper tableSqlMapper;

    @Autowired
    private IDragTableBtnRelevanceService dragTableBtnRelevanceService;

    @Resource
    private CommonMapper commonMapper;

    @Resource  // 动态sql
    private ITableSqlService iTableSqlService;

    @Resource
    private DragTableBtnRelevanceMapper dragTableBtnRelevanceMapper;

    @Resource
    private DragTableBtnMapper dragTableBtnMapper;

    /**
     * 查询拖拽格组
     *
     * @param id 拖拽格组主键
     * @return 拖拽格组
     */
    @Override
    public DragTableGroup selectDragTableGroupById(Long id)
    {
        return dragTableGroupMapper.selectDragTableGroupById(id);
    }

    /**
     * 查询拖拽格组列表
     *
     * @param dragTableGroup 拖拽格组
     * @return 拖拽格组
     */
    @Override
    public List<DragTableGroup> selectDragTableGroupList(DragTableGroup dragTableGroup)
    {
        return dragTableGroupMapper.selectDragTableGroupList(dragTableGroup);
    }


    /**
     * 新增拖拽格组
     *
     * @param dragTableGroupVo 拖拽格组
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDragTableGroup(DragTableGroupVo dragTableGroupVo)
    {
        //表格组实体类拷贝数据
        DragTableGroup dragTableGroup=new DragTableGroup();
        BeanUtils.copyProperties(dragTableGroupVo,dragTableGroup);
        //添加动态表格列表
        dragTableService.addDragTable(dragTableGroupVo);
        //默认添加的是联动表格
        dragTableGroup.setGroupType("0");
        return dragTableGroupMapper.insertDragTableGroup(dragTableGroup);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDragTableConfigurationGroup(DragTableGroupVo dragTableGroupVo)
    {
        //表格组实体类拷贝数据
        DragTableGroup dragTableGroup=new DragTableGroup();
        BeanUtils.copyProperties(dragTableGroupVo,dragTableGroup);
        //添加动态表格列表
        dragTableService.addDragTable(dragTableGroupVo);
        dragTableGroup.setGroupType("1");
        return dragTableGroupMapper.insertDragTableGroup(dragTableGroup);
    }


    // SQL 条件的开始
    public static final String SQL_START = "CONCAT(";

    // SQL 超级查询常量
    public static final String SQL_MIDDLE = "IFNULL( #{VAL}, '' )";

    // sqlserver || DM 数据类型的超级查询常量
    public static final String SQL_DM_SERVER_MIDDLE = "COALESCE( #{VAL}, '' )";

    // SQL 条件的结束
    public static final String SQL_END = "LIKE '%#{val}%'";

    /**
     * 修改联动表格拖拽格组
     *
     * @param dragTableGroupVo 拖拽格组
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDragTableGroup(DragTableGroupVo dragTableGroupVo) {
        //根据id查询表格组信息
        DragTableGroup dragTableGroupOne = dragTableGroupMapper.selectDragTableGroupById(dragTableGroupVo.getId());
        //得到group_table_info
        String groupTableInfo = dragTableGroupOne.getGroupTableInfo();
        //把他转换成Map对象
        JSONArray jsonArray = JSON.parseArray(groupTableInfo);
        //收集tableKey
        List<String> tableKeys = jsonArray.stream().map(item -> JSONObject.parseObject(item.toString()).get("tableKey").toString()
        ).collect(Collectors.toList());
        //删除条件数据
        List<Long> dragTableIds = dragTableMapper.selectDragTableTableKeys(tableKeys)
                .stream().map(item -> item.gettId()).collect(Collectors.toList());
        dragTableConditionMapper.deleteDragTableConditionBytIds(dragTableIds);
        //删除sql数据
        //Long[] dragTableIds1 = dragTableIds.toArray(new Long[0]);
        //tableSqlMapper.deleteTableSqlByTIds(dragTableIds1);
        //删除表格数据
        //dragTableMapper.deleteDragTableByTableKeys(tableKeys);

        //优化逻辑 1、表格组信息 2、表格信息、条件信息、sql信息
        List<DragTableVo> dragTables = dragTableGroupVo.getDragTables();
        if (dragTables.size()>0) {
            dragTables.stream().forEach(dragTableVo->{
                String SQL="";
                //update drag_table
                DragTable dragTable = new DragTable();
                BeanUtils.copyProperties(dragTableVo, dragTable);
                dragTable.setDtColumnName(dragTableVo.getDtColumnName().toString());
                dragTable.setPrimaryKey(dragTableVo.getPrimaryKey());
                dragTable.setMenuId(dragTableVo.getMenuId());
                dragTable.setDtType("1");
                dragTableMapper.updateDragTable(dragTable);
                //update table_sql
                TableSql tableSql = new TableSql();
                //拼接sql查询条件
                switch (SecurityUtils.getDatabaseType().toUpperCase()) {
                    case "MYSQL":
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += " AND "+dragTableVo.getSearchFieldList().get(i)+"="+dragTableVo.getConditionDefaultValueMap().get(dragTableVo.getSearchFieldList().get(i));
                        }
                        break;
                    case "DM":
                    case "SQLSERVER":
                        SQL += SQL_START;
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += SQL_DM_SERVER_MIDDLE.replace("#{VAL}", dragTableVo.getSearchFieldList().get(i));
                            SQL += dragTableVo.getSearchFieldList().size() - 1 == i ? ",'')" : ",\n";
                        }
                        break;
                    case "ORACLE":
                        //SQL_START = "";
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += dragTableVo.getSearchFieldList().get(i);
                            SQL += (dragTableVo.getSearchFieldList().size() - 1 == i ? " " : "||");
                        }
                        break;
                }
                String where = dragTableVo.getDtTableName() + ".del_flag = '0'";
                tableSql.setTableCondition(where + SQL);
                tableSql.setTableAlias(dragTableVo.getDtTableName());
                tableSql.setOrderByColumn(dragTableVo.getOrderByColumn());
                tableSql.setSortOrder(dragTableVo.getSortOrder());
                tableSql.setSqlKey(dragTableVo.getSqlKey());
                int i = tableSqlMapper.updateTableSqlBySqlKey(tableSql);
                System.out.println(i);
                //add drag_table_condition
                if (dragTableVo.getSearchFieldList().size() > 0) {
                    List<DragTableCondition> dragTableConditionList = new ArrayList<>();
                    dragTableVo.getSearchFieldList().forEach(item -> {
                        dragTableConditionList.add(new DragTableCondition(dragTable.gettId(), item,dragTableVo.getConditionDefaultValueMap().get(item).toString()));
                    });
                    dragTableConditionMapper.insertDragTableConditionByList(dragTableConditionList);
                }
            });
        }
        //修改表格组列表信息
        DragTableGroup dragTableGroup = new DragTableGroup();
        BeanUtils.copyProperties(dragTableGroupVo, dragTableGroup);
        int i = dragTableGroupMapper.updateDragTableGroup(dragTableGroup);
        return i;
    }

    /**
     * 修改表格表单拖拽格组
     *
     * @param dragTableGroupVo 拖拽格组
     * @return 结果
     */
    @Override
    public int editConfigurationGroup(DragTableGroupVo dragTableGroupVo) {
        //根据id查询表格组信息
        DragTableGroup dragTableGroupOne = dragTableGroupMapper.selectDragTableGroupById(dragTableGroupVo.getId());
        //得到group_table_info
        String groupTableInfo = dragTableGroupOne.getGroupTableInfo();
        //把他转换成Map对象
        JSONArray jsonArray = JSON.parseArray(groupTableInfo);
        //收集tableKey
        List<String> tableKeys = jsonArray.stream().map(item -> JSONObject.parseObject(item.toString()).get("tableKey").toString()
        ).collect(Collectors.toList());
        //删除条件数据
        List<Long> dragTableIds = dragTableMapper.selectDragTableTableKeys(tableKeys)
                .stream().map(item -> item.gettId()).collect(Collectors.toList());
        dragTableConditionMapper.deleteDragTableConditionBytIds(dragTableIds);
        //优化逻辑 1、表格组信息 2、表格信息、条件信息、sql信息
        List<DragTableVo> dragTables = dragTableGroupVo.getDragTables();
        if (dragTables.size()>0) {
            dragTables.stream().forEach(dragTableVo->{
                String SQL="";
                //add drag_table
                DragTable dragTable = new DragTable();
                BeanUtils.copyProperties(dragTableVo, dragTable);
                dragTable.setDtColumnName(JSONObject.toJSONString(dragTableVo.getDtColumnName()));
                dragTable.setPrimaryKey(dragTableVo.getPrimaryKey());
                dragTable.setDtName(dragTableVo.getDtTableName());//表格名称
                dragTable.setMenuId(dragTableVo.getMenuId());
                dragTable.setDtType("1");
                //add table_sql
                TableSql tableSql = new TableSql();
                tableSql.setSqlKey(dragTableVo.getSqlKey());
                tableSql.setTableSql(dragTableVo.getTableSql());
                int i1 = dragTableMapper.updateDragTable(dragTable);
                System.out.println(i1);
                //拼接sql查询条件
                switch (SecurityUtils.getDatabaseType().toUpperCase()) {
                    case "MYSQL":
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += " AND "+dragTableVo.getSearchFieldList().get(i)+"="+dragTableVo.getConditionDefaultValueMap().get(dragTableVo.getSearchFieldList().get(i));
                        }
                        break;
                    case "DM":
                    case "SQLSERVER":
                        SQL += SQL_START;
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += SQL_DM_SERVER_MIDDLE.replace("#{VAL}", dragTableVo.getSearchFieldList().get(i));
                            SQL += dragTableVo.getSearchFieldList().size() - 1 == i ? ",'')" : ",\n";
                        }
                        break;
                    case "ORACLE":
                        //SQL_START = "";
                        for (int i = 0; dragTableVo.getSearchFieldList().size() > i; i++) {
                            SQL += dragTableVo.getSearchFieldList().get(i);
                            SQL += (dragTableVo.getSearchFieldList().size() - 1 == i ? " " : "||");
                        }
                        break;
                }
                String where = dragTableVo.getDtTableName() + ".del_flag = '0'";
                tableSql.setTableCondition(where + SQL);
                tableSql.setTableAlias(dragTableVo.getDtTableName());
                tableSql.setSqlKey(dragTableVo.getSqlKey());
                tableSql.setOrderByColumn(dragTableVo.getOrderByColumn());
                tableSql.setSortOrder(dragTableVo.getSortOrder());
                tableSqlMapper.updateTableSqlBySqlKey(tableSql);
                //add drag_table_condition
                if (dragTableVo.getSearchFieldList().size() > 0) {
                    List<DragTableCondition> dragTableConditionList = new ArrayList<>();
                    dragTableVo.getSearchFieldList().forEach(item -> {
                        dragTableConditionList.add(new DragTableCondition(dragTable.gettId(), item,dragTableVo.getConditionDefaultValueMap().get(item).toString()));
                    });
                    dragTableConditionMapper.insertDragTableConditionByList(dragTableConditionList);
                }
                //修改按钮信息
                dragTableBtnRelevanceService.updateDragTableBtnRelevance(dragTableVo);
            });
        }
        //修改表格组列表信息
        DragTableGroup dragTableGroup = new DragTableGroup();
        BeanUtils.copyProperties(dragTableGroupVo, dragTableGroup);
        int i = dragTableGroupMapper.updateDragTableGroup(dragTableGroup);
        return i;
    }

    /**
     * 批量删除拖拽格组
     *
     * @param ids 需要删除的拖拽格组主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteDragTableGroupByIds(Long[] ids)
    {
        //表格数据
        List<String> tableKeys = new ArrayList<>();
        //删除条件数据
        List<Long> dragTableIds =new ArrayList<>();
        for (Long id : ids) {
            //根据id查询表格组信息
            DragTableGroup dragTableGroupOne = dragTableGroupMapper.selectDragTableGroupById(id);
            //得到group_table_info
            String groupTableInfo = dragTableGroupOne.getGroupTableInfo();
            //把他转换成Map对象
            JSONArray jsonArray = JSON.parseArray(groupTableInfo);
            //收集tableKey
            jsonArray.stream().forEach(item->
                    tableKeys.add(JSONObject.parseObject(item.toString()).get("tableKey").toString()));
            //删除条件数据
            dragTableMapper.selectDragTableTableKeys(tableKeys)
                    .stream().forEach(item ->dragTableIds.add(item.gettId()));
        }
        //删除表格数据
        dragTableMapper.deleteDragTableByTableKeys(tableKeys);
        //删除条件数据
        dragTableConditionMapper.deleteDragTableConditionBytIds(dragTableIds);
        //删除sql数据
        Long[] dragTableIds1 = dragTableIds.toArray(new Long[0]);
        tableSqlMapper.deleteTableSqlByTIds(dragTableIds1);
        //删除组数据
        return dragTableGroupMapper.deleteDragTableGroupByIds(ids);
    }


    /**
     * 根据表格组key查询表格组信息
     * @param groupKey
     * @return
     */
    @Override
    public String selectDragTableGroup(String groupKey) {
        String groupTableInfo = dragTableGroupMapper.selectDragTableGroupByGroupKey(groupKey);
        return groupTableInfo;
    }

    /**
     * 查询表格组包含的详细信息
     * @param dragTableGroup
     * @return
     */
    @Override
    public DragTableGroupVo selectDragTableGroupListDetail(DragTableGroup dragTableGroup) {
        //根据id查询表格组信息
        DragTableGroup dragTableGroupOne = dragTableGroupMapper.selectDragTableGroupById(dragTableGroup.getId());
        //得到group_table_info
        String groupTableInfo = dragTableGroupOne.getGroupTableInfo();
        //抽取的方法(处理排序查表格数据)
        List<DragTableVo> dragTableList = getDragTableVos(groupTableInfo);
        //查询这个动态表格的 1.条件 2.sql信息
        dragTableList.stream().map(item -> {
            //拿到这个表格的所有条件数据
            List<DragTableCondition> dragTableConditions = dragTableConditionMapper.selectDragTableConditionByTid(item.gettId());
            //条件
            item.setSearchFieldList(dragTableConditions.stream().map(it->it.getConditionField()).collect(Collectors.toList()));
            //绑定的默认值map
            HashMap<String, Object> conditionDefaultValueMap = new HashMap<>();
            //关联条件
            dragTableConditions.forEach(condition -> {
                if (condition.getConditionDefaultValue() != null && condition.getConditionDefaultValue() != "") {
                    //条件字段：条件值
                    conditionDefaultValueMap.put(condition.getConditionField(), condition.getConditionDefaultValue());
                    item.setConditionDefaultValueMap(conditionDefaultValueMap);
                }
            });
            //排序字段
            TableSql tableSql = tableSqlMapper.selectTableSqlByTSqlKey(item.getSqlKey());
            if(tableSql!=null){
                item.setOrderByColumn(tableSql.getOrderByColumn());
            }
            return item;
        }).collect(Collectors.toList());
        DragTableGroupVo dragTableGroupVo=new DragTableGroupVo();
        BeanUtils.copyProperties(dragTableGroupOne, dragTableGroupVo);
        dragTableGroupVo.setDragTables(dragTableList);
        //查询表格的关联数据
        return    dragTableGroupVo;
    }

    private List<DragTableVo> getDragTableVos(String groupTableInfo) {
        //把他转换成Map对象
        JSONArray jsonArray = JSON.parseArray(groupTableInfo);
        //排序确保表格的顺序
        JSONArray sortArray = jsonArray.stream().sorted(
                Comparator.comparingLong(
                        // 根据对象中的ID进行排序
                        e -> JSONObject.parseObject(e.toString()).getIntValue("sort")
                )
        ).collect(Collectors.toCollection(JSONArray::new));
        //把查询出来的动态表格数据放到一个集合里边
        List<DragTableVo> dragTableList=new ArrayList<>();
        sortArray.forEach(e->{
            JSONObject jsonObject = JSON.parseObject(e.toString());
            String str = jsonObject.get("tableKey").toString();
            DragTable dragTable = dragTableMapper.selectDragTableByTableKey(str);
            DragTableVo dragTableVo=new DragTableVo();
            BeanUtils.copyProperties(dragTable, dragTableVo);
            dragTableList.add( dragTableVo);
        });
        return dragTableList;
    }

    /**
     * 查询当前组下是否包含有表格信息
     */
    @Override
    public Boolean selectDragTableGroupTableListSize(Long[] ids) {
        List<DragTableGroup> dragTableGroups = dragTableGroupMapper.selectDragTableGroupByIdIn(ids);
        List<String> tableKeys=new ArrayList<>();
        //收集这个组下的所有tableKey
        dragTableGroups.stream().forEach(item->{
            JSONArray jsonArray = JSON.parseArray(item.getGroupTableInfo());
            jsonArray.stream().forEach(
                    it ->{
                        tableKeys.add( JSONObject.parseObject(it.toString()).get("tableKey").toString());
                    }
            );
        });
        //判断tableKey在表格表中出现了吗
        List<DragTableVo> dragTableVos = dragTableMapper.selectDragTableTableKeys(tableKeys);
        if(dragTableVos.size()>0){
            return  false;
        }
        return true;
    }

    /**
     * 工艺工序弹窗里边的表格结构信息
     * @param commonEntity
     * @return
     */
    @Override
    public CommonEntity getProcessPopupTableInfo(CommonEntity commonEntity) {
        String groupKey = commonEntity.getQueryMap().get("groupKey").toString();
        //查询组信息
        DragTableGroup dragTableGroup = dragTableGroupMapper.selectDragTableGroupOneByGroupKey(groupKey);
        //把[{"tableKey":"a1","sort":0},{"tableKey":"a2","sort":1}]转换成Map对象
        JSONArray jsonArray = JSON.parseArray( dragTableGroup.getGroupTableInfo());
        //排序确保表格的顺序
        JSONArray sortArray = jsonArray.stream().sorted(
                Comparator.comparingLong(
                        // 根据对象中的ID进行排序
                        e -> JSONObject.parseObject(e.toString()).getIntValue("sort")
                )
        ).collect(Collectors.toCollection(JSONArray::new));
        //用in查询
        List<String> tableKeys = new ArrayList<>();
        sortArray.stream().forEach(item->tableKeys.add(JSONObject.parseObject(item.toString()).get("tableKey").toString()));
        //查询表格信息
        List<DragTableVo> dragTableVos = dragTableMapper.selectDragTableTableKeysOrderby(tableKeys);
        //存条件的数组
        List<String> conditionCollectString=new ArrayList<>();
        //查询表格按钮信息
        dragTableVos.forEach(item->{
            // 动态表格按钮信息
            //根据tableKey获取根节点信息
            List<String> btnKeys = dragTableBtnRelevanceMapper.selectBtnKeyByTableKey(item.getTableKey());
            //获取根节点数据
            if(btnKeys.size() > 0){
                List<DragTableBtn> rootNodes = dragTableBtnMapper.selectDragTableBtnListByBtnKey(btnKeys);
                //查询子节点
                List<Long> ids = rootNodes.stream().map(m -> m.getId()).collect(Collectors.toList());
                if (ids.isEmpty()){
                    item.setDragTableBtnList(rootNodes);
                }else {
                    List<DragTableBtn> childNodes = dragTableBtnMapper.selectChildNodeById(ids);
                    List<DragTableBtn> btnList = rootNodes.stream().peek(
                            root -> root.setChildren(getChildrenList(root, childNodes))
                    ).collect(Collectors.toList());
                    item.setDragTableBtnList(btnList);
                }
            }
            //根据动态表格查询条件信息
            List<DragTableCondition> dragTableConditions = dragTableConditionMapper.selectDragTableConditionByTid(item.gettId());
            //拿到条件
            List<String> conditionCollect= dragTableConditions.stream().map(condition -> condition.getConditionDefaultValue()).collect(Collectors.toList());
            //添加所有集合到大条件中
            conditionCollectString.addAll(conditionCollect);
        });
        //数组集合去重
        List<String>  distinctCondition = conditionCollectString.stream().distinct().collect(Collectors.toList());
        CommonEntity common=new CommonEntity();
        //模版结果Map
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("template",dragTableVos);
        resultMap.put("condition",distinctCondition);
        common.setResultMap(resultMap);
        return  common;
    }

    /**
     * 工艺工序弹窗里边的表格数据信息
     * @param commonEntity
     * @return
     */
    @Override
    public CommonEntity getProcessPopupTableList(CommonEntity commonEntity) {
        //拿到表格组名称
        String groupKey = commonEntity.getQueryMap().get("groupKey").toString();
        //查询表格组信息
        String groupTableInfo = dragTableGroupMapper.selectDragTableGroupByGroupKey(groupKey);
        //查询出来的表信息
        List<DragTableVo> dragTableVos = getDragTableVos(groupTableInfo);
        //根据sqlKey查询TableSql数据
        CommonEntity common=new CommonEntity();
        List<List<CommonEntity>> commonEntityList=new ArrayList<>();
        dragTableVos.forEach(item->{
            TableSql tableSql = iTableSqlService.selectTableSqlByTSqlKey(item.getSqlKey());
            //sql的条件值
            AtomicReference<String> tableSqlTableCondition= new AtomicReference<>(tableSql.getTableCondition());
            //循环替换条件占位的值
            commonEntity.getQueryMap().forEach((k,v)->{
                tableSqlTableCondition.set(tableSqlTableCondition.get().replace(k, "'"+v.toString()+"'"));
            });
            //sql的执行语句
            String sqlString = tableSql.getTableSql() + " where " + tableSqlTableCondition.get();
            List<CommonEntity> commonEntities = commonMapper.queryTableList(sqlString);
            //很多条数据
            commonEntityList.add(commonEntities);
        });
        //结果Map
        HashMap hashMap = new HashMap();
        hashMap.put("result",commonEntityList);
        common.setResultMap(hashMap);
        return common;
    }

    @Override
    public DragTableGroup selectDragTableGroupInfoByGroupKey(String groupKey) {
        return dragTableGroupMapper.selectDragTableGroupInfoByGroupKey(groupKey);
    }


    //得到按钮表格的循环
    private List<DragTableBtn> getChildrenList(DragTableBtn root, List<DragTableBtn> childNodes) {
        List<DragTableBtn> list = childNodes.stream().filter(dragTableBtn ->
                //筛选出下一节点元素
                Objects.equals(dragTableBtn.getBtnParentId(), root.getId())).map(dragTableBtn -> {
            //递归set子节点
            dragTableBtn.setChildren(this.getChildrenList(dragTableBtn, childNodes));
            return dragTableBtn;
        }).collect(Collectors.toList());
        return list;
    }

}
