use anyhow::{Result, anyhow};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::fs;
use tracing::{info, warn};
use crate::data::repositories::workflow_execution_record_repository::WorkflowExecutionRecordRepository;

/// 工作流执行结果管理服务
/// 负责管理执行结果文件的存储、下载和清理
#[derive(Clone)]
pub struct WorkflowResultService {
    results_directory: PathBuf,
    execution_record_repository: WorkflowExecutionRecordRepository,
    max_result_age_days: u32,
    max_storage_size_mb: u64,
}

/// 结果文件信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResultFileInfo {
    pub execution_id: i64,
    pub file_name: String,
    pub file_path: String,
    pub file_size: u64,
    pub file_type: String,
    pub created_at: DateTime<Utc>,
    pub is_output: bool,
    pub description: Option<String>,
}

/// 存储统计信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageStatistics {
    pub total_files: u32,
    pub total_size_mb: f64,
    pub oldest_file_date: Option<DateTime<Utc>>,
    pub newest_file_date: Option<DateTime<Utc>>,
    pub files_by_type: std::collections::HashMap<String, u32>,
    pub size_by_type: std::collections::HashMap<String, f64>,
}

/// 清理结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupResult {
    pub files_deleted: u32,
    pub space_freed_mb: f64,
    pub errors: Vec<String>,
}

impl WorkflowResultService {
    /// 创建新的工作流结果服务
    pub fn new(
        results_directory: Option<PathBuf>,
        execution_record_repository: WorkflowExecutionRecordRepository,
        max_result_age_days: Option<u32>,
        max_storage_size_mb: Option<u64>,
    ) -> Result<Self> {
        let results_dir = results_directory.unwrap_or_else(|| {
            let mut default_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
            default_dir.push("workflow_results");
            default_dir
        });

        // 确保结果目录存在
        if !results_dir.exists() {
            fs::create_dir_all(&results_dir)?;
            info!("创建工作流结果目录: {:?}", results_dir);
        }

        Ok(Self {
            results_directory: results_dir,
            execution_record_repository,
            max_result_age_days: max_result_age_days.unwrap_or(30), // 默认30天
            max_storage_size_mb: max_storage_size_mb.unwrap_or(10240), // 默认10GB
        })
    }

    /// 存储执行结果文件
    pub async fn store_result_file(
        &self,
        execution_id: i64,
        file_name: &str,
        file_data: &[u8],
        file_type: &str,
        is_output: bool,
        description: Option<String>,
    ) -> Result<ResultFileInfo> {
        // 创建执行ID目录
        let execution_dir = self.results_directory.join(execution_id.to_string());
        if !execution_dir.exists() {
            fs::create_dir_all(&execution_dir)?;
        }

        // 生成安全的文件名
        let safe_file_name = self.sanitize_filename(file_name);
        let file_path = execution_dir.join(&safe_file_name);

        // 写入文件
        fs::write(&file_path, file_data)?;

        let file_info = ResultFileInfo {
            execution_id,
            file_name: safe_file_name.clone(),
            file_path: file_path.to_string_lossy().to_string(),
            file_size: file_data.len() as u64,
            file_type: file_type.to_string(),
            created_at: Utc::now(),
            is_output,
            description,
        };

        info!("存储结果文件: {} ({}字节)", safe_file_name, file_data.len());
        Ok(file_info)
    }

    /// 获取执行结果文件列表
    pub async fn get_result_files(&self, execution_id: i64) -> Result<Vec<ResultFileInfo>> {
        let execution_dir = self.results_directory.join(execution_id.to_string());
        
        if !execution_dir.exists() {
            return Ok(Vec::new());
        }

        let mut files = Vec::new();
        
        for entry in fs::read_dir(&execution_dir)? {
            let entry = entry?;
            let path = entry.path();
            
            if path.is_file() {
                let metadata = fs::metadata(&path)?;
                let file_name = path.file_name()
                    .and_then(|name| name.to_str())
                    .unwrap_or("unknown")
                    .to_string();
                
                let file_type = path.extension()
                    .and_then(|ext| ext.to_str())
                    .unwrap_or("unknown")
                    .to_string();

                let created_at = metadata.created()
                    .map(|time| DateTime::<Utc>::from(time))
                    .unwrap_or_else(|_| Utc::now());

                files.push(ResultFileInfo {
                    execution_id,
                    file_name: file_name.clone(),
                    file_path: path.to_string_lossy().to_string(),
                    file_size: metadata.len(),
                    file_type,
                    created_at,
                    is_output: self.is_output_file(&file_name),
                    description: None,
                });
            }
        }

        files.sort_by(|a, b| b.created_at.cmp(&a.created_at));
        Ok(files)
    }

    /// 下载结果文件
    pub async fn download_result_file(&self, execution_id: i64, file_name: &str) -> Result<Vec<u8>> {
        let file_path = self.results_directory
            .join(execution_id.to_string())
            .join(file_name);

        if !file_path.exists() {
            return Err(anyhow!("结果文件不存在: {}", file_name));
        }

        let file_data = fs::read(&file_path)?;
        info!("下载结果文件: {} ({}字节)", file_name, file_data.len());
        Ok(file_data)
    }

    /// 删除执行结果文件
    pub async fn delete_result_files(&self, execution_id: i64) -> Result<CleanupResult> {
        let execution_dir = self.results_directory.join(execution_id.to_string());
        
        if !execution_dir.exists() {
            return Ok(CleanupResult {
                files_deleted: 0,
                space_freed_mb: 0.0,
                errors: Vec::new(),
            });
        }

        let mut files_deleted = 0;
        let mut space_freed = 0u64;
        let mut errors = Vec::new();

        for entry in fs::read_dir(&execution_dir)? {
            match entry {
                Ok(entry) => {
                    let path = entry.path();
                    if path.is_file() {
                        match fs::metadata(&path) {
                            Ok(metadata) => {
                                let file_size = metadata.len();
                                match fs::remove_file(&path) {
                                    Ok(_) => {
                                        files_deleted += 1;
                                        space_freed += file_size;
                                    }
                                    Err(e) => {
                                        errors.push(format!("删除文件失败 {}: {}", path.display(), e));
                                    }
                                }
                            }
                            Err(e) => {
                                errors.push(format!("获取文件元数据失败 {}: {}", path.display(), e));
                            }
                        }
                    }
                }
                Err(e) => {
                    errors.push(format!("读取目录条目失败: {}", e));
                }
            }
        }

        // 删除空目录
        if let Err(e) = fs::remove_dir(&execution_dir) {
            if execution_dir.exists() {
                errors.push(format!("删除目录失败 {}: {}", execution_dir.display(), e));
            }
        }

        let result = CleanupResult {
            files_deleted,
            space_freed_mb: space_freed as f64 / (1024.0 * 1024.0),
            errors,
        };

        info!("删除执行结果: 删除{}个文件，释放{:.2}MB空间", 
              result.files_deleted, result.space_freed_mb);
        
        Ok(result)
    }

    /// 获取存储统计信息
    pub async fn get_storage_statistics(&self) -> Result<StorageStatistics> {
        let mut total_files = 0;
        let mut total_size = 0u64;
        let mut oldest_date: Option<DateTime<Utc>> = None;
        let mut newest_date: Option<DateTime<Utc>> = None;
        let mut files_by_type = std::collections::HashMap::new();
        let mut size_by_type = std::collections::HashMap::new();

        self.scan_directory(&self.results_directory, &mut |file_info| {
            total_files += 1;
            total_size += file_info.file_size;

            // 更新日期范围
            if oldest_date.is_none() || file_info.created_at < oldest_date.unwrap() {
                oldest_date = Some(file_info.created_at);
            }
            if newest_date.is_none() || file_info.created_at > newest_date.unwrap() {
                newest_date = Some(file_info.created_at);
            }

            // 按类型统计
            *files_by_type.entry(file_info.file_type.clone()).or_insert(0) += 1;
            *size_by_type.entry(file_info.file_type.clone()).or_insert(0.0) += 
                file_info.file_size as f64 / (1024.0 * 1024.0);
        })?;

        Ok(StorageStatistics {
            total_files,
            total_size_mb: total_size as f64 / (1024.0 * 1024.0),
            oldest_file_date: oldest_date,
            newest_file_date: newest_date,
            files_by_type,
            size_by_type,
        })
    }

    /// 清理过期结果文件
    pub async fn cleanup_expired_results(&self) -> Result<CleanupResult> {
        let cutoff_date = Utc::now() - chrono::Duration::days(self.max_result_age_days as i64);
        
        let mut files_deleted = 0;
        let mut space_freed = 0u64;
        let mut errors = Vec::new();

        self.scan_directory(&self.results_directory, &mut |file_info| {
            if file_info.created_at < cutoff_date {
                match fs::remove_file(&file_info.file_path) {
                    Ok(_) => {
                        files_deleted += 1;
                        space_freed += file_info.file_size;
                    }
                    Err(e) => {
                        errors.push(format!("删除过期文件失败 {}: {}", file_info.file_path, e));
                    }
                }
            }
        })?;

        let result = CleanupResult {
            files_deleted,
            space_freed_mb: space_freed as f64 / (1024.0 * 1024.0),
            errors,
        };

        info!("清理过期结果: 删除{}个文件，释放{:.2}MB空间",
              result.files_deleted, result.space_freed_mb);

        Ok(result)
    }

    /// 扫描目录并对每个文件执行回调
    fn scan_directory<F>(&self, dir: &Path, callback: &mut F) -> Result<()>
    where
        F: FnMut(ResultFileInfo),
    {
        if !dir.exists() {
            return Ok(());
        }

        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            let path = entry.path();

            if path.is_dir() {
                // 递归扫描子目录
                self.scan_directory(&path, callback)?;
            } else if path.is_file() {
                // 处理文件
                if let Ok(metadata) = fs::metadata(&path) {
                    let file_name = path.file_name()
                        .and_then(|name| name.to_str())
                        .unwrap_or("unknown")
                        .to_string();

                    let file_type = path.extension()
                        .and_then(|ext| ext.to_str())
                        .unwrap_or("unknown")
                        .to_string();

                    let created_at = metadata.created()
                        .map(|time| DateTime::<Utc>::from(time))
                        .unwrap_or_else(|_| Utc::now());

                    // 尝试从路径中提取execution_id
                    let execution_id = path.parent()
                        .and_then(|parent| parent.file_name())
                        .and_then(|name| name.to_str())
                        .and_then(|name| name.parse::<i64>().ok())
                        .unwrap_or(0);

                    let file_info = ResultFileInfo {
                        execution_id,
                        file_name: file_name.clone(),
                        file_path: path.to_string_lossy().to_string(),
                        file_size: metadata.len(),
                        file_type,
                        created_at,
                        is_output: self.is_output_file(&file_name),
                        description: None,
                    };

                    callback(file_info);
                }
            }
        }

        Ok(())
    }

    /// 清理文件名，移除不安全字符
    fn sanitize_filename(&self, filename: &str) -> String {
        filename
            .chars()
            .map(|c| match c {
                '/' | '\\' | ':' | '*' | '?' | '"' | '<' | '>' | '|' => '_',
                c if c.is_control() => '_',
                c => c,
            })
            .collect()
    }

    /// 判断是否为输出文件
    fn is_output_file(&self, filename: &str) -> bool {
        let output_patterns = ["output", "result", "generated", "final"];
        let filename_lower = filename.to_lowercase();

        output_patterns.iter().any(|pattern| filename_lower.contains(pattern))
    }

    /// 批量清理多个执行的结果
    pub async fn batch_cleanup_results(&self, execution_ids: &[i64]) -> Result<CleanupResult> {
        let mut total_files_deleted = 0;
        let mut total_space_freed = 0.0;
        let mut all_errors = Vec::new();

        for &execution_id in execution_ids {
            match self.delete_result_files(execution_id).await {
                Ok(result) => {
                    total_files_deleted += result.files_deleted;
                    total_space_freed += result.space_freed_mb;
                    all_errors.extend(result.errors);
                }
                Err(e) => {
                    all_errors.push(format!("清理执行ID {}失败: {}", execution_id, e));
                }
            }
        }

        Ok(CleanupResult {
            files_deleted: total_files_deleted,
            space_freed_mb: total_space_freed,
            errors: all_errors,
        })
    }

    /// 检查存储空间并在必要时清理
    pub async fn check_and_cleanup_storage(&self) -> Result<Option<CleanupResult>> {
        let stats = self.get_storage_statistics().await?;

        if stats.total_size_mb > self.max_storage_size_mb as f64 {
            warn!("存储空间超限: {:.2}MB > {}MB，开始清理",
                  stats.total_size_mb, self.max_storage_size_mb);

            // 首先清理过期文件
            let cleanup_result = self.cleanup_expired_results().await?;

            // 如果还是超限，清理最旧的文件
            let updated_stats = self.get_storage_statistics().await?;
            if updated_stats.total_size_mb > self.max_storage_size_mb as f64 {
                warn!("清理过期文件后仍超限，需要进一步清理");
            }

            Ok(Some(cleanup_result))
        } else {
            Ok(None)
        }
    }
}
