package org.dromara.ai.service;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.ai.domain.AiChatRecord;
import org.dromara.ai.domain.bo.AiChatRecordBo;
import org.dromara.ai.domain.dto.AiChatRequest;
import org.dromara.ai.domain.dto.AiChatResponse;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * AI聊天历史服务
 * 提供聊天历史的存储、检索和管理功能
 *
 * @author pengles
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiChatHistoryService {

    private final org.dromara.ai.service.AiChatRecordService aiChatRecordService;
    private final org.dromara.ai.service.AiUsageStatsService aiUsageStatsService;

    /**
     * Redis键前缀
     */
    private static final String HISTORY_KEY_PREFIX = "ai:chat:history:";

    /**
     * 会话统计键前缀
     */
    private static final String STATS_KEY_PREFIX = "ai:chat:stats:";

    /**
     * 历史记录默认过期时间（30天）
     */
    private static final Duration DEFAULT_EXPIRE_DURATION = Duration.ofDays(30);

    /**
     * 单次历史记录最大数量
     */
    private static final int MAX_HISTORY_SIZE = 1000;

    /**
     * 保存聊天历史
     *
     * @param sessionId 会话ID
     * @param request   聊天请求
     * @param response  聊天响应
     */
    public void saveHistory(String sessionId, AiChatRequest request, AiChatResponse response) {
        if (StringUtils.isBlank(sessionId)) {
            return;
        }

        try {
            String historyKey = HISTORY_KEY_PREFIX + sessionId;

            // 获取当前历史记录
            List<AiChatRequest.AiMessage> history = getHistoryInternal(sessionId);
            if (history == null) {
                history = new ArrayList<>();
            }

            // 添加用户消息（只保存最后一条用户消息，避免重复）
            if (request.getMessages() != null && !request.getMessages().isEmpty()) {
                // 获取最后一条用户消息
                AiChatRequest.AiMessage lastUserMessage = request.getMessages().stream()
                        .filter(msg -> "user".equals(msg.getRole()))
                        .reduce((first, second) -> second)
                        .orElse(null);

                if (lastUserMessage != null) {
                    history.add(createMessageCopy(lastUserMessage));
                }
            }

            // 添加助手响应消息
            if (response != null && response.getChoices() != null && !response.getChoices().isEmpty()) {
                AiChatResponse.Choice choice = response.getChoices().get(0);
                if (choice.getMessage() != null && choice.getMessage().getContent() != null) {
                    AiChatRequest.AiMessage assistantMsg = createMessageCopy(choice.getMessage());
                    assistantMsg.setRole("assistant");
                    history.add(assistantMsg);
                }
            }

            // 限制历史记录大小
            if (history.size() > MAX_HISTORY_SIZE) {
                history = history.subList(history.size() - MAX_HISTORY_SIZE, history.size());
            }

            // 保存到Redis
            RedisUtils.setCacheObject(historyKey, history, DEFAULT_EXPIRE_DURATION);

            // 保存到数据库
            saveToDatabase(sessionId, request, response);

            // 更新会话统计
            updateSessionStats(sessionId, request, response);

        } catch (Exception e) {
            log.error("保存聊天历史失败 - 会话: {}", sessionId, e);
        }
    }

    /**
     * 保存聊天记录到数据库
     */
    private void saveToDatabase(String sessionId, AiChatRequest request, AiChatResponse response) {
        try {
            List<AiChatRecordBo> recordBoList = new ArrayList<>();
            Long userId = null;
            try {
                if (StringUtils.isNotBlank(request.getUserId())) {
                    userId = Long.parseLong(request.getUserId());
                }
            } catch (NumberFormatException e) {
                log.warn("用户ID格式错误: {}", request.getUserId());
            }

            // 保存用户消息
            if (request.getMessages() != null && !request.getMessages().isEmpty()) {
                AiChatRequest.AiMessage lastUserMessage = request.getMessages().stream()
                        .filter(msg -> "user".equals(msg.getRole()))
                        .reduce((first, second) -> second)
                        .orElse(null);

                if (lastUserMessage != null && StringUtils.isNotBlank(lastUserMessage.getContent())) {
                    AiChatRecordBo userRecordBo = new AiChatRecordBo();
                    userRecordBo.setSessionId(sessionId);
                    userRecordBo.setUserId(userId);
                    userRecordBo.setProviderName(response != null ? response.getProvider() : null);
                    userRecordBo.setModelName(request.getModel());
                    userRecordBo.setMessageType("USER");
                    userRecordBo.setContent(lastUserMessage.getContent());
                    userRecordBo.setIsStream(request.getStream() != null && request.getStream() ? 1 : 0);
                    recordBoList.add(userRecordBo);
                }
            }

            // 保存助手响应消息
            if (response != null && response.getChoices() != null && !response.getChoices().isEmpty()) {
                AiChatResponse.Choice choice = response.getChoices().get(0);
                if (choice.getMessage() != null && StringUtils.isNotBlank(choice.getMessage().getContent())) {
                    AiChatRecordBo assistantRecordBo = new AiChatRecordBo();
                    assistantRecordBo.setSessionId(sessionId);
                    assistantRecordBo.setUserId(userId);
                    assistantRecordBo.setProviderName(response.getProvider());
                    assistantRecordBo.setModelName(response.getModel());
                    assistantRecordBo.setMessageType("ASSISTANT");
                    assistantRecordBo.setContent(choice.getMessage().getContent());
                    assistantRecordBo.setIsStream(request.getStream() != null && request.getStream() ? 1 : 0);

                    // 设置Token使用信息
                    if (response.getUsage() != null) {
                        assistantRecordBo.setTokensUsed(response.getUsage().getTotalTokens());
                    }

                    // 设置成本（如果有）
                    // 注意：成本计算需要在业务层实现，这里可以预留字段

                    // 设置响应时间
                    if (response.getResponseTime() != null) {
                        assistantRecordBo.setResponseTime(response.getResponseTime().intValue());
                    }

                    // 设置错误信息
                    if (StringUtils.isNotBlank(response.getError())) {
                        assistantRecordBo.setErrorMessage(response.getError());
                    }

                    recordBoList.add(assistantRecordBo);
                }
            }

            // 批量保存到数据库
            if (!recordBoList.isEmpty()) {
                aiChatRecordService.insertBatch(recordBoList);
            }

            // 记录使用统计（只统计助手响应，避免重复统计）
            // 无论成功或失败都记录，以便统计错误次数
            if (response != null) {
                Long userIdLong = userId;
                String providerName = response.getProvider();
                String modelName = response.getModel();
                Long tokens = response.getUsage() != null ? Long.valueOf(response.getUsage().getTotalTokens() != null ? response.getUsage().getTotalTokens() : 0) : 0L;
                BigDecimal cost = null; // 成本计算需要在业务层实现
                Integer responseTime = response.getResponseTime() != null ? response.getResponseTime().intValue() : null;
                Boolean success = response.getSuccess() != null ? response.getSuccess() : false;

                if (userIdLong != null && StringUtils.isNotBlank(providerName)) {
                    aiUsageStatsService.recordUsage(userIdLong, providerName, modelName, tokens, cost, responseTime, success);
                }
            }

        } catch (Exception e) {
            log.error("保存聊天记录到数据库失败 - 会话: {}", sessionId, e);
            // 不抛出异常，避免影响Redis保存
        }
    }

    /**
     * 获取聊天历史（内部方法，不限制数量）
     */
    private List<AiChatRequest.AiMessage> getHistoryInternal(String sessionId) {
        if (StringUtils.isBlank(sessionId)) {
            return null;
        }

        try {
            String historyKey = HISTORY_KEY_PREFIX + sessionId;
            return RedisUtils.getCacheObject(historyKey);
        } catch (Exception e) {
            log.error("获取聊天历史失败 - 会话: {}", sessionId, e);
            return null;
        }
    }

    /**
     * 获取聊天历史
     *
     * @param sessionId 会话ID
     * @param limit     限制数量
     * @return 聊天历史列表
     */
    public List<AiChatRequest.AiMessage> getHistory(String sessionId, Integer limit) {
        if (StringUtils.isBlank(sessionId)) {
            return Collections.emptyList();
        }

        try {
            List<AiChatRequest.AiMessage> history = getHistoryInternal(sessionId);

            if (history == null || history.isEmpty()) {
                return Collections.emptyList();
            }

            // 限制返回数量
            if (limit != null && limit > 0 && history.size() > limit) {
                return new ArrayList<>(history.subList(history.size() - limit, history.size()));
            }

            return new ArrayList<>(history);

        } catch (Exception e) {
            log.error("获取聊天历史失败 - 会话: {}", sessionId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 清除聊天历史
     *
     * @param sessionId 会话ID
     */
    public void clearHistory(String sessionId) {
        if (StringUtils.isBlank(sessionId)) {
            return;
        }

        try {
            String historyKey = HISTORY_KEY_PREFIX + sessionId;
            String statsKey = STATS_KEY_PREFIX + sessionId;

            RedisUtils.deleteObject(historyKey);
            RedisUtils.deleteObject(statsKey);

            log.info("清除聊天历史成功 - 会话: {}", sessionId);

        } catch (Exception e) {
            log.error("清除聊天历史失败 - 会话: {}", sessionId, e);
        }
    }

    /**
     * 获取会话统计信息
     *
     * @param sessionId 会话ID
     * @return 统计信息
     */
    public SessionStats getSessionStats(String sessionId) {
        if (StringUtils.isBlank(sessionId)) {
            return new SessionStats();
        }

        try {
            String statsKey = STATS_KEY_PREFIX + sessionId;
            SessionStats stats = RedisUtils.getCacheObject(statsKey);

            if (stats == null) {
                // 如果统计不存在，从历史记录计算
                stats = calculateStatsFromHistory(sessionId);
            }

            return stats != null ? stats : new SessionStats();

        } catch (Exception e) {
            log.error("获取会话统计失败 - 会话: {}", sessionId, e);
            return new SessionStats();
        }
    }

    /**
     * 更新会话统计
     */
    private void updateSessionStats(String sessionId, AiChatRequest request, AiChatResponse response) {
        try {
            String statsKey = STATS_KEY_PREFIX + sessionId;
            SessionStats stats = RedisUtils.getCacheObject(statsKey);

            if (stats == null) {
                stats = new SessionStats();
                stats.setSessionId(sessionId);
                stats.setCreatedAt(LocalDateTime.now());
            }

            stats.setLastUpdatedAt(LocalDateTime.now());
            stats.setMessageCount(stats.getMessageCount() + 1);

            // 更新token使用统计
            if (response != null && response.getUsage() != null) {
                if (response.getUsage().getPromptTokens() != null) {
                    stats.setTotalPromptTokens(stats.getTotalPromptTokens() + response.getUsage().getPromptTokens());
                }
                if (response.getUsage().getCompletionTokens() != null) {
                    stats.setTotalCompletionTokens(stats.getTotalCompletionTokens() + response.getUsage().getCompletionTokens());
                }
                if (response.getUsage().getTotalTokens() != null) {
                    stats.setTotalTokens(stats.getTotalTokens() + response.getUsage().getTotalTokens());
                }
            }

            // 更新响应时间统计
            if (response != null && response.getResponseTime() != null) {
                if (stats.getTotalResponseTime() == null) {
                    stats.setTotalResponseTime(0L);
                }
                stats.setTotalResponseTime(stats.getTotalResponseTime() + response.getResponseTime());
                if (stats.getMaxResponseTime() == null || response.getResponseTime() > stats.getMaxResponseTime()) {
                    stats.setMaxResponseTime(response.getResponseTime());
                }
                if (stats.getMinResponseTime() == null || response.getResponseTime() < stats.getMinResponseTime()) {
                    stats.setMinResponseTime(response.getResponseTime());
                }
            }

            // 保存统计信息
            RedisUtils.setCacheObject(statsKey, stats, DEFAULT_EXPIRE_DURATION);

        } catch (Exception e) {
            log.error("更新会话统计失败 - 会话: {}", sessionId, e);
        }
    }

    /**
     * 从历史记录计算统计信息
     */
    private SessionStats calculateStatsFromHistory(String sessionId) {
        List<AiChatRequest.AiMessage> history = getHistoryInternal(sessionId);
        if (history == null || history.isEmpty()) {
            return new SessionStats();
        }

        SessionStats stats = new SessionStats();
        stats.setSessionId(sessionId);
        stats.setMessageCount(history.size());

        // 计算用户和助手消息数量
        long userCount = history.stream().filter(msg -> "user".equals(msg.getRole())).count();
        long assistantCount = history.stream().filter(msg -> "assistant".equals(msg.getRole())).count();
        stats.setUserMessageCount((int) userCount);
        stats.setAssistantMessageCount((int) assistantCount);

        return stats;
    }

    /**
     * 创建消息副本
     */
    private AiChatRequest.AiMessage createMessageCopy(AiChatRequest.AiMessage original) {
        AiChatRequest.AiMessage copy = new AiChatRequest.AiMessage();
        copy.setRole(original.getRole());
        copy.setContent(original.getContent());
        copy.setName(original.getName());
        // 注意：不复制functionCall和toolCalls，因为它们可能包含复杂对象
        return copy;
    }

    /**
     * 会话统计信息
     */
    @Data
    public static class SessionStats {
        /**
         * 会话ID
         */
        private String sessionId;

        /**
         * 消息总数
         */
        private Integer messageCount = 0;

        /**
         * 用户消息数量
         */
        private Integer userMessageCount = 0;

        /**
         * 助手消息数量
         */
        private Integer assistantMessageCount = 0;

        /**
         * 总prompt tokens
         */
        private Integer totalPromptTokens = 0;

        /**
         * 总completion tokens
         */
        private Integer totalCompletionTokens = 0;

        /**
         * 总tokens
         */
        private Integer totalTokens = 0;

        /**
         * 总响应时间（毫秒）
         */
        private Long totalResponseTime = 0L;

        /**
         * 最大响应时间（毫秒）
         */
        private Long maxResponseTime = null;

        /**
         * 最小响应时间（毫秒）
         */
        private Long minResponseTime = null;

        /**
         * 平均响应时间（毫秒）
         */
        public Double getAvgResponseTime() {
            if (messageCount == null || messageCount == 0 || totalResponseTime == null) {
                return 0.0;
            }
            return (double) totalResponseTime / messageCount;
        }

        /**
         * 创建时间
         */
        private LocalDateTime createdAt;

        /**
         * 最后更新时间
         */
        private LocalDateTime lastUpdatedAt;
    }

}
