use rusqlite::Connection;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use anyhow::{Result, anyhow};
use std::ops::{Deref, DerefMut};

use crate::infrastructure::connection_pool::{ConnectionPool, ConnectionPoolConfig, PooledConnectionHandle};

mod migrations;
use migrations::MigrationManager;

/// 数据库健康状态
#[derive(Debug, Clone)]
pub struct DatabaseHealthStatus {
    /// 整体健康状态
    pub overall_healthy: bool,
    /// 当前数据库版本
    pub current_version: u32,
    /// 最新版本
    pub latest_version: u32,
    /// 版本是否最新
    pub version_up_to_date: bool,
    /// 连接状态描述
    pub connection_status: String,
    /// 连接是否健康
    pub connection_healthy: bool,
    /// 表结构是否完整
    pub tables_complete: bool,
    /// 缺失的表
    pub missing_tables: Vec<String>,
    /// 迁移是否健康
    pub migrations_healthy: bool,
    /// 失败的迁移
    pub failed_migrations: Vec<String>,
}

/// 统一的数据库连接句柄
/// 可以是单连接模式的 MutexGuard 或连接池模式的 PooledConnectionHandle
pub enum ConnectionHandle<'a> {
    /// 单连接模式（兼容模式）
    Single(std::sync::MutexGuard<'a, Connection>),
    /// 连接池模式（推荐）
    Pooled(PooledConnectionHandle),
}

impl<'a> Deref for ConnectionHandle<'a> {
    type Target = Connection;

    fn deref(&self) -> &Self::Target {
        match self {
            ConnectionHandle::Single(conn) => conn,
            ConnectionHandle::Pooled(conn) => conn.as_ref(),
        }
    }
}

impl<'a> DerefMut for ConnectionHandle<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            ConnectionHandle::Single(conn) => conn,
            ConnectionHandle::Pooled(conn) => conn.as_mut(),
        }
    }
}

/// 数据库管理器
/// 遵循 Tauri 开发规范的数据库设计模式
/// 支持连接池以提高并发性能，实现读写分离
pub struct Database {
    // 主连接（用于写操作和复杂事务）
    connection: Arc<Mutex<Connection>>,
    // 只读连接（专门用于读操作，避免锁竞争）
    read_connection: Arc<Mutex<Connection>>,
    // 连接池支持
    pool: Option<Arc<ConnectionPool>>,
}

/// 数据库连接模式
#[derive(Debug, Clone)]
pub enum ConnectionMode {
    /// 单连接模式（兼容模式）
    Single,
    /// 连接池模式（推荐）
    Pool(ConnectionPoolConfig),
}

impl Database {
    /// 创建新的数据库实例
    /// 遵循安全第一原则，确保数据库文件的安全存储
    pub fn new() -> Result<Self> {
        let app_data_dir = dirs::data_dir()
            .ok_or_else(|| anyhow!("无法获取应用数据目录"))?
            .join("mixvideo");

        std::fs::create_dir_all(&app_data_dir)?;
        let db_path = app_data_dir.join("mixvideoV2.db");

        Self::new_with_path(db_path.to_str().unwrap())
    }

    /// 创建带连接池的数据库实例（推荐用于生产环境）
    pub fn new_with_pool() -> Result<Self> {
        let app_data_dir = dirs::data_dir()
            .ok_or_else(|| anyhow!("无法获取应用数据目录"))?
            .join("mixvideo");

        std::fs::create_dir_all(&app_data_dir)?;
        let db_path = app_data_dir.join("mixvideoV2.db");

        // 检查数据库是否被锁定
        if let Err(e) = Self::check_database_lock(&db_path) {
            eprintln!("数据库锁检查失败: {}", e);
            // 尝试清理锁文件
            Self::cleanup_database_locks(&db_path)?;
        }

        Self::new_with_path_and_pool(db_path.to_str().unwrap(), Some(ConnectionPoolConfig::default()))
    }

    /// 检查数据库锁状态
    fn check_database_lock(db_path: &PathBuf) -> Result<()> {
        // 检查 WAL 和 SHM 文件
        let wal_path = db_path.with_extension("db-wal");
        let shm_path = db_path.with_extension("db-shm");

        if wal_path.exists() || shm_path.exists() {
            println!("检测到 WAL/SHM 文件，数据库可能正在被其他进程使用");
        }

        // 尝试打开数据库进行快速检查
        match Connection::open(db_path) {
            Ok(conn) => {
                // 尝试执行一个简单的查询
                match conn.execute("SELECT 1", []) {
                    Ok(_) => {
                        println!("数据库连接检查通过");
                        Ok(())
                    },
                    Err(e) => Err(anyhow!("数据库查询失败: {}", e))
                }
            },
            Err(e) => Err(anyhow!("无法打开数据库: {}", e))
        }
    }

    /// 清理数据库锁文件
    fn cleanup_database_locks(db_path: &PathBuf) -> Result<()> {
        let wal_path = db_path.with_extension("db-wal");
        let shm_path = db_path.with_extension("db-shm");

        if wal_path.exists() {
            println!("清理 WAL 文件: {:?}", wal_path);
            std::fs::remove_file(&wal_path).ok(); // 忽略错误
        }

        if shm_path.exists() {
            println!("清理 SHM 文件: {:?}", shm_path);
            std::fs::remove_file(&shm_path).ok(); // 忽略错误
        }

        Ok(())
    }

    /// 使用指定路径创建数据库实例（主要用于测试）
    pub fn new_with_path(db_path: &str) -> Result<Self> {
        Self::new_with_path_and_pool(db_path, None)
    }

    /// 使用指定路径和连接池配置创建数据库实例
    pub fn new_with_path_and_pool(db_path: &str, pool_config: Option<ConnectionPoolConfig>) -> Result<Self> {
        let db_path = std::path::PathBuf::from(db_path);

        // 打印数据库路径用于调试
        println!("Initializing database at: {}", db_path.display());

        // 确保数据库目录存在
        if let Some(parent) = db_path.parent() {
            std::fs::create_dir_all(parent).map_err(|e| {
                eprintln!("Failed to create database directory: {}", e);
                rusqlite::Error::SqliteFailure(
                    rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_CANTOPEN),
                    Some(format!("Failed to create database directory: {}", e)),
                )
            })?;
        }

        let connection = Connection::open(&db_path)?;
        println!("Database connection established successfully");

        // 遵循 Tauri 开发规范的安全第一原则
        // 设置数据库安全配置
        connection.pragma_update(None, "secure_delete", "ON")?;
        connection.pragma_update(None, "temp_store", "MEMORY")?;

        // 配置数据库设置
        connection.pragma_update(None, "foreign_keys", "ON")?;
        connection.pragma_update(None, "journal_mode", "WAL")?; // 使用 WAL 模式以支持并发访问
        connection.pragma_update(None, "synchronous", "NORMAL")?; // 使用 NORMAL 以提高性能
        connection.pragma_update(None, "cache_size", "10000")?; // 增加缓存大小
        connection.pragma_update(None, "busy_timeout", "5000")?; // 设置忙等待超时为5秒

        println!("Database pragmas configured");
        
        // 🚨 强制启用连接池以避免死锁问题
        let pool = if let Some(config) = pool_config {
            println!("Initializing connection pool with min={}, max={} connections",
                     config.min_connections, config.max_connections);

            let pool = ConnectionPool::new(db_path.to_string_lossy().to_string(), config)?;
            println!("Connection pool initialized successfully");
            Some(pool)
        } else {
            println!("🚨 强制启用默认连接池配置以避免死锁");
            let default_config = ConnectionPoolConfig {
                max_connections: 5,         // 减少最大连接数，SQLite不适合太多并发
                min_connections: 2,         // 减少最小连接数
                connection_timeout: Duration::from_secs(30), // 连接超时
                acquire_timeout: Duration::from_secs(10), // 减少获取超时，快速失败
                idle_timeout: Duration::from_secs(300),   // 5分钟空闲超时
            };

            let pool = ConnectionPool::new(db_path.to_string_lossy().to_string(), default_config)?;
            println!("✅ 默认连接池初始化成功");
            Some(pool)
        };

        // 创建专用的只读连接
        let read_connection = Connection::open(&db_path)?;
        read_connection.pragma_update(None, "secure_delete", "ON")?;
        read_connection.pragma_update(None, "temp_store", "MEMORY")?;
        read_connection.pragma_update(None, "foreign_keys", "ON")?;
        read_connection.pragma_update(None, "journal_mode", "WAL")?;
        read_connection.pragma_update(None, "synchronous", "NORMAL")?;
        read_connection.pragma_update(None, "cache_size", "10000")?;
        read_connection.pragma_update(None, "busy_timeout", "5000")?;
        // 只读连接设置为只读模式
        read_connection.pragma_update(None, "query_only", "ON")?;

        println!("只读数据库连接创建成功");

        let database = Database {
            connection: Arc::new(Mutex::new(connection)),
            read_connection: Arc::new(Mutex::new(read_connection)),
            pool,
        };
        
        // 运行数据库迁移（包含表初始化）
        database.run_migrations()?;
        
        Ok(database)
    }

    /// 获取数据库连接（用于写操作）
    pub fn get_connection(&self) -> Arc<Mutex<Connection>> {
        Arc::clone(&self.connection)
    }

    /// 获取只读数据库连接（用于读操作）
    /// 这个连接专门用于查询操作，避免与写操作竞争锁
    pub fn get_read_connection(&self) -> Arc<Mutex<Connection>> {
        Arc::clone(&self.read_connection)
    }

    /// 检查数据库连接状态
    pub fn check_connection_status(&self) -> String {
        match self.connection.try_lock() {
            Ok(_) => "连接可用".to_string(),
            Err(std::sync::TryLockError::Poisoned(_)) => "连接已损坏".to_string(),
            Err(std::sync::TryLockError::WouldBlock) => "连接被占用".to_string(),
        }
    }

    /// 尝试非阻塞获取数据库连接（写连接）
    /// 如果连接被占用，立即返回 None
    pub fn try_get_connection(&self) -> Option<std::sync::MutexGuard<Connection>> {
        match self.connection.try_lock() {
            Ok(conn) => Some(conn),
            Err(_) => None,
        }
    }

    /// 尝试非阻塞获取只读数据库连接
    /// 如果连接被占用，立即返回 None
    pub fn try_get_read_connection(&self) -> Option<std::sync::MutexGuard<Connection>> {
        match self.read_connection.try_lock() {
            Ok(conn) => Some(conn),
            Err(_) => None,
        }
    }

    /// 获取最佳的只读连接
    /// 优先使用专用只读连接，如果不可用则尝试主连接
    pub fn get_best_read_connection(&self) -> Result<ConnectionHandle> {
        // 首先尝试专用只读连接
        match self.read_connection.try_lock() {
            Ok(conn) => {
                return Ok(ConnectionHandle::Single(conn));
            },
            Err(_) => {
                println!("只读连接被占用，尝试连接池");
            }
        }

        // 如果只读连接被占用，尝试连接池
        if let Some(pool) = &self.pool {
            match pool.try_acquire()? {
                Some(conn) => {
                    println!("使用连接池连接进行读操作");
                    return Ok(ConnectionHandle::Pooled(conn));
                },
                None => {
                    println!("连接池无可用连接，尝试主连接");
                }
            }
        }

        // 最后尝试主连接（非阻塞）
        match self.connection.try_lock() {
            Ok(conn) => {
                println!("使用主连接进行读操作");
                Ok(ConnectionHandle::Single(conn))
            },
            Err(_) => {
                println!("所有连接都被占用，读操作失败");
                Err(anyhow!("所有数据库连接都被占用"))
            }
        }
    }

    /// 检查是否启用了连接池
    pub fn has_pool(&self) -> bool {
        self.pool.is_some()
    }

    /// 从连接池获取连接（推荐）
    /// 如果连接池未启用，返回错误
    pub fn acquire_from_pool(&self) -> Result<PooledConnectionHandle> {
        match &self.pool {
            Some(pool) => pool.acquire().map_err(|e| anyhow!("获取连接池连接失败: {}", e)),
            None => Err(anyhow!("连接池未启用")),
        }
    }

    /// 尝试从连接池获取连接（非阻塞）
    /// 如果连接池未启用或无可用连接，返回 None
    pub fn try_acquire_from_pool(&self) -> Result<Option<PooledConnectionHandle>> {
        match &self.pool {
            Some(pool) => pool.try_acquire().map_err(|e| anyhow!("尝试获取连接池连接失败: {}", e)),
            None => Ok(None),
        }
    }

    /// 获取连接（自动选择最佳方式）
    /// 如果连接池可用，优先使用连接池
    /// 否则使用单连接模式
    pub fn get_best_connection(&self) -> Result<ConnectionHandle> {
        if let Some(pool) = &self.pool {
            // 优先使用连接池
            match pool.try_acquire()? {
                Some(conn) => return Ok(ConnectionHandle::Pooled(conn)),
                None => {
                    // 连接池中没有可用连接，尝试获取主连接
                    println!("连接池中没有可用连接，尝试获取主连接");
                }
            }
        }

        // 回退到单连接模式
        match self.connection.try_lock() {
            Ok(conn) => Ok(ConnectionHandle::Single(conn)),
            Err(_) => Err(anyhow!("所有数据库连接都被占用")),
        }
    }

    /// 执行数据库操作的辅助方法，自动处理锁的获取和释放
    /// 这是推荐的数据库访问方式，可以避免锁竞争问题
    pub fn with_connection<T, F>(&self, operation: F) -> Result<T, rusqlite::Error>
    where
        F: FnOnce(&Connection) -> Result<T, rusqlite::Error>,
    {
        // 直接使用 connection 字段，避免额外的 Arc::clone
        match self.connection.try_lock() {
            Ok(conn) => {
                // 成功获取锁，执行操作
                operation(&*conn)
            },
            Err(_) => {
                // 锁被占用，等待一小段时间后重试
                std::thread::sleep(std::time::Duration::from_millis(10));

                // 使用阻塞方式获取锁，但有错误处理
                let conn = self.connection.lock().map_err(|e| {
                    eprintln!("数据库连接锁获取失败: {}", e);
                    rusqlite::Error::SqliteFailure(
                        rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_BUSY),
                        Some("数据库连接被锁定".to_string()),
                    )
                })?;

                operation(&*conn)
            }
        }
    }

    /// 执行只读查询的辅助方法
    pub fn query<T, F>(&self, operation: F) -> Result<T, rusqlite::Error>
    where
        F: FnOnce(&Connection) -> Result<T, rusqlite::Error>,
    {
        self.with_connection(operation)
    }

    /// 执行写入操作的辅助方法
    pub fn execute<T, F>(&self, operation: F) -> Result<T, rusqlite::Error>
    where
        F: FnOnce(&Connection) -> Result<T, rusqlite::Error>,
    {
        self.with_connection(operation)
    }

    /// 运行数据库迁移
    /// 使用新的迁移管理系统，遵循最佳实践
    pub fn run_migrations(&self) -> Result<()> {
        let conn = self.connection.lock().unwrap();

        println!("开始数据库迁移检查...");

        // 创建迁移管理器
        let migration_manager = MigrationManager::new();

        // 获取当前版本和最新版本
        let current_version = migration_manager.get_current_version(&conn)?;
        let latest_version = migration_manager.get_latest_version();

        println!("当前数据库版本: v{}", current_version);
        println!("最新数据库版本: v{}", latest_version);

        // 执行迁移
        migration_manager.migrate(&conn)?;

        println!("数据库迁移系统完成");
        Ok(())
    }

    /// 检查数据库健康状态
    /// 包括版本检查、连接状态、表完整性等
    pub fn check_database_health(&self) -> Result<DatabaseHealthStatus> {
        let migration_manager = MigrationManager::new();

        // 检查版本信息（在单独的作用域中获取连接）
        let (current_version, latest_version) = {
            let conn = self.connection.lock().unwrap();
            let current_version = migration_manager.get_current_version(&conn)?;
            let latest_version = migration_manager.get_latest_version();
            (current_version, latest_version)
        };
        let version_up_to_date = current_version == latest_version;

        // 检查连接状态（连接已释放，现在可以安全检查）
        let connection_status = self.check_connection_status();
        let connection_healthy = connection_status == "连接可用";

        // 检查关键表是否存在（在单独的作用域中获取连接）
        let (missing_tables, migration_history) = {
            let conn = self.connection.lock().unwrap();

            let required_tables = vec![
                "projects", "materials", "material_segments", "models",
                "ai_classifications", "templates", "template_materials",
                "tracks", "track_segments", "video_classification_records",
                "schema_migrations"
            ];

            let mut missing_tables = Vec::new();
            for table in &required_tables {
                let table_exists: bool = conn.query_row(
                    "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?1",
                    [table],
                    |row| row.get::<_, i32>(0)
                ).unwrap_or(0) > 0;

                if !table_exists {
                    missing_tables.push(table.to_string());
                }
            }

            // 获取迁移历史
            let migration_history = migration_manager.get_migration_history(&conn)?;

            (missing_tables, migration_history)
        };

        let tables_complete = missing_tables.is_empty();
        let failed_migrations: Vec<_> = migration_history.iter()
            .filter(|(_, _, _, success)| !success)
            .map(|(version, description, _, _)| format!("v{}: {}", version, description))
            .collect();

        let migrations_healthy = failed_migrations.is_empty();

        Ok(DatabaseHealthStatus {
            overall_healthy: version_up_to_date && connection_healthy && tables_complete && migrations_healthy,
            current_version,
            latest_version,
            version_up_to_date,
            connection_status,
            connection_healthy,
            tables_complete,
            missing_tables,
            migrations_healthy,
            failed_migrations,
        })
    }

    /// 获取数据库版本信息
    /// 提供给外部调用，用于调试和监控
    pub fn get_database_version_info(&self) -> Result<(u32, u32)> {
        let conn = self.connection.lock().unwrap();
        let migration_manager = MigrationManager::new();

        let current_version = migration_manager.get_current_version(&conn)?;
        let latest_version = migration_manager.get_latest_version();

        Ok((current_version, latest_version))
    }

    /// 获取迁移历史
    /// 提供给外部调用，用于调试和监控
    pub fn get_migration_history(&self) -> Result<Vec<(u32, String, String, bool)>> {
        let conn = self.connection.lock().unwrap();
        let migration_manager = MigrationManager::new();

        migration_manager.get_migration_history(&conn)
    }

    /// 手动执行迁移到指定版本
    /// 仅用于开发和调试，生产环境应使用自动迁移
    #[allow(dead_code)]
    pub fn migrate_to_version(&self, target_version: u32) -> Result<()> {
        let conn = self.connection.lock().unwrap();
        let migration_manager = MigrationManager::new();

        let current_version = migration_manager.get_current_version(&conn)?;

        if target_version > current_version {
            // 向前迁移
            migration_manager.migrate(&conn)
        } else if target_version < current_version {
            // 回滚迁移
            migration_manager.rollback_to(&conn, target_version)
        } else {
            println!("数据库已是目标版本 v{}", target_version);
            Ok(())
        }
    }

    /// 执行SQL查询（仅用于测试）
    #[cfg(test)]
    pub fn execute_sql_simple(&self, sql: &str) -> Result<usize> {
        let conn = self.connection.lock().unwrap();
        let result = conn.execute(sql, [])?;
        Ok(result)
    }

    /// 准备SQL语句（仅用于测试）
    #[cfg(test)]
    pub fn prepare_sql(&self, sql: &str) -> Result<bool> {
        let conn = self.connection.lock().unwrap();
        let x = match conn.prepare(sql) {
            Ok(_) => Ok(true),
            Err(_) => Ok(false),
        };
        x
    }

    /// 获取数据库文件路径
    /// 遵循安全存储原则，将数据库存储在应用数据目录
    fn get_database_path() -> PathBuf {
        // 优先使用应用数据目录
        if let Some(data_dir) = dirs::data_dir() {
            let app_dir = data_dir.join("mixvideo");
            // 确保目录存在
            if let Err(e) = std::fs::create_dir_all(&app_dir) {
                eprintln!("Failed to create app data directory: {}", e);
                // 如果创建失败，使用当前目录
                return PathBuf::from("mixvideoV2.db");
            }
            app_dir.join("mixvideoV2.db")
        } else {
            // 备用方案：使用当前目录
            PathBuf::from("mixvideoV2.db")
        }
    }

    /// 获取数据库路径的调试信息
    pub fn get_database_path_info() -> String {
        let path = Self::get_database_path();
        format!("Database path: {}", path.display())
    }
}
