use crate::app_state::AppState;
use crate::data::models::ai_classification::{
    AiClassification, CreateAiClassificationRequest, UpdateAiClassificationRequest,
    AiClassificationQuery, AiClassificationPreview
};
use crate::data::repositories::ai_classification_repository::AiClassificationRepository;
use crate::business::services::ai_classification_service::AiClassificationService;
use anyhow::Result;
use std::sync::Arc;
use tauri::State;

/// 创建AI分类
/// 遵循 Tauri 开发规范的命令接口设计
#[tauri::command]
pub async fn create_ai_classification(
    request: CreateAiClassificationRequest,
    state: State<'_, AppState>,
) -> Result<AiClassification, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.create_classification(request)
        .await
        .map_err(|e| e.to_string())
}

/// 获取所有AI分类
#[tauri::command]
pub async fn get_all_ai_classifications(
    query: Option<AiClassificationQuery>,
    state: State<'_, AppState>,
) -> Result<Vec<AiClassification>, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.get_classifications(query)
        .await
        .map_err(|e| e.to_string())
}

/// 根据ID获取AI分类
#[tauri::command]
pub async fn get_ai_classification_by_id(
    id: String,
    state: State<'_, AppState>,
) -> Result<Option<AiClassification>, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.get_classification_by_id(&id)
        .await
        .map_err(|e| e.to_string())
}

/// 更新AI分类
#[tauri::command]
pub async fn update_ai_classification(
    id: String,
    request: UpdateAiClassificationRequest,
    state: State<'_, AppState>,
) -> Result<Option<AiClassification>, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.update_classification(&id, request)
        .await
        .map_err(|e| e.to_string())
}

/// 删除AI分类
#[tauri::command]
pub async fn delete_ai_classification(
    id: String,
    state: State<'_, AppState>,
) -> Result<bool, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.delete_classification(&id)
        .await
        .map_err(|e| e.to_string())
}

/// 获取AI分类总数
#[tauri::command]
pub async fn get_ai_classification_count(
    active_only: Option<bool>,
    state: State<'_, AppState>,
) -> Result<i64, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.get_classification_count(active_only)
        .await
        .map_err(|e| e.to_string())
}

/// 生成AI分类预览
#[tauri::command]
pub async fn generate_ai_classification_preview(
    state: State<'_, AppState>,
) -> Result<AiClassificationPreview, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

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

/// 批量更新分类排序
#[tauri::command]
pub async fn update_ai_classification_sort_orders(
    updates: Vec<(String, i32)>,
    state: State<'_, AppState>,
) -> Result<Vec<AiClassification>, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.update_sort_orders(updates)
        .await
        .map_err(|e| e.to_string())
}

/// 切换分类激活状态
#[tauri::command]
pub async fn toggle_ai_classification_status(
    id: String,
    state: State<'_, AppState>,
) -> Result<Option<AiClassification>, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));
    let service = AiClassificationService::new(repository);

    service.toggle_classification_status(&id)
        .await
        .map_err(|e| e.to_string())
}

/// 验证分类名称是否可用
#[tauri::command]
pub async fn validate_ai_classification_name(
    name: String,
    exclude_id: Option<String>,
    state: State<'_, AppState>,
) -> Result<bool, String> {
    let database = state.get_database();
    let repository = Arc::new(AiClassificationRepository::new(database));

    let exists = repository.exists_by_name(&name, exclude_id.as_deref())
        .await
        .map_err(|e| e.to_string())?;

    Ok(!exists) // 返回名称是否可用（不存在则可用）
}

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

    async fn create_test_service() -> AiClassificationService {
        let database = Arc::new(Database::new_with_path(":memory:").unwrap());
        let repository = Arc::new(AiClassificationRepository::new(database));
        AiClassificationService::new(repository)
    }

    #[tokio::test]
    async fn test_create_ai_classification_service() {
        let service = create_test_service().await;

        let request = CreateAiClassificationRequest {
            name: "全身".to_string(),
            prompt_text: "头顶到脚底完整入镜，肢体可见度≥90%".to_string(),
            description: Some("全身分类描述".to_string()),
            sort_order: Some(1),
        };

        let result = service.create_classification(request).await;
        assert!(result.is_ok());

        let classification = result.unwrap();
        assert_eq!(classification.name, "全身");
        assert!(classification.is_active);
    }

    #[tokio::test]
    async fn test_get_all_ai_classifications_service() {
        let service = create_test_service().await;

        // 先创建一个分类
        let request = CreateAiClassificationRequest {
            name: "上半身".to_string(),
            prompt_text: "头部到腰部".to_string(),
            description: None,
            sort_order: Some(1),
        };

        let _ = service.create_classification(request).await.unwrap();

        // 获取所有分类
        let result = service.get_classifications(None).await;
        assert!(result.is_ok());

        let classifications = result.unwrap();
        assert_eq!(classifications.len(), 1);
        assert_eq!(classifications[0].name, "上半身");
    }

    #[tokio::test]
    async fn test_generate_preview_service() {
        let service = create_test_service().await;

        // 创建几个测试分类
        let requests = vec![
            CreateAiClassificationRequest {
                name: "全身".to_string(),
                prompt_text: "头顶到脚底完整入镜".to_string(),
                description: None,
                sort_order: Some(1),
            },
            CreateAiClassificationRequest {
                name: "上半身".to_string(),
                prompt_text: "头部到腰部".to_string(),
                description: None,
                sort_order: Some(2),
            },
        ];

        for request in requests {
            let _ = service.create_classification(request).await.unwrap();
        }

        let result = service.generate_preview().await;
        assert!(result.is_ok());

        let preview = result.unwrap();
        assert_eq!(preview.classifications.len(), 2);
        assert!(preview.full_prompt.contains("全身"));
        assert!(preview.full_prompt.contains("上半身"));
    }

    #[tokio::test]
    async fn test_validate_name_service() {
        let service = create_test_service().await;

        // 创建一个分类
        let request = CreateAiClassificationRequest {
            name: "全身".to_string(),
            prompt_text: "头顶到脚底完整入镜".to_string(),
            description: None,
            sort_order: Some(1),
        };

        let _classification = service.create_classification(request).await.unwrap();

        // 验证重复名称应该失败
        let duplicate_request = CreateAiClassificationRequest {
            name: "全身".to_string(),
            prompt_text: "另一个全身描述".to_string(),
            description: None,
            sort_order: Some(2),
        };

        let result = service.create_classification(duplicate_request).await;
        assert!(result.is_err()); // 应该失败，因为名称重复
    }
}
