package com.rongwei.bscommon.sys.service.impl;

import com.rongwei.bscommon.sys.dao.KbKnowledgebaseSearchKeywordsDao;
import com.rongwei.bscommon.sys.service.KnowledgeBaseService;
import com.rongwei.bsentity.vo.*;
import com.rongwei.rwcommon.base.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * KnowledgeBaseServiceImpl class
 *
 * @author XH
 * @date 2024/01/11
 */
@Service
public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
    @Autowired
    private KbKnowledgebaseSearchKeywordsDao kbKnowledgebaseSearchKeywordsDao;
    /**
     * 下拉选的类型
     */
    public static final String SELECT = "select";
    public static final String DICT = "dict";
    public static final String SQL = "sql";
    public static final String STR = "%s-;-%s";
    public static final String KB_MODEL_ID = "4149efeef04c4e08972dd5516a2dc16f";
    public static final String EYE_CATCHING = "<span style='color: red;'>%s</span>";

    @Async("customThreadPool")
    public void updateKeyWords(String searchContent) {
        // 是否为空的搜索内容
        boolean emptySearchContent = StringUtils.isBlank(searchContent);
        if (!emptySearchContent) {
            // 增加关键词搜索次数
            kbKnowledgebaseSearchKeywordsDao.insertOrUpdateSearchCount(searchContent);
        }
    }

    @Override
    public R search(KnowledgeBaseSearchVo knowledgeBaseSearchVo) {
        if (knowledgeBaseSearchVo == null) {
            return R.ok();
        }
        // 搜索内容
        String searchContent = knowledgeBaseSearchVo.getSearchContent();
        updateKeyWords(searchContent);
        String systemId = knowledgeBaseSearchVo.getSystemId();

        List<KnowledgeBaseVo> searchBasicInfo = kbKnowledgebaseSearchKeywordsDao.getSearchBasicInfo(systemId);
        // 知识库只需要根据
        if (!KB_MODEL_ID.equals(systemId)) {
            // 找到所有的数据字典
            List<KnowledgeBaseVo> dictSqlList = searchBasicInfo.stream().filter(info -> SELECT.equals(info.getControlType()) && (DICT.equals(info.getEnumType()) || SQL.equals(info.getEnumType()))).collect(Collectors.toList());
            List<KBDictDataVo> selectInfo;
            if(!dictSqlList.isEmpty()){
                selectInfo = kbKnowledgebaseSearchKeywordsDao.getSelectInfo(dictSqlList);
            } else {
                selectInfo = new ArrayList<>();
            }
            // 使用数据字典替换掉searchBasicInfo 的searchValue

            // 设置下拉选的搜索条件
            searchBasicInfo.forEach(info -> {
                if (SELECT.equals(info.getControlType()) && (DICT.equals(info.getEnumType()) || SQL.equals(info.getEnumType()))) {
                    List<KBDictDataVo> collect = selectInfo.stream().filter(data -> (data.getDictKey().equals(String.format(STR, info.getTableName(), info.getColumnName())))).collect(Collectors.toList());
                    List<KBDictDataVo> kbDictDataVoList = collect.stream().filter(dictData -> dictData.getLabel().contains(searchContent)).collect(Collectors.toList());
                    String searchValue = kbDictDataVoList.stream().map(KBDictDataVo::getValue).collect(Collectors.joining(","));
                    info.setSearchValue(StringUtils.isBlank(searchValue) ? "" : searchValue);
                    info.setDictData(collect.stream().collect(Collectors.toMap(KBDictDataVo::getValue, KBDictDataVo::getLabel,(existingValue, newValue) -> existingValue)));
                } else {
                    info.setSearchValue(searchContent);
                }
            });
        }
        List<KBSearchVo> kbSearchVos = new ArrayList<>();
        // 组织查询结果
        searchBasicInfo.stream().collect(Collectors.groupingBy(KnowledgeBaseVo::getPagePartId, Collectors.toList())).forEach((k, v) -> {
            KBSearchVo vo = new KBSearchVo();
            KnowledgeBaseVo knowledgeBaseVo = v.get(0);
            vo.setPagePartId(knowledgeBaseVo.getPagePartId());
            vo.setMenuId(knowledgeBaseVo.getMenuId());
            vo.setMenuName(knowledgeBaseVo.getMenuName());
            vo.setMenuPid(knowledgeBaseVo.getMenuPid());
            vo.setTableName(knowledgeBaseVo.getTableName());
            vo.setTableSql(knowledgeBaseVo.getTablesql());
            vo.setColumnInfoList(v.stream().filter(info -> StringUtils.isNotBlank(info.getSearchValue())).map(data -> {
                KBSearchVo.ColumnInfo columnInfo = new KBSearchVo.ColumnInfo();
                columnInfo.setColumnName(data.getColumnName());
                columnInfo.setColumnDesc(data.getColumnDesc());
                columnInfo.setColumnType(data.getColumnType());
                columnInfo.setSearchValue(data.getSearchValue());
                columnInfo.setDictData(data.getDictData());
                return columnInfo;
            }).collect(Collectors.toList()));
            if (!vo.getColumnInfoList().isEmpty()) {
                kbSearchVos.add(vo);
            }
        });

        int limitPage = knowledgeBaseSearchVo.getPageNum() == 0 ? 0 : (knowledgeBaseSearchVo.getPageNum() - 1) * knowledgeBaseSearchVo.getPageSize();
        if(kbSearchVos.isEmpty()){
            return R.ok(new HashMap<String,Object>(){{
                put("data",new ArrayList<>());
                put("total",0);
            }});
        }
        List<KBResultVo> kbData = kbKnowledgebaseSearchKeywordsDao.getKbData(kbSearchVos, systemId,
                knowledgeBaseSearchVo.getOrderRules(), limitPage, knowledgeBaseSearchVo.getPageSize(),searchContent);
        int length = kbKnowledgebaseSearchKeywordsDao.getKbDataLength(kbSearchVos, systemId,searchContent);
        String format = String.format("<span style='color: red;'>%s</span>", searchContent);
        for (int i = 0; i < kbData.size(); i++) {
            KBResultVo kbResultVo = kbData.get(i);
            kbResultVo.setSearchContentList(kbResultVo.getSearchContentList().stream()
                    .map(info-> info.replaceAll(searchContent,format))
                    .collect(Collectors.toList()));
        }
        return R.ok(new HashMap<String,Object>(){{
            put("data",kbData);
            put("total",length);
        }});
    }
}
