package com.qiuguo.iot.third.service;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiuguo.iot.third.nlp.INlp;
import com.qiuguo.iot.third.nlp.Nlp;
import com.qiuguo.iot.third.nlp.NlpKey;

import com.qiuguo.iot.third.nlp.lac.LacRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
 * <p>
 * </p>*百度LAC分词器
 * https://www.paddlepaddle.org.cn/hubdetail?name=lac&en_category=LexicalAnalysis
 * @author wulin
 * @since 2023-09-06
 */
//LAC中的tag说明 v：动词 n：名称 PER/nr：人名 a：量词 w：标点符号 m：数字（中文、阿拉伯） TIME：时间词 vn：动名词组 xc：语气词 c：连接词
@Service
@Slf4j
public class LacNlpService implements INlp {
    private static WebClient webClient = WebClient.builder()
            .defaultHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_VALUE).build();
    //免得注入没有相关配置报错
//    @Value("${lac.url}")
//    private String url;

    private Mono<JSONObject> getNlpFromLac(LacRequest request){

        return webClient.post().uri(SpringUtil.getProperty("lac.url") + "/predict/lac").bodyValue(JSONObject.toJSON(request))
                .retrieve()
                .bodyToMono(JSONObject.class).doOnNext(res -> {
                    if (!Objects.equals(res.getInteger("status"), 0)) {
                        throw new RuntimeException(res.getString("info"));
                    }
                    //log.info("", res);
                    //log.info("res{}", res.toString());
                });
    }

    @Override
    public Mono<Nlp> geSingletNlp(String value) {

        List<String> text = new ArrayList<>();
        text.add(value);
        LacRequest request = new LacRequest();
        request.setText(text);
        Mono<JSONObject> mono = getNlpFromLac(request);
        Mono<Nlp> nlpKeyMono = mono.map(jsonObject -> {
            JSONArray jsonArray = jsonObject.getJSONArray("results");
            Nlp nlp = new Nlp();
            JSONObject o = jsonArray.getJSONObject(0);
            nlp.setKeys(getKeys(o));
            //nlp.getKeys().sort(Comparator.comparing(NlpKey::getType));
            return nlp;
        });
        return nlpKeyMono;
    }

    @Override
    public Mono<List<Nlp>> getNlp(List<String> values) {
        LacRequest request = new LacRequest();
        request.setText(values);
        Mono<JSONObject> mono = getNlpFromLac(request);
        Mono<List<Nlp>> nlpKeyFlux = mono.map(jsonObject -> {
            JSONArray jsonArray = jsonObject.getJSONArray("results");
            List<Nlp> nlps = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++
            ) {
                Nlp nlp = new Nlp();
                JSONObject o = jsonArray.getJSONObject(i);
                nlp.setKeys(getKeys(o));
                nlps.add(nlp);
            }
            return nlps;
        });
        return nlpKeyFlux;
    }

    private List<NlpKey> getKeys(JSONObject jsonObject){
        List<NlpKey> nlpModels = new ArrayList<>();
        List<String> tagName = jsonObject.getJSONArray("tag").toJavaList(String.class);
        List<String> keys = jsonObject.getJSONArray("word").toJavaList(String.class);
        for (int j = 0; j < keys.size(); j++){
            NlpKey key = new NlpKey();
            key.setTagName(tagName.get(j));
            key.setKey(keys.get(j));
            nlpModels.add(key);
        }
        return nlpModels;
    }
}
