use crate::business::services::directory_settings_service::DirectorySettingsService;
use crate::config::{DirectorySettings, DirectorySettingType};
use serde::{Deserialize, Serialize};
use tauri::command;
use tracing::{info, warn, error};

/// 目录设置响应结构
#[derive(Debug, Serialize, Deserialize)]
pub struct DirectorySettingsResponse {
    pub material_import_directory: Option<String>,
    pub template_import_directory: Option<String>,
    pub jianying_export_directory: Option<String>,
    pub project_export_directory: Option<String>,
    pub thumbnail_export_directory: Option<String>,
    pub auto_remember_directories: bool,
}

impl From<DirectorySettings> for DirectorySettingsResponse {
    fn from(settings: DirectorySettings) -> Self {
        Self {
            material_import_directory: settings.material_import_directory,
            template_import_directory: settings.template_import_directory,
            jianying_export_directory: settings.jianying_export_directory,
            project_export_directory: settings.project_export_directory,
            thumbnail_export_directory: settings.thumbnail_export_directory,
            auto_remember_directories: settings.auto_remember_directories,
        }
    }
}

/// 目录设置更新请求
#[derive(Debug, Serialize, Deserialize)]
pub struct UpdateDirectorySettingRequest {
    pub setting_type: String,
    pub path: String,
}

/// 批量目录设置更新请求
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchUpdateDirectorySettingsRequest {
    pub settings: Vec<UpdateDirectorySettingRequest>,
}

/// 获取所有目录设置
#[command]
pub async fn get_directory_settings() -> Result<DirectorySettingsResponse, String> {
    info!("获取目录设置");
    
    let service = DirectorySettingsService::new();
    
    match service.get_directory_settings() {
        Ok(settings) => {
            Ok(DirectorySettingsResponse::from(settings))
        }
        Err(e) => {
            error!("获取目录设置失败: {}", e);
            Err(format!("获取目录设置失败: {}", e))
        }
    }
}

/// 获取特定类型的目录设置
#[command]
pub async fn get_directory_setting(setting_type: String) -> Result<Option<String>, String> {
    info!("获取目录设置: {}", setting_type);
    
    let setting_type_enum = parse_directory_setting_type(&setting_type)?;
    let service = DirectorySettingsService::new();
    
    match service.get_directory_setting(setting_type_enum) {
        Ok(setting) => {
            Ok(setting)
        }
        Err(e) => {
            error!("获取目录设置失败: {}", e);
            Err(format!("获取目录设置失败: {}", e))
        }
    }
}

/// 更新目录设置
#[command]
pub async fn update_directory_setting(setting_type: String, path: String) -> Result<(), String> {
    info!("更新目录设置: {} -> {}", setting_type, path);
    
    let setting_type_enum = parse_directory_setting_type(&setting_type)?;
    let service = DirectorySettingsService::new();
    
    match service.update_directory_setting(setting_type_enum, path.clone()) {
        Ok(()) => {
            info!("成功更新目录设置: {} -> {}", setting_type, path);
            Ok(())
        }
        Err(e) => {
            error!("更新目录设置失败: {}", e);
            Err(format!("更新目录设置失败: {}", e))
        }
    }
}

/// 批量更新目录设置
#[command]
pub async fn batch_update_directory_settings(request: BatchUpdateDirectorySettingsRequest) -> Result<(), String> {
    info!("批量更新目录设置，共 {} 项", request.settings.len());
    
    let service = DirectorySettingsService::new();
    let mut settings = Vec::new();
    
    // 解析所有设置类型
    for setting in request.settings {
        let setting_type_enum = parse_directory_setting_type(&setting.setting_type)?;
        settings.push((setting_type_enum, setting.path));
    }
    
    match service.update_multiple_directory_settings(settings) {
        Ok(()) => {
            info!("成功批量更新目录设置");
            Ok(())
        }
        Err(e) => {
            error!("批量更新目录设置失败: {}", e);
            Err(format!("批量更新目录设置失败: {}", e))
        }
    }
}

/// 清除目录设置
#[command]
pub async fn clear_directory_setting(setting_type: String) -> Result<(), String> {
    info!("清除目录设置: {}", setting_type);
    
    let setting_type_enum = parse_directory_setting_type(&setting_type)?;
    let service = DirectorySettingsService::new();
    
    match service.clear_directory_setting(setting_type_enum) {
        Ok(()) => {
            info!("成功清除目录设置: {}", setting_type);
            Ok(())
        }
        Err(e) => {
            error!("清除目录设置失败: {}", e);
            Err(format!("清除目录设置失败: {}", e))
        }
    }
}

/// 重置所有目录设置
#[command]
pub async fn reset_all_directory_settings() -> Result<(), String> {
    info!("重置所有目录设置");
    
    let service = DirectorySettingsService::new();
    
    match service.reset_all_directory_settings() {
        Ok(()) => {
            info!("成功重置所有目录设置");
            Ok(())
        }
        Err(e) => {
            error!("重置目录设置失败: {}", e);
            Err(format!("重置目录设置失败: {}", e))
        }
    }
}

/// 设置自动记忆功能
#[command]
pub async fn set_auto_remember_directories(enabled: bool) -> Result<(), String> {
    info!("设置自动记忆功能: {}", enabled);
    
    let service = DirectorySettingsService::new();
    
    match service.set_auto_remember_directories(enabled) {
        Ok(()) => {
            info!("成功设置自动记忆功能: {}", enabled);
            Ok(())
        }
        Err(e) => {
            error!("设置自动记忆功能失败: {}", e);
            Err(format!("设置自动记忆功能失败: {}", e))
        }
    }
}

/// 检查是否启用自动记忆功能
#[command]
pub async fn is_auto_remember_enabled() -> Result<bool, String> {
    let service = DirectorySettingsService::new();
    
    match service.is_auto_remember_enabled() {
        Ok(enabled) => {
            info!("自动记忆功能状态: {}", enabled);
            Ok(enabled)
        }
        Err(e) => {
            error!("获取自动记忆功能状态失败: {}", e);
            Err(format!("获取自动记忆功能状态失败: {}", e))
        }
    }
}

/// 验证目录路径
#[command]
pub async fn validate_directory_path(path: String) -> Result<bool, String> {
    let is_valid = DirectorySettingsService::validate_directory_path(&path);
    info!("验证目录路径 {}: {}", path, is_valid);
    Ok(is_valid)
}

/// 选择目录并可选择性地保存设置
#[command]
pub async fn select_and_save_directory(
    app: tauri::AppHandle,
    setting_type: Option<String>,
    title: Option<String>,
) -> Result<Option<String>, String> {
    use crate::presentation::commands::system_commands::select_directory;
    
    // 设置对话框标题
    let dialog_title = title.unwrap_or_else(|| {
        if let Some(ref st) = setting_type {
            format!("选择{}", get_setting_display_name_by_string(st))
        } else {
            "选择目录".to_string()
        }
    });
    
    info!("打开目录选择对话框: {}", dialog_title);
    
    // 使用现有的目录选择功能
    match select_directory(app) {
        Ok(Some(selected_path)) => {
            info!("用户选择了目录: {}", selected_path);
            
            // 如果指定了设置类型，询问是否保存
            if let Some(st) = setting_type {
                let service = DirectorySettingsService::new();
                
                // 检查是否启用自动记忆
                if service.is_auto_remember_enabled().unwrap_or(false) {
                    let setting_type_enum = parse_directory_setting_type(&st)?;
                    if let Err(e) = service.update_directory_setting(setting_type_enum, selected_path.clone()) {
                        warn!("自动保存目录设置失败: {}", e);
                        // 不返回错误，只是记录警告
                    } else {
                        info!("自动保存目录设置: {} -> {}", st, selected_path);
                    }
                }
            }
            
            Ok(Some(selected_path))
        }
        Ok(None) => {
            info!("用户取消了目录选择");
            Ok(None)
        }
        Err(e) => {
            error!("目录选择失败: {}", e);
            Err(format!("目录选择失败: {}", e))
        }
    }
}

/// 解析目录设置类型字符串
fn parse_directory_setting_type(setting_type: &str) -> Result<DirectorySettingType, String> {
    match setting_type.to_lowercase().as_str() {
        "material_import" | "materialimport" => Ok(DirectorySettingType::MaterialImport),
        "template_import" | "templateimport" => Ok(DirectorySettingType::TemplateImport),
        "jianying_export" | "jianyingexport" => Ok(DirectorySettingType::JianyingExport),
        "project_export" | "projectexport" => Ok(DirectorySettingType::ProjectExport),
        "thumbnail_export" | "thumbnailexport" => Ok(DirectorySettingType::ThumbnailExport),
        _ => Err(format!("不支持的目录设置类型: {}", setting_type)),
    }
}

/// 根据字符串获取设置显示名称
fn get_setting_display_name_by_string(setting_type: &str) -> &'static str {
    match setting_type.to_lowercase().as_str() {
        "material_import" | "materialimport" => "素材导入目录",
        "template_import" | "templateimport" => "模板导入目录",
        "jianying_export" | "jianyingexport" => "剪影导出目录",
        "project_export" | "projectexport" => "项目导出目录",
        "thumbnail_export" | "thumbnailexport" => "缩略图导出目录",
        _ => "目录",
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_directory_setting_type() {
        assert!(matches!(
            parse_directory_setting_type("material_import"),
            Ok(DirectorySettingType::MaterialImport)
        ));
        assert!(matches!(
            parse_directory_setting_type("MaterialImport"),
            Ok(DirectorySettingType::MaterialImport)
        ));
        assert!(matches!(
            parse_directory_setting_type("template_import"),
            Ok(DirectorySettingType::TemplateImport)
        ));
        assert!(matches!(
            parse_directory_setting_type("jianying_export"),
            Ok(DirectorySettingType::JianyingExport)
        ));
        assert!(matches!(
            parse_directory_setting_type("project_export"),
            Ok(DirectorySettingType::ProjectExport)
        ));
        assert!(matches!(
            parse_directory_setting_type("thumbnail_export"),
            Ok(DirectorySettingType::ThumbnailExport)
        ));
        assert!(parse_directory_setting_type("invalid").is_err());
    }

    #[test]
    fn test_get_setting_display_name() {
        assert_eq!(get_setting_display_name_by_string("material_import"), "素材导入目录");
        assert_eq!(get_setting_display_name_by_string("template_import"), "模板导入目录");
        assert_eq!(get_setting_display_name_by_string("jianying_export"), "剪影导出目录");
        assert_eq!(get_setting_display_name_by_string("project_export"), "项目导出目录");
        assert_eq!(get_setting_display_name_by_string("thumbnail_export"), "缩略图导出目录");
        assert_eq!(get_setting_display_name_by_string("invalid"), "目录");
    }

    #[test]
    fn test_directory_settings_response_from_settings() {
        let settings = DirectorySettings {
            material_import_directory: Some("/path/to/material".to_string()),
            template_import_directory: Some("/path/to/template".to_string()),
            jianying_export_directory: None,
            project_export_directory: None,
            thumbnail_export_directory: None,
            auto_remember_directories: true,
        };

        let response = DirectorySettingsResponse::from(settings);

        assert_eq!(response.material_import_directory, Some("/path/to/material".to_string()));
        assert_eq!(response.template_import_directory, Some("/path/to/template".to_string()));
        assert_eq!(response.jianying_export_directory, None);
        assert_eq!(response.project_export_directory, None);
        assert_eq!(response.thumbnail_export_directory, None);
        assert_eq!(response.auto_remember_directories, true);
    }

    #[test]
    fn test_batch_update_request_parsing() {
        let request = BatchUpdateDirectorySettingsRequest {
            settings: vec![
                UpdateDirectorySettingRequest {
                    setting_type: "material_import".to_string(),
                    path: "/path/to/material".to_string(),
                },
                UpdateDirectorySettingRequest {
                    setting_type: "template_import".to_string(),
                    path: "/path/to/template".to_string(),
                },
            ],
        };

        assert_eq!(request.settings.len(), 2);
        assert_eq!(request.settings[0].setting_type, "material_import");
        assert_eq!(request.settings[0].path, "/path/to/material");
        assert_eq!(request.settings[1].setting_type, "template_import");
        assert_eq!(request.settings[1].path, "/path/to/template");
    }

    #[tokio::test]
    async fn test_get_directory_settings_command() {
        // 这个测试需要实际的服务实例，在集成测试中更合适
        // 这里只测试函数签名和基本逻辑
        let result = get_directory_settings().await;
        // 由于依赖文件系统，这里只验证返回类型
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_validate_directory_path_command() {
        // 测试有效路径（当前目录应该存在）
        let result = validate_directory_path(".".to_string()).await;
        assert!(result.is_ok());
        assert!(result.unwrap());

        // 测试无效路径
        let result = validate_directory_path("/non/existent/path".to_string()).await;
        assert!(result.is_ok());
        assert!(!result.unwrap());
    }
}
