package org.dromara.ai.monitor;

import lombok.Data;
import lombok.EqualsAndHashCode;

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

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

    /**
     * 系统启动时间
     */
    private LocalDateTime systemStartTime;

    /**
     * 总用户数
     */
    private AtomicLong totalUsers = new AtomicLong(0);

    /**
     * 活跃用户数（24小时内）
     */
    private AtomicLong activeUsers = new AtomicLong(0);

    /**
     * 在线用户数
     */
    private AtomicLong onlineUsers = new AtomicLong(0);

    /**
     * 总Provider数
     */
    private AtomicLong totalProviders = new AtomicLong(0);

    /**
     * 可用Provider数
     */
    private AtomicLong availableProviders = new AtomicLong(0);

    /**
     * 总模型数
     */
    private AtomicLong totalModels = new AtomicLong(0);

    /**
     * 可用模型数
     */
    private AtomicLong availableModels = new AtomicLong(0);

    /**
     * 系统总收入（分）
     */
    private LongAdder totalRevenue = new LongAdder();

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

    /**
     * 系统利润（分）
     */
    private LongAdder totalProfit = new LongAdder();

    /**
     * 峰值并发请求数
     */
    private AtomicLong peakConcurrentRequests = new AtomicLong(0);

    /**
     * 峰值并发用户数
     */
    private AtomicLong peakConcurrentUsers = new AtomicLong(0);

    /**
     * 系统负载（0-100）
     */
    private volatile double systemLoad = 0.0;

    /**
     * 内存使用率（0-100）
     */
    private volatile double memoryUsage = 0.0;

    /**
     * CPU使用率（0-100）
     */
    private volatile double cpuUsage = 0.0;

    /**
     * 磁盘使用率（0-100）
     */
    private volatile double diskUsage = 0.0;

    /**
     * 网络带宽使用（MB/s）
     */
    private volatile double networkBandwidth = 0.0;

    /**
     * 数据库连接池使用率（0-100）
     */
    private volatile double dbConnectionUsage = 0.0;

    /**
     * Redis连接池使用率（0-100）
     */
    private volatile double redisConnectionUsage = 0.0;

    /**
     * 按小时统计的请求数
     */
    private Map<Integer, AtomicLong> hourlyRequests = new ConcurrentHashMap<>();

    /**
     * 按天统计的请求数
     */
    private Map<String, AtomicLong> dailyRequests = new ConcurrentHashMap<>();

    /**
     * 系统健康状态
     */
    private String healthStatus = "HEALTHY";

    /**
     * 系统警告数
     */
    private AtomicLong warningCount = new AtomicLong(0);

    /**
     * 系统错误数
     */
    private AtomicLong systemErrorCount = new AtomicLong(0);

    /**
     * 最后健康检查时间
     */
    private LocalDateTime lastHealthCheckTime;

    /**
     * 系统版本
     */
    private String systemVersion;

    /**
     * 部署环境
     */
    private String environment;

    public SystemMetrics(String systemVersion, String environment) {
        this.systemVersion = systemVersion;
        this.environment = environment;
        this.systemStartTime = LocalDateTime.now();
        this.lastHealthCheckTime = LocalDateTime.now();

        // 初始化24小时统计
        for (int i = 0; i < 24; i++) {
            hourlyRequests.put(i, new AtomicLong(0));
        }
    }

    /**
     * 记录用户活动
     *
     * @param userId    用户ID
     * @param isNewUser 是否新用户
     */
    public void recordUserActivity(Long userId, boolean isNewUser) {
        if (isNewUser) {
            totalUsers.incrementAndGet();
        }
        // 这里可以添加更复杂的活跃用户统计逻辑
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新在线用户数
     *
     * @param count 当前在线用户数
     */
    public void updateOnlineUsers(long count) {
        onlineUsers.set(count);

        // 更新峰值并发用户数
        long currentPeak = peakConcurrentUsers.get();
        while (count > currentPeak && !peakConcurrentUsers.compareAndSet(currentPeak, count)) {
            currentPeak = peakConcurrentUsers.get();
        }

        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新Provider统计
     *
     * @param total     总Provider数
     * @param available 可用Provider数
     */
    public void updateProviderStats(long total, long available) {
        totalProviders.set(total);
        availableProviders.set(available);
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新模型统计
     *
     * @param total     总模型数
     * @param available 可用模型数
     */
    public void updateModelStats(long total, long available) {
        totalModels.set(total);
        availableModels.set(available);
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录收入
     *
     * @param revenue 收入金额（分）
     */
    public void recordRevenue(long revenue) {
        totalRevenue.add(revenue);
        updateProfit();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录成本
     *
     * @param cost 成本金额（分）
     */
    public void recordCost(long cost) {
        totalCost.add(cost);
        updateProfit();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新系统资源使用情况
     *
     * @param cpuUsage         CPU使用率
     * @param memoryUsage      内存使用率
     * @param diskUsage        磁盘使用率
     * @param networkBandwidth 网络带宽
     */
    public void updateSystemResources(double cpuUsage, double memoryUsage,
                                      double diskUsage, double networkBandwidth) {
        this.cpuUsage = cpuUsage;
        this.memoryUsage = memoryUsage;
        this.diskUsage = diskUsage;
        this.networkBandwidth = networkBandwidth;

        // 计算系统负载
        this.systemLoad = (cpuUsage + memoryUsage + diskUsage) / 3.0;

        updateHealthStatus();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新数据库连接使用情况
     *
     * @param dbUsage    数据库连接使用率
     * @param redisUsage Redis连接使用率
     */
    public void updateConnectionUsage(double dbUsage, double redisUsage) {
        this.dbConnectionUsage = dbUsage;
        this.redisConnectionUsage = redisUsage;
        updateHealthStatus();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录请求（按时间统计）
     */
    @Override
    public void incrementTotalRequests() {
        super.incrementTotalRequests();

        // 记录当前小时的请求数
        int currentHour = LocalDateTime.now().getHour();
        hourlyRequests.get(currentHour).incrementAndGet();

        // 记录当天的请求数
        String today = LocalDateTime.now().toLocalDate().toString();
        dailyRequests.computeIfAbsent(today, k -> new AtomicLong(0)).incrementAndGet();

        // 更新峰值并发请求数
        int activeCount = getActiveRequestCount();
        long currentPeak = peakConcurrentRequests.get();
        while (activeCount > currentPeak && !peakConcurrentRequests.compareAndSet(currentPeak, activeCount)) {
            currentPeak = peakConcurrentRequests.get();
        }
    }

    /**
     * 记录系统警告
     *
     * @param warningMessage 警告信息
     */
    public void recordWarning(String warningMessage) {
        warningCount.incrementAndGet();
        incrementErrorCount("WARNING: " + warningMessage);
        updateHealthStatus();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 记录系统错误
     *
     * @param errorMessage 错误信息
     */
    public void recordSystemError(String errorMessage) {
        systemErrorCount.incrementAndGet();
        incrementErrorCount("ERROR: " + errorMessage);
        updateHealthStatus();
        lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 更新健康状态
     */
    private void updateHealthStatus() {
        // 基于各种指标计算健康状态
        if (systemLoad > 90 || memoryUsage > 90 || diskUsage > 95 ||
                dbConnectionUsage > 90 || redisConnectionUsage > 90) {
            healthStatus = "CRITICAL";
        } else if (systemLoad > 70 || memoryUsage > 70 || diskUsage > 80 ||
                dbConnectionUsage > 70 || redisConnectionUsage > 70) {
            healthStatus = "WARNING";
        } else if (availableProviders.get() == 0 || availableModels.get() == 0) {
            healthStatus = "DEGRADED";
        } else {
            healthStatus = "HEALTHY";
        }

        lastHealthCheckTime = LocalDateTime.now();
    }

    /**
     * 更新利润
     */
    private void updateProfit() {
        long profit = totalRevenue.longValue() - totalCost.longValue();
        totalProfit.reset();
        totalProfit.add(profit);
    }

    /**
     * 获取系统运行时间（小时）
     */
    public long getSystemUptimeHours() {
        return java.time.Duration.between(systemStartTime, LocalDateTime.now()).toHours();
    }

    /**
     * 获取Provider可用率
     */
    public double getProviderAvailabilityRate() {
        long total = totalProviders.get();
        if (total > 0) {
            return (double) availableProviders.get() / total * 100;
        }
        return 0.0;
    }

    /**
     * 获取模型可用率
     */
    public double getModelAvailabilityRate() {
        long total = totalModels.get();
        if (total > 0) {
            return (double) availableModels.get() / total * 100;
        }
        return 0.0;
    }

    /**
     * 获取利润率
     */
    public double getProfitMargin() {
        long revenue = totalRevenue.longValue();
        if (revenue > 0) {
            return (double) totalProfit.longValue() / revenue * 100;
        }
        return 0.0;
    }

    /**
     * 获取系统健康评分 (0-100)
     */
    public double getSystemHealthScore() {
        double resourceScore = 100 - systemLoad;
        double availabilityScore = (getProviderAvailabilityRate() + getModelAvailabilityRate()) / 2;
        double errorScore = Math.max(0, 100 - systemErrorCount.get());

        return (resourceScore + availabilityScore + errorScore) / 3.0;
    }

    /**
     * 获取今日请求数
     */
    public long getTodayRequests() {
        String today = LocalDateTime.now().toLocalDate().toString();
        return dailyRequests.getOrDefault(today, new AtomicLong(0)).get();
    }

    /**
     * 获取当前小时请求数
     */
    public long getCurrentHourRequests() {
        int currentHour = LocalDateTime.now().getHour();
        return hourlyRequests.get(currentHour).get();
    }

    /**
     * 获取系统摘要
     */
    public String getSystemSummary() {
        return String.format(
                "System: %s [%s], Status: %s, Users: %d/%d, Providers: %d/%d, Models: %d/%d, Load: %.1f%%, Health: %.1f",
                systemVersion, environment, healthStatus,
                onlineUsers.get(), totalUsers.get(),
                availableProviders.get(), totalProviders.get(),
                availableModels.get(), totalModels.get(),
                systemLoad, getSystemHealthScore()
        );
    }

    /**
     * 重置指标
     */
    @Override
    public void reset() {
        super.reset();
        totalUsers.set(0);
        activeUsers.set(0);
        onlineUsers.set(0);
        totalProviders.set(0);
        availableProviders.set(0);
        totalModels.set(0);
        availableModels.set(0);
        totalRevenue.reset();
        totalCost.reset();
        totalProfit.reset();
        peakConcurrentRequests.set(0);
        peakConcurrentUsers.set(0);
        warningCount.set(0);
        systemErrorCount.set(0);
        hourlyRequests.values().forEach(counter -> counter.set(0));
        dailyRequests.clear();
        systemLoad = 0.0;
        memoryUsage = 0.0;
        cpuUsage = 0.0;
        diskUsage = 0.0;
        networkBandwidth = 0.0;
        dbConnectionUsage = 0.0;
        redisConnectionUsage = 0.0;
        healthStatus = "HEALTHY";
        systemStartTime = LocalDateTime.now();
        lastHealthCheckTime = LocalDateTime.now();
    }
}