use crate::config::{AppConfig, DirectorySettings, DirectorySettingType};
use anyhow::Result;
use std::sync::{Arc, Mutex};
use tracing::{info, warn, error};

/// 目录设置管理服务
/// 遵循 Tauri 开发规范的服务层设计原则
pub struct DirectorySettingsService {
    config: Arc<Mutex<AppConfig>>,
}

impl DirectorySettingsService {
    /// 创建新的目录设置服务实例
    pub fn new() -> Self {
        let config = AppConfig::load();
        Self {
            config: Arc::new(Mutex::new(config)),
        }
    }

    /// 从现有配置创建服务实例
    pub fn from_config(config: AppConfig) -> Self {
        Self {
            config: Arc::new(Mutex::new(config)),
        }
    }

    /// 获取所有目录设置
    pub fn get_directory_settings(&self) -> Result<DirectorySettings> {
        let config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        Ok(config.directory_settings.clone())
    }

    /// 获取特定类型的目录设置
    pub fn get_directory_setting(&self, setting_type: DirectorySettingType) -> Result<Option<String>> {
        let config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        let result = config.get_directory_setting(setting_type.clone()).cloned();
        info!("获取目录设置 {:?}: {:?}", setting_type, result);
        Ok(result)
    }

    /// 更新特定类型的目录设置
    pub fn update_directory_setting(&self, setting_type: DirectorySettingType, path: String) -> Result<()> {
        // 验证路径是否存在
        if !std::path::Path::new(&path).exists() {
            warn!("设置的目录路径不存在: {}", path);
            return Err(anyhow::anyhow!("目录路径不存在: {}", path));
        }

        let mut config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        config.update_directory_setting(setting_type.clone(), path.clone());
        
        // 保存配置到文件
        if let Err(e) = config.save() {
            error!("保存配置失败: {}", e);
            return Err(anyhow::anyhow!("保存配置失败: {}", e));
        }
        
        info!("更新目录设置 {:?}: {}", setting_type, path);
        Ok(())
    }

    /// 批量更新目录设置
    pub fn update_multiple_directory_settings(&self, settings: Vec<(DirectorySettingType, String)>) -> Result<()> {
        // 验证所有路径
        for (setting_type, path) in &settings {
            if !std::path::Path::new(path).exists() {
                warn!("设置的目录路径不存在: {} (类型: {:?})", path, setting_type);
                return Err(anyhow::anyhow!("目录路径不存在: {}", path));
            }
        }

        let mut config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        // 批量更新
        for (setting_type, path) in settings {
            config.update_directory_setting(setting_type.clone(), path.clone());
            info!("批量更新目录设置 {:?}: {}", setting_type, path);
        }
        
        // 保存配置到文件
        if let Err(e) = config.save() {
            error!("保存配置失败: {}", e);
            return Err(anyhow::anyhow!("保存配置失败: {}", e));
        }
        
        info!("批量更新目录设置完成");
        Ok(())
    }

    /// 清除特定类型的目录设置
    pub fn clear_directory_setting(&self, setting_type: DirectorySettingType) -> Result<()> {
        let mut config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        match setting_type {
            DirectorySettingType::MaterialImport => {
                config.directory_settings.material_import_directory = None;
            }
            DirectorySettingType::TemplateImport => {
                config.directory_settings.template_import_directory = None;
            }
            DirectorySettingType::JianyingExport => {
                config.directory_settings.jianying_export_directory = None;
            }
            DirectorySettingType::ProjectExport => {
                config.directory_settings.project_export_directory = None;
            }
            DirectorySettingType::ThumbnailExport => {
                config.directory_settings.thumbnail_export_directory = None;
            }
        }
        
        // 保存配置到文件
        if let Err(e) = config.save() {
            error!("保存配置失败: {}", e);
            return Err(anyhow::anyhow!("保存配置失败: {}", e));
        }
        
        info!("清除目录设置 {:?}", setting_type);
        Ok(())
    }

    /// 重置所有目录设置为默认值
    pub fn reset_all_directory_settings(&self) -> Result<()> {
        let mut config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        config.directory_settings = DirectorySettings::default();
        
        // 保存配置到文件
        if let Err(e) = config.save() {
            error!("保存配置失败: {}", e);
            return Err(anyhow::anyhow!("保存配置失败: {}", e));
        }
        
        info!("重置所有目录设置为默认值");
        Ok(())
    }

    /// 设置自动记忆功能开关
    pub fn set_auto_remember_directories(&self, enabled: bool) -> Result<()> {
        let mut config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        config.directory_settings.auto_remember_directories = enabled;
        
        // 保存配置到文件
        if let Err(e) = config.save() {
            error!("保存配置失败: {}", e);
            return Err(anyhow::anyhow!("保存配置失败: {}", e));
        }
        
        info!("设置自动记忆功能: {}", enabled);
        Ok(())
    }

    /// 检查是否启用自动记忆功能
    pub fn is_auto_remember_enabled(&self) -> Result<bool> {
        let config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        Ok(config.directory_settings.auto_remember_directories)
    }

    /// 获取配置的克隆副本
    pub fn get_config_clone(&self) -> Result<AppConfig> {
        let config = self.config.lock().map_err(|e| {
            error!("获取配置锁失败: {}", e);
            anyhow::anyhow!("配置访问失败")
        })?;
        
        Ok(config.clone())
    }

    /// 验证目录路径是否有效
    pub fn validate_directory_path(path: &str) -> bool {
        let path_obj = std::path::Path::new(path);
        path_obj.exists() && path_obj.is_dir()
    }

    /// 获取目录设置的显示名称
    pub fn get_setting_display_name(setting_type: &DirectorySettingType) -> &'static str {
        match setting_type {
            DirectorySettingType::MaterialImport => "素材导入目录",
            DirectorySettingType::TemplateImport => "模板导入目录",
            DirectorySettingType::JianyingExport => "剪影导出目录",
            DirectorySettingType::ProjectExport => "项目导出目录",
            DirectorySettingType::ThumbnailExport => "缩略图导出目录",
        }
    }
}

impl Default for DirectorySettingsService {
    fn default() -> Self {
        Self::new()
    }
}

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

    #[test]
    fn test_directory_settings_service_creation() {
        let service = DirectorySettingsService::new();
        assert!(service.get_directory_settings().is_ok());
    }

    #[test]
    fn test_update_directory_setting() {
        let service = DirectorySettingsService::new();
        let temp_dir = tempdir().unwrap();
        let temp_path = temp_dir.path().to_string_lossy().to_string();

        let result = service.update_directory_setting(
            DirectorySettingType::MaterialImport,
            temp_path.clone()
        );
        assert!(result.is_ok());

        let setting = service.get_directory_setting(DirectorySettingType::MaterialImport).unwrap();
        assert_eq!(setting, Some(temp_path));
    }

    #[test]
    fn test_update_nonexistent_directory() {
        let service = DirectorySettingsService::new();
        let result = service.update_directory_setting(
            DirectorySettingType::MaterialImport,
            "/non/existent/path".to_string()
        );
        assert!(result.is_err());
    }

    #[test]
    fn test_batch_update_directory_settings() {
        let service = DirectorySettingsService::new();
        let temp_dir1 = tempdir().unwrap();
        let temp_dir2 = tempdir().unwrap();
        let temp_path1 = temp_dir1.path().to_string_lossy().to_string();
        let temp_path2 = temp_dir2.path().to_string_lossy().to_string();

        let settings = vec![
            (DirectorySettingType::MaterialImport, temp_path1.clone()),
            (DirectorySettingType::TemplateImport, temp_path2.clone()),
        ];

        let result = service.update_multiple_directory_settings(settings);
        assert!(result.is_ok());

        let material_setting = service.get_directory_setting(DirectorySettingType::MaterialImport).unwrap();
        let template_setting = service.get_directory_setting(DirectorySettingType::TemplateImport).unwrap();

        assert_eq!(material_setting, Some(temp_path1));
        assert_eq!(template_setting, Some(temp_path2));
    }

    #[test]
    fn test_clear_directory_setting() {
        let service = DirectorySettingsService::new();
        let temp_dir = tempdir().unwrap();
        let temp_path = temp_dir.path().to_string_lossy().to_string();

        // 先设置一个目录
        service.update_directory_setting(
            DirectorySettingType::MaterialImport,
            temp_path
        ).unwrap();

        // 验证设置成功
        let setting = service.get_directory_setting(DirectorySettingType::MaterialImport).unwrap();
        assert!(setting.is_some());

        // 清除设置
        service.clear_directory_setting(DirectorySettingType::MaterialImport).unwrap();

        // 验证已清除
        let setting = service.get_directory_setting(DirectorySettingType::MaterialImport).unwrap();
        assert!(setting.is_none());
    }

    #[test]
    fn test_reset_all_directory_settings() {
        let service = DirectorySettingsService::new();
        let temp_dir = tempdir().unwrap();
        let temp_path = temp_dir.path().to_string_lossy().to_string();

        // 设置一些目录
        service.update_directory_setting(
            DirectorySettingType::MaterialImport,
            temp_path.clone()
        ).unwrap();
        service.update_directory_setting(
            DirectorySettingType::TemplateImport,
            temp_path
        ).unwrap();

        // 重置所有设置
        service.reset_all_directory_settings().unwrap();

        // 验证所有设置都被重置
        let material_setting = service.get_directory_setting(DirectorySettingType::MaterialImport).unwrap();
        let template_setting = service.get_directory_setting(DirectorySettingType::TemplateImport).unwrap();

        assert!(material_setting.is_none());
        assert!(template_setting.is_none());
    }

    #[test]
    fn test_validate_directory_path() {
        let temp_dir = tempdir().unwrap();
        let temp_path = temp_dir.path().to_string_lossy();

        assert!(DirectorySettingsService::validate_directory_path(&temp_path));
        assert!(!DirectorySettingsService::validate_directory_path("/non/existent/path"));
    }

    #[test]
    fn test_auto_remember_setting() {
        let service = DirectorySettingsService::new();

        // 默认应该是启用的
        assert!(service.is_auto_remember_enabled().unwrap());

        // 禁用自动记忆
        service.set_auto_remember_directories(false).unwrap();
        assert!(!service.is_auto_remember_enabled().unwrap());

        // 重新启用
        service.set_auto_remember_directories(true).unwrap();
        assert!(service.is_auto_remember_enabled().unwrap());
    }

    #[test]
    fn test_get_setting_display_name() {
        assert_eq!(
            DirectorySettingsService::get_setting_display_name(&DirectorySettingType::MaterialImport),
            "素材导入目录"
        );
        assert_eq!(
            DirectorySettingsService::get_setting_display_name(&DirectorySettingType::TemplateImport),
            "模板导入目录"
        );
        assert_eq!(
            DirectorySettingsService::get_setting_display_name(&DirectorySettingType::JianyingExport),
            "剪影导出目录"
        );
        assert_eq!(
            DirectorySettingsService::get_setting_display_name(&DirectorySettingType::ProjectExport),
            "项目导出目录"
        );
        assert_eq!(
            DirectorySettingsService::get_setting_display_name(&DirectorySettingType::ThumbnailExport),
            "缩略图导出目录"
        );
    }

    #[test]
    fn test_get_config_clone() {
        let service = DirectorySettingsService::new();
        let config = service.get_config_clone();
        assert!(config.is_ok());

        let config = config.unwrap();
        assert_eq!(config.directory_settings.auto_remember_directories, true);
    }
}
