package cn.fateverse.query.service;

import cn.fateverse.admin.dto.MenuDto;
import cn.fateverse.admin.dubbo.DubboMenuService;
import cn.fateverse.common.core.enums.MenuEnum;
import cn.fateverse.common.core.enums.ResultEnum;
import cn.fateverse.common.core.enums.StateEnum;
import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.common.core.result.Result;
import cn.fateverse.common.core.result.page.TableDataInfo;
import cn.fateverse.common.decrypt.service.EncryptService;
import cn.fateverse.query.entity.UniColumn;
import cn.fateverse.query.entity.UniCon;
import cn.fateverse.query.entity.UniQuery;
import cn.fateverse.query.entity.dto.UniConDto;
import cn.fateverse.query.entity.vo.CustomQueryResult;
import cn.fateverse.query.entity.vo.UniConVo;
import cn.fateverse.query.mapper.UniColumnMapper;
import cn.fateverse.query.mapper.UniConMapper;
import cn.fateverse.query.mapper.UniQueryMapper;
import cn.fateverse.query.service.impl.SqlSearchServiceImpl;
//import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 搜索服务基类
 *
 * @author Clay
 * @date 2023-08-10
 */
public class SearchService {

    //加密服务
    private final EncryptService encryptService;
    //dubbo 新增菜单
    @DubboReference
    protected DubboMenuService menuService;
    //条件信息
    protected final UniConMapper uniConMapper;
    //查询列
    protected final UniColumnMapper uniColumnMapper;
    //自定义查询实例
    protected final UniQueryMapper uniQueryMapper;
    //动态数据查询
    protected final DynamicDataSearchService dynamicDataSearchService;
    //动态数据源
    protected final DynamicDataSourceTableService dynamicDataSourceTableService;


    public SearchService(EncryptService encryptService,
                         UniConMapper uniConMapper,
                         UniColumnMapper uniColumnMapper,
                         UniQueryMapper uniQueryMapper,
                         DynamicDataSearchService dynamicDataSearchService,
                         DynamicDataSourceTableService dynamicDataSourceTableService) {
        this.encryptService = encryptService;
        this.uniConMapper = uniConMapper;
        this.uniColumnMapper = uniColumnMapper;
        this.uniQueryMapper = uniQueryMapper;
        this.dynamicDataSearchService = dynamicDataSearchService;
        this.dynamicDataSourceTableService = dynamicDataSourceTableService;
    }


    /**
     * 查询数据信息
     *
     * @param list    查询条件列表
     * @param queryId 自定义查询id
     * @return 查询数据结果
     */
    protected TableDataInfo<Map<String, Object>> searchData(List<UniConDto> list, Long queryId) {
        UniQuery query = uniQueryMapper.selectSampleById(queryId);
        if (query.getPublish()) {
            throw new CustomException("当前查询以发布");
        }
        return dynamicDataSearchService.searchData(list, query);
    }

    /**
     * 发布操作
     *
     * @param query      自定义查询对象
     * @param menuId     菜单id
     * @param uniCons    查询条件
     * @param uniColumns 查询列信息
     */
    protected void doPublish(UniQuery query, Long menuId, List<UniCon> uniCons, List<UniColumn> uniColumns) {
        insertMenu(menuId, query);
        //更新查询
        uniQueryMapper.update(query);
        //获取到查询条件信息
        //更新操作
        if (null != uniCons && !uniCons.isEmpty()) {
            uniCons.forEach(uniCon -> uniCon.setUqId(query.getId()));
            uniConMapper.batchDelete(query.getId());
            uniConMapper.batchInsert(uniCons);
        }
        if (null != uniColumns && uniColumns.size() > 0) {
            uniColumns.forEach(uniCon -> uniCon.setQueryId(query.getId()));
            uniColumnMapper.batchDeleteByQueryId(query.getId());
            uniColumnMapper.batchInsert(uniColumns);
        }
    }

    /**
     * 撤销下线
     *
     * @param queryId 自定义查询id
     */
//    @GlobalTransactional
    public void cancel(Long queryId) {
        UniQuery sample = uniQueryMapper.selectSampleById(queryId);
        if (!sample.getPublish()) {
            throw new CustomException("状态异常");
        }
        UniQuery query = new UniQuery();
        query.setId(queryId);
        query.setPublish(false);
        query.setMenuId(0L);
        uniQueryMapper.update(query);
        menuService.removeMenu(sample.getMenuId());
    }

    /**
     * 新增菜单
     *
     * @param parentId 父级菜单id
     * @param query    自定义查询对象
     */
    protected void insertMenu(Long parentId, UniQuery query) {
        //rpc新增菜单信息
        MenuDto menuDto = new MenuDto();
        menuDto.setParentId(parentId);
        menuDto.setMenuName(query.getUqName());
        menuDto.setMenuType(MenuEnum.MENU.getCode());
        menuDto.setOrderNum(0);
        String queryId = encryptService.encrypt(query.getId().toString());
        menuDto.setPath("page/" + parentId + "/" + queryId);
        menuDto.setComponent("custom-query/query-page/index");
        menuDto.setPerms("page:list:" + parentId + ":" + queryId);
        menuDto.setIcon("Message");
        menuDto.setState(StateEnum.NORMAL.getCode());
        Result<Long> result = menuService.insertMenu(menuDto);
        if (!result.getCode().equals(ResultEnum.SUCCESS.code)) {
            throw new CustomException(result.getMsg());
        }
        query.setMenuId(result.getData());
    }

    protected List<UniConVo> syncUniCons(List<UniCon> uniCons, Long queryId) {
        List<UniCon> dataBaseList = uniConMapper.selectByQueryId(queryId);
        if (dataBaseList == null || dataBaseList.isEmpty()) {
            uniConMapper.batchInsert(uniCons);
            return uniCons.stream().map(UniCon::toUcConVo).collect(Collectors.toList());
        } else {
            List<UniCon> updateList = new ArrayList<>();
            List<UniCon> insertList = new ArrayList<>();
            List<Long> removeIds = new ArrayList<>();
            Map<Long, UniCon> dataBaseMap = dataBaseList.stream().collect(Collectors.toMap(UniCon::getUcId, Function.identity()));
            Set<Long> dataBaseSet = dataBaseMap.keySet();
            for (UniCon uniCon : uniCons) {
                if (uniCon.getUcId() != null && dataBaseSet.contains(uniCon.getUcId())) {
                    updateList.add(uniCon);
                    dataBaseSet.remove(uniCon.getUcId());
                } else {
                    insertList.add(uniCon);
                }
            }
            if (!dataBaseSet.isEmpty()) {
                removeIds.addAll(dataBaseSet);
            }
            if (!updateList.isEmpty()) {
                uniConMapper.batchUpdate(updateList);
            }
            if (!insertList.isEmpty()) {
                insertList.forEach(item -> item.setUqId(queryId));
                uniConMapper.batchInsert(insertList);
            }
            if (!removeIds.isEmpty()) {
                uniConMapper.batchRemove(removeIds);
            }
            updateList.addAll(insertList);
            return updateList.stream().map(UniCon::toUcConVo).collect(Collectors.toList());
        }
    }


    protected void syncUniColumns(List<UniColumn> uniColumns, Long queryId) {
        List<UniColumn> dataBaseList = uniColumnMapper.selectByQueryId(queryId);
        if (dataBaseList == null || dataBaseList.isEmpty()) {
            uniColumnMapper.batchInsert(uniColumns);
        } else {
            List<UniColumn> updateList = new ArrayList<>();
            List<UniColumn> insertList = new ArrayList<>();
            List<Long> removeIds = new ArrayList<>();
            Map<Long, UniColumn> dataBaseMap = dataBaseList.stream().collect(Collectors.toMap(UniColumn::getId, Function.identity()));
            Set<Long> dataBaseSet = dataBaseMap.keySet();
            for (UniColumn column : uniColumns) {
                if (column.getId() != null && dataBaseSet.contains(column.getId())) {
                    updateList.add(column);
                    dataBaseSet.remove(column.getId());
                } else {
                    insertList.add(column);
                }
            }
            if (!dataBaseSet.isEmpty()) {
                removeIds.addAll(dataBaseSet);
            }
            if (!updateList.isEmpty()) {
                uniColumnMapper.batchUpdate(updateList);
            }
            if (!insertList.isEmpty()) {
                insertList.forEach(item -> item.setQueryId(queryId));
                uniColumnMapper.batchInsert(insertList);
            }
            if (!removeIds.isEmpty()) {
                uniColumnMapper.batchRemove(removeIds);
            }
        }
    }

    protected Result<CustomQueryResult> previewCustomQueryResult(List<UniCon> uniCons, List<UniColumn> uniColumns, UniQuery query, TableDataInfo<Map<String, Object>> mapTableDataInfo) {
        uniQueryMapper.update(query);
        //获取到查询条件信息
        //查询条件返回对象
        List<UniConVo> uniConVos = new ArrayList<>();
        //更新操作
        if (null != uniCons && !uniCons.isEmpty()) {
            uniConVos = syncUniCons(uniCons, query.getId());
        }
        if (null != uniColumns && !uniColumns.isEmpty() && this instanceof SqlSearchServiceImpl) {
            syncUniColumns(uniColumns, query.getId());
        }
        //制作返回信息对象
        CustomQueryResult result = CustomQueryResult.builder()
                .table(mapTableDataInfo)
                .uniColumns(uniColumns)
                .uniCons(uniConVos)
                .build();
        return Result.ok(result);
    }


}
