package org.dromara.ai.monitor;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * AI Model监控指标
 * 继承基础监控指标，添加Model特有的监控数据
 *
 * @author pengles
 * @date 2024-01-01
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class ModelMetrics extends BaseMetrics {

    /**
     * 模型ID
     */
    private String modelId;

    /**
     * 模型名称
     */
    private String modelName;

    /**
     * Provider名称
     */
    private String providerName;

    /**
     * 模型类型
     */
    private String modelType;

    /**
     * 总成本（分）
     */
    private LongAdder totalCost = new LongAdder();

    /**
     * 输入成本（分）
     */
    private LongAdder inputCost = new LongAdder();

    /**
     * 输出成本（分）
     */
    private LongAdder outputCost = new LongAdder();

    /**
     * 平均质量评分
     */
    private double avgQualityScore = 0.0;

    /**
     * 质量评分总和
     */
    private LongAdder totalQualityScore = new LongAdder();

    /**
     * 质量评分次数
     */
    private AtomicLong qualityScoreCount = new AtomicLong(0);

    /**
     * 上下文长度使用统计
     */
    private LongAdder totalContextLength = new LongAdder();

    /**
     * 最大上下文长度
     */
    private AtomicLong maxContextLength = new AtomicLong(0);

    /**
     * 流式请求数
     */
    private AtomicLong streamRequests = new AtomicLong(0);

    /**
     * 函数调用请求数
     */
    private AtomicLong functionCallRequests = new AtomicLong(0);

    /**
     * 工具调用请求数
     */
    private AtomicLong toolCallRequests = new AtomicLong(0);

    /**
     * 视觉处理请求数
     */
    private AtomicLong visionRequests = new AtomicLong(0);

    /**
     * 图像生成请求数
     */
    private AtomicLong imageGenerationRequests = new AtomicLong(0);

    /**
     * 音频处理请求数
     */
    private AtomicLong audioRequests = new AtomicLong(0);

    /**
     * 最后使用时间
     */
    private LocalDateTime lastUsedTime;

    /**
     * 模型热度（使用频率）
     */
    private double popularity = 0.0;

    public ModelMetrics(String modelId, String modelName, String providerName, String modelType) {
        this.modelId = modelId;
        this.modelName = modelName;
        this.providerName = providerName;
        this.modelType = modelType;
        this.lastUsedTime = LocalDateTime.now();
    }

    /**
     * 记录成本
     *
     * @param inputTokens  输入Token数
     * @param outputTokens 输出Token数
     * @param inputPrice   输入价格（每千Token）
     * @param outputPrice  输出价格（每千Token）
     */
    public void recordCost(int inputTokens, int outputTokens, double inputPrice, double outputPrice) {
        long inputCostValue = Math.round(inputTokens * inputPrice / 1000.0 * 100); // 转换为分
        long outputCostValue = Math.round(outputTokens * outputPrice / 1000.0 * 100); // 转换为分

        inputCost.add(inputCostValue);
        outputCost.add(outputCostValue);
        totalCost.add(inputCostValue + outputCostValue);

        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录质量评分
     *
     * @param score 质量评分 (0-100)
     */
    public void recordQualityScore(double score) {
        if (score >= 0 && score <= 100) {
            totalQualityScore.add(Math.round(score * 100)); // 保留两位小数精度
            qualityScoreCount.incrementAndGet();
            updateAvgQualityScore();
            lastUpdateTime = LocalDateTime.now();
        }
    }

    /**
     * 记录上下文长度
     *
     * @param contextLength 上下文长度
     */
    public void recordContextLength(int contextLength) {
        totalContextLength.add(contextLength);

        // 更新最大上下文长度
        long currentMax = maxContextLength.get();
        while (contextLength > currentMax && !maxContextLength.compareAndSet(currentMax, contextLength)) {
            currentMax = maxContextLength.get();
        }

        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录流式请求
     */
    public void recordStreamRequest() {
        streamRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录函数调用请求
     */
    public void recordFunctionCallRequest() {
        functionCallRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录工具调用请求
     */
    public void recordToolCallRequest() {
        toolCallRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录视觉处理请求
     */
    public void recordVisionRequest() {
        visionRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录图像生成请求
     */
    public void recordImageGenerationRequest() {
        imageGenerationRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录音频处理请求
     */
    public void recordAudioRequest() {
        audioRequests.incrementAndGet();
        recordUsage();
    }

    /**
     * 记录模型使用
     */
    public void recordUsage() {
        incrementTotalRequests();
        lastUsedTime = LocalDateTime.now();
        updatePopularity();
    }

    /**
     * 更新平均质量评分
     */
    private void updateAvgQualityScore() {
        long count = qualityScoreCount.get();
        if (count > 0) {
            avgQualityScore = totalQualityScore.doubleValue() / (count * 100.0);
        }
    }

    /**
     * 更新模型热度
     */
    private void updatePopularity() {
        // 基于最近使用时间和总请求数计算热度
        long totalReqs = getTotalRequests();
        if (totalReqs > 0) {
            // 简单的热度计算：总请求数的对数值
            popularity = Math.log10(totalReqs + 1) * 10;
        }
    }

    /**
     * 获取平均成本（分/千Token）
     */
    public double getAvgCostPerKToken() {
        long totalTokens = getTotalInputTokens() + getTotalOutputTokens();
        if (totalTokens > 0) {
            return totalCost.doubleValue() / (totalTokens / 1000.0);
        }
        return 0.0;
    }

    /**
     * 获取平均上下文长度
     */
    public double getAvgContextLength() {
        long totalReqs = getTotalRequests();
        if (totalReqs > 0) {
            return totalContextLength.doubleValue() / totalReqs;
        }
        return 0.0;
    }

    /**
     * 获取流式请求比例
     */
    public double getStreamRequestRatio() {
        long totalReqs = getTotalRequests();
        if (totalReqs > 0) {
            return (double) streamRequests.get() / totalReqs * 100;
        }
        return 0.0;
    }

    /**
     * 获取功能使用统计
     */
    public String getFeatureUsageStats() {
        return String.format("Stream: %d, Function: %d, Tool: %d, Vision: %d, Image: %d, Audio: %d",
                streamRequests.get(), functionCallRequests.get(), toolCallRequests.get(),
                visionRequests.get(), imageGenerationRequests.get(), audioRequests.get());
    }

    /**
     * 重置指标
     */
    @Override
    public void reset() {
        super.reset();
        totalCost.reset();
        inputCost.reset();
        outputCost.reset();
        totalQualityScore.reset();
        qualityScoreCount.set(0);
        totalContextLength.reset();
        maxContextLength.set(0);
        streamRequests.set(0);
        functionCallRequests.set(0);
        toolCallRequests.set(0);
        visionRequests.set(0);
        imageGenerationRequests.set(0);
        audioRequests.set(0);
        avgQualityScore = 0.0;
        popularity = 0.0;
        lastUsedTime = LocalDateTime.now();
    }
}