package com.pjilisense.flxai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.pjilisense.flxai.base.service.impl.CrudServiceImpl;
import com.pjilisense.flxai.dao.ChunksDao;
import com.pjilisense.flxai.dto.ChunksDTO;
import com.pjilisense.flxai.entity.ChunksEntity;
import com.pjilisense.flxai.service.ChunksService;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * ${comments}
 *
 * @author liushujing liushujing@philisense.com
 * @since 1.0.0 2025-02-10
 */
@Service
public class ChunksServiceImpl extends CrudServiceImpl<ChunksDao, ChunksEntity, ChunksDTO> implements ChunksService {

    @Override
    public QueryWrapper<ChunksEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");

        QueryWrapper<ChunksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StrUtil.isNotBlank(id), "id", id);

        return wrapper;
    }


    @Override
    public List<Map<String, Object>> search(String userid,String keyText) {
        return search2( userid, keyText);
    }

    private List<Map<String, Object>> search1(String userid,String keyText) {
        Segment seg= HanLP.newSegment();
        seg.enableCustomDictionary(false);
        List<Term> lst = seg.seg(keyText);
        ArrayList<String> listWord=processTermList(lst);
        //ArrayList<String> listSentence=processTermListx(lst);
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.addAll(listWord);
        //set.addAll(listSentence);
        listWord.clear();
        //listSentence.clear();
        ArrayList<String> wordList=processTermList(lst);
        wordList.addAll(set);
        set.clear();
        HashMap<String,Object> map = new HashMap<>();
        map.put("userid",userid);
        map.put("wordList",wordList);
        List<Map<String,Object>> list = baseDao.queryCsv(map);
        List<Map<String,Object>> listRet = new ArrayList<>() ;
        if(list!=null && list.size()>0) {
            ArrayList<String> listText=processTermListN0Com(lst);
            List<String> idList = new ArrayList<>();
            for (Map<String, Object> mp: list){
                String ttext = String.valueOf(mp.get("text"));
                int pos = ttext.indexOf(',');
                String question = ttext.substring(0,pos);
                String answer = ttext.substring(pos+1);
                mp.put("question",question);
                mp.put("answer",answer);
                List<Term> lst2 = seg.seg(question);
                ArrayList<String> listQuestion=processTermListN0Com(lst2);
                double similarity =calculateSimilarity(listText, listQuestion);
                BigDecimal bd = new BigDecimal(similarity);
                if(bd.compareTo(BigDecimal.ZERO.stripTrailingZeros())==0){
                    idList.add(String.valueOf(mp.get("id")));
                } else {
                    System.out.println(bd.toString());
                    mp.put("similarity",bd.toString());
                }
            }
            for(Map<String, Object> mp: list){
                String id=String.valueOf(mp.get("id"));
                if(!idList.contains(id)){
                    listRet.add(mp);
                }
            }
            list.clear();
            list.addAll(listRet);
            Collections.sort(list, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    BigDecimal bd1 = new BigDecimal(String.valueOf(o1.get("similarity")));
                    BigDecimal bd2 = new BigDecimal(String.valueOf(o2.get("similarity")));
                    return bd1.compareTo(bd2)*(-1);
                }
            });
        }
        return list;
    }
    private List<Map<String, Object>> search2(String userid,String keyText) {
        Segment seg= HanLP.newSegment();
        seg.enableCustomDictionary(false);
        List<Term> lst = seg.seg(keyText);
        ArrayList<String> listWord=processTermList(lst);
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.addAll(listWord);
        listWord.clear();
        ArrayList<String> wordList=processTermList(lst);
        wordList.addAll(set);
        set.clear();
        HashMap<String,Object> map = new HashMap<>();
        map.put("userid",userid);
        map.put("wordList",wordList);
        List<Map<String,Object>> list = baseDao.queryCsv(map);
        List<Map<String,Object>> listRet = new ArrayList<>() ;
        if(list!=null && list.size()>0) {
            ArrayList<String> listText=processTermListN0Com(lst);
            List<String> idList = new ArrayList<>();
            for (Map<String, Object> mp: list){
                String ttext = String.valueOf(mp.get("text"));
                List<Term> lst2 = seg.seg(ttext);
                ArrayList<String> listQuestion=processTermListN0Com(lst2);
                double similarity =calculateSimilarity(listText, listQuestion);
                BigDecimal bd = new BigDecimal(similarity);
                if(bd.compareTo(BigDecimal.ZERO.stripTrailingZeros())==0){
                    idList.add(String.valueOf(mp.get("id")));
                } else {
                    System.out.println(bd.toString());
                    mp.put("similarity",bd.toString());
                }
            }
            for(Map<String, Object> mp: list){
                String id=String.valueOf(mp.get("id"));
                if(!idList.contains(id)){
                    listRet.add(mp);
                }
            }
            list.clear();
            list.addAll(listRet);
            Collections.sort(list, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    BigDecimal bd1 = new BigDecimal(String.valueOf(o1.get("similarity")));
                    BigDecimal bd2 = new BigDecimal(String.valueOf(o2.get("similarity")));
                    return bd1.compareTo(bd2)*(-1);
                }
            });
        }
        return list;
    }

    private static ArrayList<String> processTermList(List<Term> lst) {
        ArrayList<String> ret = new ArrayList<>();
        StringBuilder sd = new StringBuilder();
        for(int i=0;i<lst.size();i++) {
            Term term = lst.get(i);
            if(term.nature.startsWith('w')) {
                if(sd.length()>0) {
                    ret.add(sd.toString());
                    sd = sd.delete(0,sd.length());
                }
                continue;
            }else {
                String word = term.word;
                if(word.length()==1) {
                    sd.append(word);
                    if(i+1< lst.size()) {
                        Term termx = lst.get(i+1);
                        if(!termx.nature.startsWith('w')) {
                            String wordx = termx.word;
                            sd.append(wordx);
                            if(wordx.length()>1) {
                                ret.add(sd.toString());
                                sd = sd.delete(0,sd.length());
                            }
                            i++;
                        }
                    }
                } else {
                    sd.append(word);
                    ret.add(sd.toString());
                    sd = sd.delete(0,sd.length());
                }
            }

        }
//        System.out.println("ret=");
//        for(String term : ret) {
//            System.out.println(term);
//        }
        return ret;
    }

    private static ArrayList<String> processTermListN0Com(List<Term> lst) {
        ArrayList<String> ret = new ArrayList<>();
        StringBuilder sd = new StringBuilder();
        for(int i=0;i<lst.size();i++) {
            Term term = lst.get(i);
            if(term.nature.startsWith('w')) {
                if(sd.length()>0) {
                    ret.add(sd.toString());
                    sd = sd.delete(0,sd.length());
                }
                continue;
            }else {
                String word = term.word;
                if(word.length()==1) {
                    sd.append(word);
                    if(i+1< lst.size()) {
                        Term termx = lst.get(i+1);
                        if(!termx.nature.startsWith('w')) {
                            String wordx = termx.word;
                            sd.append(wordx);
                            if(wordx.length()>0) {
                                ret.add(sd.toString());
                                sd = sd.delete(0,sd.length());
                            }
                            i++;
                        }
                    }
                } else {
                    sd.append(word);
                    ret.add(sd.toString());
                    sd = sd.delete(0,sd.length());
                }
            }

        }
//        System.out.println("ret=");
//        for(String term : ret) {
//            System.out.println(term);
//        }
        return ret;
    }
    private static ArrayList<String> processTermListx(List<Term> lst) {
        ArrayList<String> ret = new ArrayList<>();
        StringBuilder sd = new StringBuilder();
        for(int i=0;i<lst.size();i++) {
            Term term = lst.get(i);
            if(term.nature.startsWith('w')) {
                if(sd.length()>0) {
                    ret.add(sd.toString());
                    sd = sd.delete(0,sd.length());
                }
                continue;
            }else {
                String word = term.word;
                sd.append(word);
            }
        }
//        System.out.println("ret=");
//        for(String term : ret) {
//            System.out.println(term);
//        }
        return ret;
    }

    // 创建单词频率映射
    private Map<String, Integer> createFrequencyMap(List<String> words) {
        Map<String, Integer> freqMap = new HashMap<>();
        for (String word : words) {
            freqMap.put(word, freqMap.getOrDefault(word, 0) + 1);
        }
        return freqMap;
    }

    // 计算余弦相似度
    private double calculateSimilarity(List<String> words1, List<String> words2) {
//        List<String> words1 = preprocessText(text1);
//        List<String> words2 = preprocessText(text2);

        Map<String, Integer> freqMap1 = createFrequencyMap(words1);
        Map<String, Integer> freqMap2 = createFrequencyMap(words2);

        double dotProduct = 0.0;
        double magnitude1 = 0.0;
        double magnitude2 = 0.0;

        for (String word : freqMap1.keySet()) {
            int freq1 = freqMap1.get(word);
            magnitude1 += freq1 * freq1;
            if (freqMap2.containsKey(word)) {
                int freq2 = freqMap2.get(word);
                dotProduct += freq1 * freq2;
            }
        }

        for (int freq : freqMap2.values()) {
            magnitude2 += freq * freq;
        }

        return dotProduct / (Math.sqrt(magnitude1) * Math.sqrt(magnitude2));
    }
}