use crate::app_state::AppState;
use crate::data::models::video_classification::*;
use crate::data::repositories::video_classification_repository::VideoClassificationRepository;
use crate::data::repositories::ai_classification_repository::AiClassificationRepository;
use crate::data::repositories::material_repository::MaterialRepository;
use crate::business::services::video_classification_service::VideoClassificationService;
use crate::business::services::video_classification_queue::{VideoClassificationQueue, QueueStats, TaskProgress};
use crate::infrastructure::gemini_service::GeminiConfig;
use anyhow::Result;
use std::sync::Arc;
use tauri::{command, State};

use std::collections::HashMap;

/// 全局队列实例
static QUEUE_INSTANCE: tokio::sync::OnceCell<Arc<VideoClassificationQueue>> = tokio::sync::OnceCell::const_new();

/// 获取或创建队列实例
async fn get_queue_instance(state: &AppState) -> Arc<VideoClassificationQueue> {
    QUEUE_INSTANCE.get_or_init(|| async {
        let database = state.get_database();

        let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
        let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
        let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());
        
        let gemini_config = Some(GeminiConfig::default());
        let service = Arc::new(VideoClassificationService::new(
            video_repo,
            ai_classification_repo,
            material_repo,
            gemini_config,
        ));
        
        Arc::new(VideoClassificationQueue::new(service))
    }).await.clone()
}

/// 启动AI视频分类
/// 遵循 Tauri 开发规范的命令接口设计
#[command]
pub async fn start_video_classification(
    request: BatchClassificationRequest,
    state: State<'_, AppState>,
) -> Result<Vec<String>, String> {
    let queue = get_queue_instance(&state).await;
    
    // 添加任务到队列
    let task_ids = queue.add_batch_tasks(request)
        .await
        .map_err(|e| e.to_string())?;
    
    // 启动队列（如果尚未启动）
    if let Err(e) = queue.start().await {
        // 如果队列已经在运行，忽略错误
        if !e.to_string().contains("已经在运行中") {
            return Err(e.to_string());
        }
    }
    
    Ok(task_ids)
}

/// 启动项目一键AI视频分类
/// 遍历项目下所有符合条件的素材并添加到分类队列
#[command]
pub async fn start_project_batch_classification(
    request: ProjectBatchClassificationRequest,
    state: State<'_, AppState>,
) -> Result<ProjectBatchClassificationResponse, String> {
    let queue = get_queue_instance(&state).await;

    // 创建项目批量分类任务
    let response = queue.service.create_project_batch_classification_tasks(request)
        .await
        .map_err(|e| e.to_string())?;

    // 启动队列（如果尚未启动）
    if let Err(e) = queue.start().await {
        // 如果队列已经在运行，忽略错误
        if !e.to_string().contains("已经在运行中") {
            return Err(e.to_string());
        }
    }

    Ok(response)
}

/// 获取分类队列状态
#[command]
pub async fn get_classification_queue_status(
    state: State<'_, AppState>,
) -> Result<QueueStats, String> {
    let queue = get_queue_instance(&state).await;
    Ok(queue.get_stats().await)
}

/// 获取项目的分类队列状态
#[command]
pub async fn get_project_classification_queue_status(
    project_id: String,
    state: State<'_, AppState>,
) -> Result<QueueStats, String> {
    let queue = get_queue_instance(&state).await;
    queue.get_project_stats(&project_id).await.map_err(|e| e.to_string())
}

/// 获取任务进度
#[command]
pub async fn get_classification_task_progress(
    task_id: String,
    state: State<'_, AppState>,
) -> Result<Option<TaskProgress>, String> {
    let queue = get_queue_instance(&state).await;
    Ok(queue.get_task_progress(&task_id).await)
}

/// 获取所有任务进度
#[command]
pub async fn get_all_classification_task_progress(
    state: State<'_, AppState>,
) -> Result<HashMap<String, TaskProgress>, String> {
    let queue = get_queue_instance(&state).await;
    Ok(queue.get_all_task_progress().await)
}

/// 获取项目的任务进度
#[command]
pub async fn get_project_classification_task_progress(
    project_id: String,
    state: State<'_, AppState>,
) -> Result<HashMap<String, TaskProgress>, String> {
    let queue = get_queue_instance(&state).await;
    Ok(queue.get_project_task_progress(&project_id).await)
}

/// 停止分类队列
#[command]
pub async fn stop_classification_queue(
    state: State<'_, AppState>,
) -> Result<(), String> {
    let queue = get_queue_instance(&state).await;
    queue.stop().await.map_err(|e| e.to_string())
}

/// 恢复卡住的任务状态
#[command]
pub async fn recover_stuck_classification_tasks(
    state: State<'_, AppState>,
) -> Result<usize, String> {
    let database = state.get_database();
    let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
    let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
    let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());

    let service = VideoClassificationService::new(
        video_repo,
        ai_classification_repo,
        material_repo,
        Some(GeminiConfig::default()),
    );

    service.recover_stuck_tasks()
        .await
        .map_err(|e| e.to_string())
}

/// 暂停分类队列
#[command]
pub async fn pause_classification_queue(
    state: State<'_, AppState>,
) -> Result<(), String> {
    let queue = get_queue_instance(&state).await;
    queue.pause().await.map_err(|e| e.to_string())
}

/// 恢复分类队列
#[command]
pub async fn resume_classification_queue(
    state: State<'_, AppState>,
) -> Result<(), String> {
    let queue = get_queue_instance(&state).await;
    queue.resume().await.map_err(|e| e.to_string())
}

/// 获取素材的分类记录
#[command]
pub async fn get_material_classification_records(
    material_id: String,
    state: State<'_, AppState>,
) -> Result<Vec<VideoClassificationRecord>, String> {
    let database = state.get_database();
    let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
    let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
    let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());
    
    let service = VideoClassificationService::new(
        video_repo,
        ai_classification_repo,
        material_repo,
        Some(GeminiConfig::default()),
    );
    
    service.get_classifications_by_material(&material_id)
        .await
        .map_err(|e| e.to_string())
}

/// 获取分类统计信息
#[command]
pub async fn get_classification_statistics(
    project_id: Option<String>,
    state: State<'_, AppState>,
) -> Result<ClassificationStats, String> {
    let database = state.get_database();
    let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
    let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
    let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());
    
    let service = VideoClassificationService::new(
        video_repo,
        ai_classification_repo,
        material_repo,
        Some(GeminiConfig::default()),
    );
    
    service.get_classification_stats(project_id.as_deref())
        .await
        .map_err(|e| e.to_string())
}

/// 检查片段是否已分类
#[command]
pub async fn is_segment_classified(
    segment_id: String,
    state: State<'_, AppState>,
) -> Result<bool, String> {
    let database = state.get_database();
    let video_repo = VideoClassificationRepository::new(database);
    
    video_repo.is_segment_classified(&segment_id)
        .await
        .map_err(|e| e.to_string())
}

/// 取消分类任务
#[command]
pub async fn cancel_classification_task(
    task_id: String,
    state: State<'_, AppState>,
) -> Result<(), String> {
    let database = state.get_database();
    let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
    let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
    let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());
    
    let service = VideoClassificationService::new(
        video_repo,
        ai_classification_repo,
        material_repo,
        Some(GeminiConfig::default()),
    );
    
    service.cancel_task(&task_id)
        .await
        .map_err(|e| e.to_string())
}

/// 重试失败的分类任务
#[command]
pub async fn retry_classification_task(
    task_id: String,
    state: State<'_, AppState>,
) -> Result<(), String> {
    let database = state.get_database();
    let video_repo = Arc::new(VideoClassificationRepository::new(database.clone()));
    let ai_classification_repo = Arc::new(AiClassificationRepository::new(database.clone()));
    let material_repo = Arc::new(MaterialRepository::new(database.clone()).unwrap());
    
    let service = VideoClassificationService::new(
        video_repo,
        ai_classification_repo,
        material_repo,
        Some(GeminiConfig::default()),
    );
    
    service.retry_failed_task(&task_id)
        .await
        .map_err(|e| e.to_string())
}

/// 测试Gemini连接
#[command]
pub async fn test_gemini_connection() -> Result<String, String> {
    use crate::infrastructure::gemini_service::GeminiService;
    
    let _service = GeminiService::new(Some(GeminiConfig::default()))
        .map_err(|e| format!("Failed to create GeminiService: {}", e))?;
    
    // 尝试获取访问令牌来测试连接
    // 注意：这里需要实现一个公开的测试方法
    Ok("Gemini连接测试功能待实现".to_string())
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::infrastructure::database::Database;

    async fn create_test_state() -> AppState {
        let database = Arc::new(Database::new().unwrap());
        AppState::new_with_database(database)
    }

    #[tokio::test]
    async fn test_get_queue_instance() {
        let state = create_test_state().await;
        let queue1 = get_queue_instance(&state).await;
        let queue2 = get_queue_instance(&state).await;
        
        // 应该返回同一个实例
        assert!(Arc::ptr_eq(&queue1, &queue2));
    }
}
