package com.fs.crm.utils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fs.common.core.domain.R;
import com.fs.common.core.domain.entity.SysDictData;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.DictUtils;
import com.fs.common.utils.date.DateUtil;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.config.ai.AiHostProper;
import com.fs.crm.domain.CrmCustomer;
import com.fs.crm.domain.CrmCustomerAnalyze;
import com.fs.crm.domain.CrmCustomerInfo;
import com.fs.crm.domain.CrmCustomerPropertyTemplate;
import com.fs.crm.dto.CrmCustomerAiAutoTagVo;
import com.fs.crm.mapper.CrmCustomerAnalyzeMapper;
import com.fs.crm.mapper.CrmCustomerMapper;
import com.fs.crm.param.CrmCustomerAiTagParam;
import com.fs.crm.service.ICrmCustomerPropertyTemplateService;
import com.fs.crm.vo.CrmCustomerAiTagVo;
import com.fs.fastgptApi.param.ChatParam;
import com.fs.fastgptApi.service.ChatService;
import com.fs.hisapi.util.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
public class CrmCustomerAiTagUtil {

    //行业字典名称
    private static final String TRADE_TYPE = "trade_type";
    @Value("${crm.customer.ai.key:mygpt-tbQfq4ejR162mGJBCTTDUH9ecP1XCVuUfaOGTipnLjb1hP8x5prg}")
    private String appKey;
    private static final String CRM_AI_REDIS_KEY = "crm:AI:data:processing";

    private static final ObjectMapper mapper = new ObjectMapper();

    private static String APP_KEY;

    // 1. 声明静态变量
    private static RedisTemplate redisTemplate;

    // 2. 注入实例到非静态变量
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplateInstance;
    @PostConstruct
    public void initStatic() {
        APP_KEY = this.appKey;
        redisTemplate = this.redisTemplateInstance;
    }

    public static List<CrmCustomerAiTagVo> getCrmCustomerAiTag(CrmCustomerAiTagParam content) throws JsonProcessingException {
        // 1. 参数校验
        validateParams(content);
        Long customerId = content.getCustomerId();
        Long logId = content.getLogId();
        String tradeType = content.getTradeType();
        List<Map<String, Object>> communication = parseCommunicationJson(content.getJson());

        // 2. 构建请求参数
        Map<String, Object> requestParam = buildRequestParam(customerId, tradeType, communication);

        // 3. 调用AI服务
        R aiResponse = callAiService(requestParam, logId);

        // 4. 解析响应并保存
        List<CrmCustomerAiTagVo> results = parseAiResponse(aiResponse, customerId);

        // 5. 异步保存到Redis,后续调用ai分析其他数据 //暂时只传聊天记录
        saveToRedisAsync(customerId,  requestParam.get("history").toString(),logId);
        return results;
    }
    private static void saveToRedisAsync(Long customerId, String aiResponse, Long logId) {
        // 使用线程池异步保存，避免影响主流程
        CompletableFuture.runAsync(() -> {
            try {
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("customerId", customerId);
                dataMap.put("data", aiResponse);
                dataMap.put("logId", logId);
                dataMap.put("timestamp", System.currentTimeMillis());

                // 存储队列索引
                redisTemplate.opsForList().rightPush(CRM_AI_REDIS_KEY, dataMap);

            } catch (Exception e) {
            }
        });
    }
    private static CrmCustomerAiTagVo buildTagVo(Map<String, String> tag, Long customerId) {
        CrmCustomerAiTagVo vo = new CrmCustomerAiTagVo();
        vo.setCustomerId(customerId);
        vo.setId(tag.get("id"));
        vo.setName(tag.get("name"));
        vo.setValue(tag.get("value"));
        return vo;
    }
    private static List<CrmCustomerAiTagVo> parseAiResponse(R aiResponse, Long customerId) {
        if (aiResponse == null || !Integer.valueOf(200).equals(aiResponse.get("code"))) {
            throw new RuntimeException("AI响应异常: " +
                    (aiResponse != null ? aiResponse.get("msg") : "响应为空"));
        }

        List<Map<String, String>> tagInfos = extractTagInfos(JSONUtil.toJsonStr(aiResponse));
        if (CollectionUtils.isEmpty(tagInfos)) {
            return Collections.emptyList();
        }

        return tagInfos.stream()
                .map(tag -> buildTagVo(tag, customerId))
                .collect(Collectors.toList());
    }
    public static R callAiService(Map<String, Object> requestParam, Long logId) {
        try {
            String requestJson = mapper.writeValueAsString(requestParam);

            ChatParam param = new ChatParam();
            param.setChatId(logId.toString());
            param.setStream(false);
            param.setDetail(true);
            ChatParam.Message message = new ChatParam.Message();
            List<ChatParam.Message> messageList = new ArrayList<ChatParam.Message>();
            message.setContent(requestJson);
            message.setRole("user");
            messageList.add(message);
            param.setMessages(messageList);
            ChatService chatService = SpringUtils.getBean(ChatService.class);
            AiHostProper aiHost = SpringUtils.getBean(AiHostProper.class);

            return chatService.initiatingTakeChat(param, aiHost.getAiApi(), APP_KEY);
        } catch (Exception e) {
            throw new RuntimeException("AI服务调用失败", e);
        }
    }
    private static Map<String, Object> buildRequestParam(Long customerId,
                                                         String tradeType,
                                                         List<Map<String, Object>> communication) {
        Map<String, Object> requestParam = new HashMap<>();

        // 获取各类数据
        Map<String, Object> remove = communication.remove(0);
        String tradeName = getDictLabel(tradeType);
        Map<String, Object> tags = getTags(tradeType);
        Map<String, Object> history = getHistory(communication,customerId.toString());
        Map<String, Object> userInfo = getUserInfo(customerId);
        Map<String, Object> aiInfo = getAiInfo(remove);
        String likeRatio ="";
        if (!userInfo.isEmpty()){
            likeRatio = (String) userInfo.remove("likeRatio");
        }
        // 合并数据
        Stream.of(tags, history, userInfo, aiInfo)
                .filter(Objects::nonNull)
                .forEach(requestParam::putAll);

        // 设置其他参数
        requestParam.put("tradeName", tradeName);
        requestParam.put("tradeType", tradeType);
        requestParam.put("tagInfos", Collections.emptyList());
        requestParam.put("isRepository", "");
        requestParam.put("userContent", "");
        requestParam.put("aiContent", "");
        requestParam.put("likeRatio", likeRatio);
        requestParam.put("modelType","ai标签");

        return requestParam;
    }
    private static List<Map<String, Object>> parseCommunicationJson(String jsonStr) {
        try {
            return mapper.readValue(jsonStr,
                    new TypeReference<List<Map<String, Object>>>() {});
        } catch (Exception e) {
            throw new RuntimeException("数据格式错误", e);
        }
    }
    private static void validateParams(CrmCustomerAiTagParam content) {
        if (ObjectUtil.isEmpty(content.getTradeType())
                || ObjectUtil.isEmpty(content.getCustomerId())
                || ObjectUtil.isEmpty(content.getLogId())
                || ObjectUtil.isEmpty(content.getJson())) {
            throw new IllegalArgumentException("参数不能为空");
        }
    }
    /**
     * 提取 tagInfos 数据
     */
    public static List<Map<String, String>> extractTagInfos(String jsonStr) {
        try {
            JsonNode root = mapper.readTree(jsonStr);

            // 获取 responseData 数组
            JsonNode responseData = root.path("data").path("responseData");

            // 查找 AI 对话节点
            for (JsonNode node : responseData) {
                String moduleName = node.path("moduleName").asText();
                if ("AI 对话".equals(moduleName)) {
                    // 获取 historyPreview 数组
                    JsonNode historyPreview = node.path("historyPreview");

                    // 查找 AI 节点的 historyPreview
                    for (JsonNode preview : historyPreview) {
                        String objType = preview.path("obj").asText();
                        if ("AI".equals(objType)) {
                            JsonNode valueNode = preview.path("value");

                            // 如果 value 是字符串，需要再次解析
                            if (valueNode.isTextual()) {
                                String valueStr = valueNode.asText();
                                JsonNode tagInfosNode = mapper.readTree(valueStr).path("tagInfos");

                                if (tagInfosNode.isArray()) {
                                    return mapper.convertValue(tagInfosNode,
                                            new TypeReference<List<Map<String, String>>>() {
                                            });
                                }
                            } else if (valueNode.isObject()) {
                                JsonNode tagInfosNode = valueNode.path("tagInfos");
                                if (tagInfosNode.isArray()) {
                                    return mapper.convertValue(tagInfosNode,
                                            new TypeReference<List<Map<String, String>>>() {
                                            });
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 获取完整的 AI 响应数据
     */
    public static Map<String, Object> getAIResponseData(String jsonStr) {
        try {
            JsonNode root = mapper.readTree(jsonStr);
            JsonNode responseData = root.path("data").path("responseData");

            for (JsonNode node : responseData) {
                if ("AI 对话".equals(node.path("moduleName").asText())) {
                    JsonNode historyPreview = node.path("historyPreview");

                    for (JsonNode preview : historyPreview) {
                        if ("AI".equals(preview.path("obj").asText())) {
                            JsonNode valueNode = preview.path("value");

                            if (valueNode.isTextual()) {
                                return mapper.readValue(valueNode.asText(),
                                        new TypeReference<Map<String, Object>>() {
                                        });
                            } else if (valueNode.isObject()) {
                                return mapper.convertValue(valueNode,
                                        new TypeReference<Map<String, Object>>() {
                                        });
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<>();
    }

    /**
     * 提取所有标签（包括 tagInfos 和 tags 定义）
     */
    public static Map<String, Object> getAllTagInfo(String jsonStr) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 获取 AI 响应数据
            Map<String, Object> aiResponse = getAIResponseData(jsonStr);

            // tagInfos - 实际提取的标签值
            List<Map<String, String>> tagInfos = (List<Map<String, String>>) aiResponse.get("tagInfos");
            result.put("tagInfos", tagInfos != null ? tagInfos : new ArrayList<>());

            // tags - 标签定义（从原始 query 中获取）
            JsonNode root = mapper.readTree(jsonStr);
            JsonNode responseData = root.path("data").path("responseData");

            for (JsonNode node : responseData) {
                if ("AI 对话".equals(node.path("moduleName").asText())) {
                    JsonNode query = node.path("query");
                    JsonNode tagsNode = query.path("tags");

                    if (tagsNode.isArray()) {
                        List<Map<String, String>> tags = mapper.convertValue(tagsNode,
                                new TypeReference<List<Map<String, String>>>() {
                                });
                        result.put("tags", tags);
                    }
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    private static Map<String, Object> getAiInfo(Map<String, Object> remove) {
        HashMap<String, String> aiInfo = new HashMap<>();
        aiInfo.put("name", "");
        aiInfo.put("sex", "");
        aiInfo.put("age", "");
        aiInfo.put("city", "");
        aiInfo.put("habits", "");
        aiInfo.put("describe", "");
        HashMap<String, Object> result = new HashMap<>();
        result.put("aiInfo", aiInfo);
        return result;
    }

    private static Map<String, Object> getUserInfo(Long customerId) {
        CrmCustomerMapper customerMapper = SpringUtils.getBean(CrmCustomerMapper.class);
        CrmCustomer crmCustomer = customerMapper.selectCrmCustomerById(customerId);
        if (ObjectUtil.isEmpty(crmCustomer)) throw new RuntimeException("客户不存在");
        CrmCustomerInfo crmCustomerInfo = customerMapper.selectCrmCustomerInfoById(customerId);
        if (ObjectUtil.isEmpty(crmCustomerInfo)) {
            crmCustomerInfo = new CrmCustomerInfo();
            crmCustomerInfo.setCustomerId(crmCustomer.getCustomerId()).setName(crmCustomer.getCustomerName()).setSex(crmCustomer.getSex().toString())
                    .setTalk("首次交流");
            customerMapper.insertCrmCustomerInfo(crmCustomerInfo);
        }
        HashMap<String, String> userInfo = new HashMap<String, String>();
        userInfo.put("name", crmCustomerInfo.getName()==null?"" : crmCustomerInfo.getName());
        userInfo.put("sex", crmCustomerInfo.getSex()==null?"" : crmCustomerInfo.getSex().toString());
        userInfo.put("age", "");
        userInfo.put("city", "");
        userInfo.put("habits", "");
        userInfo.put("describe", "");
        HashMap<String, Object> result = new HashMap<>();
        result.put("userInfo", userInfo);
        result.put("likeRatio", ObjectUtil.isNotEmpty(crmCustomer.getIntention()) ? crmCustomer.getIntention() : "");
        return result;
    }

    private static Map<String, Object> getHistory(List<Map<String, Object>> communication,String customerId) {
        StringBuilder history = new StringBuilder();
        history.append("{");
        for (Map<String, Object> o :
                communication) {
            String role = (String) o.get("role");
            String content = (String) o.get("content");
            String roleTag = "user".equals(role) ? "user" : "ai";
            history.append(String.format("\"%s\":\"%s\",", roleTag, content));
        }
        history.deleteCharAt(history.length() - 1).append("}");
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("history", history);
        ArrayList<Map> maps = new ArrayList<>();
        //存入crm_customer_info
        communication.forEach(o->{
            String role = (String) o.get("role");
            String content = (String) o.get("content");
            if (content != null && !content.trim().isEmpty()) { // 过滤空内容
                String roleTag = "user".equals(role) ? "user" : "ai";
                Map<String, String> message = new HashMap<>();
                message.put(roleTag, content);
                maps.add(message);
            }
        });
        if (!maps.isEmpty()){
            CrmCustomerAnalyzeMapper bean = SpringUtils.getBean(CrmCustomerAnalyzeMapper.class);
            CrmCustomerAnalyze crmCustomerAnalyze = bean.selectLatestOne(Long.valueOf(customerId));
            crmCustomerAnalyze.setAiChatRecord(JSONUtil.toJsonStr(maps));
            crmCustomerAnalyze.setCreateTime(new Date());
            bean.insertCrmCustomerAnalyze(crmCustomerAnalyze);
        }

        return result;
    }

    private static Map<String, Object> getTags(String tradeType) {
        List<CrmCustomerPropertyTemplate> templates = SpringUtils.getBean(ICrmCustomerPropertyTemplateService.class).getBaseMapper().selectList(new LambdaQueryWrapper<CrmCustomerPropertyTemplate>().eq(
                CrmCustomerPropertyTemplate::getTradeType, tradeType
        ));
        if (ObjectUtil.isEmpty(templates)) throw new RuntimeException("该行业无标签模板");
        ArrayList<Map<String, String>> tags = new ArrayList<>();//标签及提示词
        templates.forEach(o -> {
            Map<String, String> tag = MapUtil.convertToMap(new CrmCustomerAiAutoTagVo(String.valueOf(o.getId()), o.getName(), o.getAiHint()));
            tags.add(tag);
        });
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("tags", tags);
        return resultMap;
    }

    private static String getDictLabel(String tradeType) {
        List<SysDictData> tradeTypeDict = DictUtils.getDictCache(TRADE_TYPE);
        String dictLabel;
        if (ObjectUtil.isEmpty(tradeTypeDict)) {
            dictLabel = DictUtils.getDictLabel(TRADE_TYPE, tradeType);
        } else {
            Map<String, String> collect = tradeTypeDict.stream().collect(Collectors.toMap(SysDictData::getDictValue,
                    SysDictData::getDictLabel, (v1, v2) -> v1)
            );
            dictLabel = collect.get(tradeType);
        }
        if (ObjectUtil.isEmpty(dictLabel)) {
            throw new RuntimeException("字典中不存在该行业");
        } else return dictLabel;
    }
}
