package com.qaup.collision.config;

import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.HikariPoolMXBean;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import jakarta.persistence.EntityManagerFactory;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 数据库性能配置和监控
 * 
 * 功能：
 * 1. 连接池性能监控
 * 2. Hibernate统计信息收集
 * 3. 数据库健康检查
 * 4. PostGIS查询性能优化
 * 5. 定期性能报告
 */
@Slf4j
@Configuration
public class DatabasePerformanceConfig {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    /**
     * 数据库健康检查指标
     */
    @Bean
    public HealthIndicator databaseHealthIndicator() {
        return () -> {
            try {
                if (dataSource instanceof HikariDataSource) {
                    // HikariCP连接池状态检查
                    HikariDataSource hikariDataSource = (HikariDataSource) dataSource;
                    if (hikariDataSource.isRunning()) {
                        int activeConnections = hikariDataSource.getHikariPoolMXBean().getActiveConnections();
                        int totalConnections = hikariDataSource.getHikariPoolMXBean().getTotalConnections();
                        int idleConnections = hikariDataSource.getHikariPoolMXBean().getIdleConnections();
                        
                        return Health.up()
                                .withDetail("database", "PostgreSQL + PostGIS")
                                .withDetail("connectionPool", "HikariCP")
                                .withDetail("activeConnections", activeConnections)
                                .withDetail("totalConnections", totalConnections)
                                .withDetail("idleConnections", idleConnections)
                                .withDetail("maxPoolSize", hikariDataSource.getMaximumPoolSize())
                                .withDetail("isRunning", true)
                                .build();
                    }
                }
                
                return Health.down()
                        .withDetail("database", "PostgreSQL + PostGIS")
                        .withDetail("connectionPool", "Unknown or not running")
                        .build();
                        
            } catch (Exception e) {
                log.error("数据库健康检查失败", e);
                return Health.down()
                        .withDetail("database", "PostgreSQL + PostGIS")
                        .withDetail("error", e.getMessage())
                        .build();
            }
        };
    }

    /**
     * 应用启动后初始化性能监控
     */
    @EventListener(ApplicationReadyEvent.class)
    public void initializePerformanceMonitoring() {
        log.info("初始化数据库性能监控...");
        
        // 启用Hibernate统计
        enableHibernateStatistics();
        
        // 启动连接池监控
        startConnectionPoolMonitoring();
        
        // 启动定期性能报告
        startPerformanceReporting();
        
        log.info("数据库性能监控初始化完成");
    }

    /**
     * 启用Hibernate统计信息收集
     */
    private void enableHibernateStatistics() {
        try {
            SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
            Statistics statistics = sessionFactory.getStatistics();
            // 禁用统计信息收集以减少日志输出
            statistics.setStatisticsEnabled(false);
            
            log.info("Hibernate统计信息收集已禁用");
        } catch (Exception e) {
            log.warn("配置Hibernate统计信息失败", e);
        }
    }

    /**
     * 启动连接池监控
     */
    private void startConnectionPoolMonitoring() {
        if (dataSource instanceof HikariDataSource) {
            HikariDataSource hikariDataSource = (HikariDataSource) dataSource;
            scheduler.scheduleWithFixedDelay(() -> {
                try {
                    HikariPoolMXBean poolMXBean = hikariDataSource.getHikariPoolMXBean();
                    
                    int activeConnections = poolMXBean.getActiveConnections();
                    int totalConnections = poolMXBean.getTotalConnections();
                    int idleConnections = poolMXBean.getIdleConnections();
                    int threadsAwaitingConnection = poolMXBean.getThreadsAwaitingConnection();
                    
                    // 连接池使用率警告
                    double usageRate = (double) activeConnections / hikariDataSource.getMaximumPoolSize();
                    if (usageRate > 0.8) {
                        log.warn("连接池使用率过高: {:.1%} ({}/{})", 
                                usageRate, activeConnections, hikariDataSource.getMaximumPoolSize());
                    }
                    
                    // 等待连接的线程警告
                    if (threadsAwaitingConnection > 0) {
                        log.warn("有 {} 个线程正在等待数据库连接", threadsAwaitingConnection);
                    }
                    
                    log.debug("连接池状态 - 活跃: {}, 总计: {}, 空闲: {}, 等待: {}", 
                             activeConnections, totalConnections, idleConnections, threadsAwaitingConnection);
                             
                } catch (Exception e) {
                    log.error("连接池监控失败", e);
                }
            }, 30, 30, TimeUnit.SECONDS);
            
            log.info("HikariCP连接池监控已启动，监控间隔: 30秒");
        }
    }

    /**
     * 启动定期性能报告
     */
    private void startPerformanceReporting() {
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                generatePerformanceReport();
            } catch (Exception e) {
                log.error("生成性能报告失败", e);
            }
        }, 5, 5, TimeUnit.MINUTES);
        
        log.info("数据库性能报告已启动，报告间隔: 5分钟");
    }

    /**
     * 生成性能报告
     */
    private void generatePerformanceReport() {
        StringBuilder report = new StringBuilder("\n=== 数据库性能报告 ===\n");
        
        try {
            // Hibernate统计信息
            SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
            Statistics stats = sessionFactory.getStatistics();
            
            if (stats.isStatisticsEnabled()) {
                report.append("Hibernate统计信息:\n");
                report.append("  查询执行次数: ").append(stats.getQueryExecutionCount()).append("\n");
                report.append("  查询缓存命中次数: ").append(stats.getQueryCacheHitCount()).append("\n");
                report.append("  查询缓存未命中次数: ").append(stats.getQueryCacheMissCount()).append("\n");
                report.append("  二级缓存命中次数: ").append(stats.getSecondLevelCacheHitCount()).append("\n");
                report.append("  二级缓存未命中次数: ").append(stats.getSecondLevelCacheMissCount()).append("\n");
                report.append("  事务次数: ").append(stats.getTransactionCount()).append("\n");
                report.append("  成功事务次数: ").append(stats.getSuccessfulTransactionCount()).append("\n");
                
                // 计算缓存命中率
                long totalQueryCache = stats.getQueryCacheHitCount() + stats.getQueryCacheMissCount();
                if (totalQueryCache > 0) {
                    double hitRate = (double) stats.getQueryCacheHitCount() / totalQueryCache * 100;
                    report.append("  查询缓存命中率: ").append(String.format("%.1f%%", hitRate)).append("\n");
                }
                
                long totalSecondLevel = stats.getSecondLevelCacheHitCount() + stats.getSecondLevelCacheMissCount();
                if (totalSecondLevel > 0) {
                    double hitRate = (double) stats.getSecondLevelCacheHitCount() / totalSecondLevel * 100;
                    report.append("  二级缓存命中率: ").append(String.format("%.1f%%", hitRate)).append("\n");
                }
            }
            
            // 连接池信息
            if (dataSource instanceof HikariDataSource) {
                HikariDataSource hikariDataSource = (HikariDataSource) dataSource;
                HikariPoolMXBean poolMXBean = hikariDataSource.getHikariPoolMXBean();
                report.append("HikariCP连接池信息:\n");
                report.append("  活跃连接: ").append(poolMXBean.getActiveConnections()).append("\n");
                report.append("  总连接数: ").append(poolMXBean.getTotalConnections()).append("\n");
                report.append("  空闲连接: ").append(poolMXBean.getIdleConnections()).append("\n");
                report.append("  等待连接的线程: ").append(poolMXBean.getThreadsAwaitingConnection()).append("\n");
                report.append("  最大池大小: ").append(hikariDataSource.getMaximumPoolSize()).append("\n");
            }
            
            report.append("======================\n");
            
            log.info(report.toString());
            
        } catch (Exception e) {
            log.error("生成性能报告时出错", e);
        }
    }

    /**
     * 应用关闭时清理资源
     */
    public void destroy() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            try {
                if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
                    scheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
            log.info("性能监控线程池已关闭");
        }
    }
} 