package com.keyware.shandan.browser;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.entity.SysOperateLog;
import com.keyware.shandan.system.service.SysOperateLogService;
import com.keyware.shandan.system.utils.DictUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用于处理分析系统热词和用户搜索历史
 */
@Slf4j
@Component
public class SearchLogProcessor extends Thread {
    private final SysOperateLogService logService;
    private int cycle = 7;
    private DateField unit = DateField.DAY_OF_MONTH;
    private final Map<String, Integer> systemWords = new HashMap<>();

    private final Map<String, Map<String, Integer>> userHistoryWords = new HashMap<>();

    public SearchLogProcessor(SysOperateLogService logService) {
        this.logService = logService;
    }

    @Override
    public void run() {
        log.info("搜索日志处理程序启动成功");
        while (true) {
            parseConfig();
            systemWords.clear();
            LambdaQueryWrapper<SysOperateLog> query = new LambdaQueryWrapper<>();
            DateTime date = DateUtil.offset(new Date(), unit, cycle);
            query.gt(SysOperateLog::getOperateTime, date.toJdkDate());
            logService.list(query).forEach(logs -> {
                String word = parseLogs(logs);
                if (StringUtils.hasText(word)) {
                    addSystemWords(word);
                }
            });
            try {
                Thread.sleep(1000 * 60 * 30);
            } catch (InterruptedException ignore) {
            }
        }
    }

    /**
     * 获取用户的搜索历史
     *
     * @param loginName
     * @return
     */
    public List<String> getUserSearchHistory(String loginName) {
        List<String> searchHistory = new ArrayList<>();
        LambdaQueryWrapper<SysOperateLog> query = new LambdaQueryWrapper<>();
        query.eq(SysOperateLog::getLoginName, loginName).orderByDesc(SysOperateLog::getOperateTime).last("limit 30");
        for (SysOperateLog logs : logService.list(query)) {
            String word = parseLogs(logs);
            if (StringUtils.hasText(word) && !searchHistory.contains(word)) {
                searchHistory.add(word);
            }
        }
        return searchHistory;
    }

    /**
     * 获取系统级热词
     *
     * @return
     */
    public List<String> getSystemWords() {
        return systemWords
                .entrySet()
                .stream()
                //.sorted(Comparator.comparingInt(Map.Entry::getValue))
                .sorted((a, b) -> b.getValue() - a.getValue())
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }


    private String parseLogs(SysOperateLog logs) {
        String value = null;
        String url = logs.getUrl();
        if (url.startsWith("/browser/search/")) {
            String paramsText = logs.getParams();
            if (JSONUtil.isJsonArray(logs.getParams())) {
                for (Object object : JSONArray.parseArray(paramsText)) {
                    JSONObject json = (JSONObject) object;
                    String fieldName = json.getString("fieldName");
                    if ("metadataName".equals(fieldName)) {
                        value = json.getString("fieldValue");
                        break;
                    }
                }
            } else {
                JSONObject json = JSONObject.parseObject(paramsText);
                if (json.containsKey("search")) {
                    value = json.getString("search");
                }
            }

        }
        return value;
    }

    private void addSystemWords(String word) {
        Integer count = systemWords.get(word);
        count = count == null ? 0 : count;
        systemWords.put(word, ++count);
    }

    private void parseConfig() {
        String systemWordsConfig = DictUtil.getPublicDict("browser_system_words_config");
        if (StringUtils.hasText(systemWordsConfig)) {
            systemWordsConfig = systemWordsConfig.toLowerCase();
            if (systemWordsConfig.endsWith("d")) {
                cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("d", "")));
                unit = DateField.DAY_OF_YEAR;
            } else if (systemWordsConfig.endsWith("m")) {
                cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("m", "")));
                unit = DateField.MONTH;
            } else if (systemWordsConfig.endsWith("y")) {
                cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("y", "")));
                unit = DateField.YEAR;
            }
        }
    }
}
