package org.dromara.ai.monitor;

import lombok.extern.slf4j.Slf4j;
import org.dromara.ai.provider.AiProvider;
import org.dromara.ai.provider.AiProviderManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * AI服务监控服务
 * 提供性能监控、使用统计和健康检查功能
 *
 * @author pengles
 * @since 2024-01-01
 */
@Slf4j
@Service
public class AiMonitorService {

    @Autowired
    private AiProviderManager providerManager;

    // 监控数据存储
    private final Map<String, ProviderMetrics> providerMetrics = new ConcurrentHashMap<>();
    private final Map<String, ModelMetrics> modelMetrics = new ConcurrentHashMap<>();
    private final Map<String, UserMetrics> userMetrics = new ConcurrentHashMap<>();
    private final SystemMetrics systemMetrics = new SystemMetrics("1.0.0", "production");

    /**
     * 记录请求开始
     *
     * @param providerName Provider名称
     * @param modelName    模型名称
     * @param userId       用户ID
     * @return 请求ID
     */
    public String recordRequestStart(String providerName, String modelName, String userId) {
        String requestId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();

        // 记录Provider指标
        ProviderMetrics pMetrics = providerMetrics.computeIfAbsent(providerName, k -> new ProviderMetrics(k, "AI_PROVIDER"));
        pMetrics.incrementTotalRequests();
        pMetrics.addActiveRequest(requestId, startTime);

        // 记录模型指标
        String modelKey = providerName + ":" + modelName;
        ModelMetrics mMetrics = modelMetrics.computeIfAbsent(modelKey, k -> new ModelMetrics(modelName, modelName, providerName, "TEXT_GENERATION"));
        mMetrics.incrementTotalRequests();
        mMetrics.addActiveRequest(requestId, startTime);

        // 记录用户指标
        if (userId != null) {
            UserMetrics uMetrics = userMetrics.computeIfAbsent(userId, k -> {
                try {
                    return new UserMetrics(Long.parseLong(k), k, "REGULAR");
                } catch (NumberFormatException e) {
                    // 如果userId不是数字，使用hashCode作为ID
                    return new UserMetrics((long) k.hashCode(), k, "REGULAR");
                }
            });
            uMetrics.incrementTotalRequests();
            uMetrics.addActiveRequest(requestId, startTime);
        }

        // 记录系统指标
        systemMetrics.incrementTotalRequests();
        systemMetrics.addActiveRequest(requestId, startTime);

        log.debug("记录请求开始: requestId={}, provider={}, model={}, user={}",
                requestId, providerName, modelName, userId);

        return requestId;
    }

    /**
     * 记录请求完成
     *
     * @param requestId    请求ID
     * @param providerName Provider名称
     * @param modelName    模型名称
     * @param userId       用户ID
     * @param success      是否成功
     * @param inputTokens  输入token数
     * @param outputTokens 输出token数
     * @param errorCode    错误码
     */
    public void recordRequestEnd(String requestId, String providerName, String modelName,
                                 String userId, boolean success, int inputTokens, int outputTokens, String errorCode) {
        long endTime = System.currentTimeMillis();

        // 记录Provider指标
        ProviderMetrics pMetrics = providerMetrics.get(providerName);
        if (pMetrics != null) {
            Long startTime = pMetrics.removeActiveRequest(requestId);
            if (startTime != null) {
                long responseTime = endTime - startTime;
                pMetrics.addResponseTime(responseTime);
                if (success) {
                    pMetrics.incrementSuccessRequests();
                } else {
                    pMetrics.incrementFailedRequests();
                    pMetrics.incrementErrorCount(errorCode);
                }
                pMetrics.addTokenUsage(inputTokens, outputTokens);
            }
        }

        // 记录模型指标
        String modelKey = providerName + ":" + modelName;
        ModelMetrics mMetrics = modelMetrics.get(modelKey);
        if (mMetrics != null) {
            Long startTime = mMetrics.removeActiveRequest(requestId);
            if (startTime != null) {
                long responseTime = endTime - startTime;
                mMetrics.addResponseTime(responseTime);
                if (success) {
                    mMetrics.incrementSuccessRequests();
                } else {
                    mMetrics.incrementFailedRequests();
                    mMetrics.incrementErrorCount(errorCode);
                }
                mMetrics.addTokenUsage(inputTokens, outputTokens);
            }
        }

        // 记录用户指标
        if (userId != null) {
            UserMetrics uMetrics = userMetrics.get(userId);
            if (uMetrics != null) {
                Long startTime = uMetrics.removeActiveRequest(requestId);
                if (startTime != null) {
                    long responseTime = endTime - startTime;
                    uMetrics.addResponseTime(responseTime);
                    if (success) {
                        uMetrics.incrementSuccessRequests();
                    } else {
                        uMetrics.incrementFailedRequests();
                    }
                    uMetrics.addTokenUsage(inputTokens, outputTokens);
                }
            }
        }

        // 记录系统指标
        Long startTime = systemMetrics.removeActiveRequest(requestId);
        if (startTime != null) {
            long responseTime = endTime - startTime;
            systemMetrics.addResponseTime(responseTime);
            if (success) {
                systemMetrics.incrementSuccessRequests();
            } else {
                systemMetrics.incrementFailedRequests();
                systemMetrics.incrementErrorCount(errorCode);
            }
            systemMetrics.addTokenUsage(inputTokens, outputTokens);
        }

        log.debug("记录请求完成: requestId={}, provider={}, model={}, user={}, success={}, responseTime={}ms",
                requestId, providerName, modelName, userId, success, endTime - (startTime != null ? startTime : endTime));
    }

    /**
     * 获取Provider统计信息
     *
     * @param providerName Provider名称
     * @return 统计信息
     */
    public Map<String, Object> getProviderStats(String providerName) {
        ProviderMetrics metrics = providerMetrics.get(providerName);
        if (metrics == null) {
            return new HashMap<>();
        }

        Map<String, Object> stats = new HashMap<>();
        stats.put("providerName", providerName);
        stats.put("totalRequests", metrics.getTotalRequests());
        stats.put("successRequests", metrics.getSuccessRequests());
        stats.put("failedRequests", metrics.getFailedRequests());
        stats.put("activeRequests", metrics.getActiveRequestCount());
        stats.put("successRate", metrics.getSuccessRate());
        stats.put("avgResponseTime", metrics.getAvgResponseTime());
        stats.put("minResponseTime", metrics.getMinResponseTime());
        stats.put("maxResponseTime", metrics.getMaxResponseTime());
        stats.put("totalInputTokens", metrics.getTotalInputTokens());
        stats.put("totalOutputTokens", metrics.getTotalOutputTokens());
        stats.put("errorCounts", metrics.getErrorCounts());
        stats.put("lastUpdateTime", metrics.getLastUpdateTime());

        return stats;
    }

    /**
     * 获取模型统计信息
     *
     * @param providerName Provider名称
     * @param modelName    模型名称
     * @return 统计信息
     */
    public Map<String, Object> getModelStats(String providerName, String modelName) {
        String modelKey = providerName + ":" + modelName;
        ModelMetrics metrics = modelMetrics.get(modelKey);
        if (metrics == null) {
            return new HashMap<>();
        }

        Map<String, Object> stats = new HashMap<>();
        stats.put("providerName", providerName);
        stats.put("modelName", modelName);
        stats.put("totalRequests", metrics.getTotalRequests());
        stats.put("successRequests", metrics.getSuccessRequests());
        stats.put("failedRequests", metrics.getFailedRequests());
        stats.put("activeRequests", metrics.getActiveRequestCount());
        stats.put("successRate", metrics.getSuccessRate());
        stats.put("avgResponseTime", metrics.getAvgResponseTime());
        stats.put("minResponseTime", metrics.getMinResponseTime());
        stats.put("maxResponseTime", metrics.getMaxResponseTime());
        stats.put("totalInputTokens", metrics.getTotalInputTokens());
        stats.put("totalOutputTokens", metrics.getTotalOutputTokens());
        stats.put("errorCounts", metrics.getErrorCounts());
        stats.put("lastUpdateTime", metrics.getLastUpdateTime());

        return stats;
    }

    /**
     * 获取用户统计信息
     *
     * @param userId 用户ID
     * @return 统计信息
     */
    public Map<String, Object> getUserStats(String userId) {
        UserMetrics metrics = userMetrics.get(userId);
        if (metrics == null) {
            return new HashMap<>();
        }

        Map<String, Object> stats = new HashMap<>();
        stats.put("userId", userId);
        stats.put("totalRequests", metrics.getTotalRequests());
        stats.put("successRequests", metrics.getSuccessRequests());
        stats.put("failedRequests", metrics.getFailedRequests());
        stats.put("activeRequests", metrics.getActiveRequestCount());
        stats.put("successRate", metrics.getSuccessRate());
        stats.put("avgResponseTime", metrics.getAvgResponseTime());
        stats.put("totalInputTokens", metrics.getTotalInputTokens());
        stats.put("totalOutputTokens", metrics.getTotalOutputTokens());
        stats.put("lastUpdateTime", metrics.getLastUpdateTime());

        return stats;
    }

    /**
     * 获取系统统计信息
     *
     * @return 统计信息
     */
    public Map<String, Object> getSystemStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalRequests", systemMetrics.getTotalRequests());
        stats.put("successRequests", systemMetrics.getSuccessRequests());
        stats.put("failedRequests", systemMetrics.getFailedRequests());
        stats.put("activeRequests", systemMetrics.getActiveRequestCount());
        stats.put("successRate", systemMetrics.getSuccessRate());
        stats.put("avgResponseTime", systemMetrics.getAvgResponseTime());
        stats.put("minResponseTime", systemMetrics.getMinResponseTime());
        stats.put("maxResponseTime", systemMetrics.getMaxResponseTime());
        stats.put("totalInputTokens", systemMetrics.getTotalInputTokens());
        stats.put("totalOutputTokens", systemMetrics.getTotalOutputTokens());
        stats.put("errorCounts", systemMetrics.getErrorCounts());
        stats.put("providerCount", providerMetrics.size());
        stats.put("modelCount", modelMetrics.size());
        stats.put("userCount", userMetrics.size());
        stats.put("lastUpdateTime", systemMetrics.getLastUpdateTime());

        return stats;
    }

    /**
     * 获取所有Provider统计信息
     *
     * @return Provider统计列表
     */
    public List<Map<String, Object>> getAllProviderStats() {
        return providerMetrics.keySet().stream()
                .map(this::getProviderStats)
                .collect(Collectors.toList());
    }

    /**
     * 获取热门模型排行
     *
     * @param limit 限制数量
     * @return 模型排行列表
     */
    public List<Map<String, Object>> getPopularModels(int limit) {
        return modelMetrics.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue().getTotalRequests(), e1.getValue().getTotalRequests()))
                .limit(limit)
                .map(entry -> {
                    String[] parts = entry.getKey().split(":", 2);
                    Map<String, Object> model = new HashMap<>();
                    model.put("providerName", parts[0]);
                    model.put("modelName", parts.length > 1 ? parts[1] : "");
                    model.put("totalRequests", entry.getValue().getTotalRequests());
                    model.put("successRate", entry.getValue().getSuccessRate());
                    model.put("avgResponseTime", entry.getValue().getAvgResponseTime());
                    return model;
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取活跃用户排行
     *
     * @param limit 限制数量
     * @return 用户排行列表
     */
    public List<Map<String, Object>> getActiveUsers(int limit) {
        return userMetrics.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue().getTotalRequests(), e1.getValue().getTotalRequests()))
                .limit(limit)
                .map(entry -> {
                    Map<String, Object> user = new HashMap<>();
                    user.put("userId", entry.getKey());
                    user.put("totalRequests", entry.getValue().getTotalRequests());
                    user.put("successRate", entry.getValue().getSuccessRate());
                    user.put("totalTokens", entry.getValue().getTotalInputTokens() + entry.getValue().getTotalOutputTokens());
                    return user;
                })
                .collect(Collectors.toList());
    }

    /**
     * 健康检查
     *
     * @return 健康状态
     */
    public Map<String, Object> healthCheck() {
        Map<String, Object> health = new HashMap<>();

        // 检查Provider健康状态
        List<Map<String, Object>> providerHealth = new ArrayList<>();
        for (AiProvider provider : providerManager.getAllProviders()) {
            Map<String, Object> providerStatus = new HashMap<>();
            providerStatus.put("name", provider.getProviderName());
            providerStatus.put("available", provider.isAvailable());
            providerStatus.put("version", provider.getVersion());

            ProviderMetrics metrics = providerMetrics.get(provider.getProviderName());
            if (metrics != null) {
                providerStatus.put("successRate", metrics.getSuccessRate());
                providerStatus.put("avgResponseTime", metrics.getAvgResponseTime());
                providerStatus.put("activeRequests", metrics.getActiveRequestCount());
            }

            providerHealth.add(providerStatus);
        }

        health.put("providers", providerHealth);
        health.put("systemStats", getSystemStats());
        health.put("timestamp", LocalDateTime.now());

        // 计算整体健康分数
        double healthScore = calculateHealthScore();
        health.put("healthScore", healthScore);
        health.put("status", healthScore >= 0.8 ? "HEALTHY" : healthScore >= 0.5 ? "WARNING" : "CRITICAL");

        return health;
    }

    /**
     * 计算健康分数
     *
     * @return 健康分数 (0.0-1.0)
     */
    private double calculateHealthScore() {
        if (systemMetrics.getTotalRequests() == 0) {
            return 1.0; // 没有请求时认为是健康的
        }

        double successRate = systemMetrics.getSuccessRate();
        double responseTimeScore = Math.max(0, 1.0 - systemMetrics.getAvgResponseTime() / 10000.0); // 10秒为基准

        return (successRate * 0.7 + responseTimeScore * 0.3);
    }

    /**
     * 重置统计数据
     */
    public void resetStats() {
        providerMetrics.clear();
        modelMetrics.clear();
        userMetrics.clear();
        systemMetrics.reset();
        log.info("AI监控统计数据已重置");
    }

    /**
     * 定时清理过期数据
     */
    @Scheduled(fixedRate = 3600000) // 每小时执行一次
    public void cleanupExpiredData() {
        long expireTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000; // 24小时前

        // 清理过期的活跃请求
        providerMetrics.values().forEach(metrics -> metrics.cleanupExpiredRequests(expireTime));
        modelMetrics.values().forEach(metrics -> metrics.cleanupExpiredRequests(expireTime));
        userMetrics.values().forEach(metrics -> metrics.cleanupExpiredRequests(expireTime));
        systemMetrics.cleanupExpiredRequests(expireTime);

        log.debug("清理过期监控数据完成");
    }

    /**
     * 定时输出监控报告
     */
    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
    public void logMonitorReport() {
        Map<String, Object> systemStats = getSystemStats();
        log.info("AI服务监控报告: 总请求={}, 成功率={}, 平均响应时间={}ms, 活跃请求={}",
                systemStats.get("totalRequests"),
                systemStats.get("successRate"),
                systemStats.get("avgResponseTime"),
                systemStats.get("activeRequests"));
    }
}