use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use anyhow::{anyhow, Result};
use tokio::fs;
use tracing::{info, warn, error};
use uuid::Uuid;

use crate::data::models::batch_processing::*;
use crate::data::models::workflow_execution_record::{ExecuteWorkflowRequest, CreateExecutionRecordRequest};
use crate::business::services::universal_workflow_service::UniversalWorkflowService;
use crate::infrastructure::database::Database;

/// 批量处理服务
pub struct BatchProcessingService {
    /// 活跃的批量任务
    active_tasks: Arc<Mutex<HashMap<String, BatchProcessingTask>>>,
    /// 文件项映射
    file_items: Arc<Mutex<HashMap<String, Vec<BatchFileItem>>>>,
    /// 工作流服务
    workflow_service: Arc<UniversalWorkflowService>,
}

impl BatchProcessingService {
    /// 创建新的批量处理服务
    pub fn new(workflow_service: Arc<UniversalWorkflowService>) -> Self {
        Self {
            active_tasks: Arc::new(Mutex::new(HashMap::new())),
            file_items: Arc::new(Mutex::new(HashMap::new())),
            workflow_service,
        }
    }

    /// 创建批量处理任务
    pub async fn create_batch_task(&self, request: CreateBatchTaskRequest) -> Result<BatchProcessingTask> {
        info!("创建批量处理任务: {}", request.name);

        // 验证输入文件夹
        let input_path = Path::new(&request.input_folder);
        if !input_path.exists() || !input_path.is_dir() {
            return Err(anyhow!("输入文件夹不存在或不是有效目录: {}", request.input_folder));
        }

        // 创建输出文件夹
        let output_path = Path::new(&request.output_folder);
        if !output_path.exists() {
            fs::create_dir_all(output_path).await
                .map_err(|e| anyhow!("创建输出文件夹失败: {}", e))?;
        }

        // 创建任务
        let mut task = BatchProcessingTask::new(request.clone());

        // 扫描文件
        let file_items = self.scan_files(&request).await?;
        task.total_files = file_items.len() as u32;

        info!("扫描到 {} 个文件", file_items.len());

        // 存储任务和文件项
        {
            let mut tasks = self.active_tasks.lock().unwrap();
            tasks.insert(task.id.clone(), task.clone());
        }
        {
            let mut items = self.file_items.lock().unwrap();
            items.insert(task.id.clone(), file_items);
        }

        Ok(task)
    }

    /// 扫描文件夹中的文件
    async fn scan_files(&self, request: &CreateBatchTaskRequest) -> Result<Vec<BatchFileItem>> {
        let mut file_items = Vec::new();
        let input_path = Path::new(&request.input_folder);

        self.scan_directory_recursive(
            input_path,
            &request.file_extensions,
            request.recursive,
            &mut file_items,
            &format!("batch_{}", chrono::Utc::now().timestamp_millis()),
        ).await?;

        Ok(file_items)
    }

    /// 递归扫描目录
    async fn scan_directory_recursive(
        &self,
        dir_path: &Path,
        extensions: &[String],
        recursive: bool,
        file_items: &mut Vec<BatchFileItem>,
        batch_task_id: &str,
    ) -> Result<()> {
        let mut entries = fs::read_dir(dir_path).await
            .map_err(|e| anyhow!("读取目录失败: {}", e))?;

        while let Some(entry) = entries.next_entry().await
            .map_err(|e| anyhow!("读取目录项失败: {}", e))? {
            
            let path = entry.path();
            
            if path.is_file() {
                // 检查文件扩展名
                if let Some(ext) = path.extension() {
                    let ext_str = ext.to_string_lossy().to_lowercase();
                    if extensions.is_empty() || extensions.iter().any(|e| e.to_lowercase() == ext_str) {
                        let file_item = BatchFileItem::new(batch_task_id.to_string(), path);
                        file_items.push(file_item);
                    }
                }
            } else if path.is_dir() && recursive {
                // 递归扫描子目录
                self.scan_directory_recursive(&path, extensions, recursive, file_items, batch_task_id).await?;
            }
        }

        Ok(())
    }

    /// 开始批量处理
    pub async fn start_batch_processing(&self, task_id: &str) -> Result<()> {
        info!("开始批量处理任务: {}", task_id);

        // 获取任务
        let mut task = {
            let mut tasks = self.active_tasks.lock().unwrap();
            tasks.get_mut(task_id)
                .ok_or_else(|| anyhow!("批量任务不存在: {}", task_id))?
                .clone()
        };

        // 获取文件项
        let file_items = {
            let items = self.file_items.lock().unwrap();
            items.get(task_id)
                .ok_or_else(|| anyhow!("文件项不存在: {}", task_id))?
                .clone()
        };

        // 开始处理
        task.start_processing(file_items.len() as u32);
        self.update_task(&task)?;

        // 异步处理文件
        let service = Arc::clone(&self.workflow_service);
        let task_id = task_id.to_string();
        let active_tasks = Arc::clone(&self.active_tasks);
        let file_items_map = Arc::clone(&self.file_items);

        tokio::spawn(async move {
            let result = Self::process_files_async(
                service,
                task_id.clone(),
                file_items,
                active_tasks.clone(),
                file_items_map.clone(),
            ).await;

            // 更新任务状态
            {
                let mut tasks = active_tasks.lock().unwrap();
                if let Some(mut task) = tasks.get_mut(&task_id) {
                    match result {
                        Ok(_) => task.complete_processing(),
                        Err(e) => task.mark_failed(e.to_string()),
                    }
                }
            }
        });

        Ok(())
    }

    /// 异步处理文件
    async fn process_files_async(
        workflow_service: Arc<UniversalWorkflowService>,
        task_id: String,
        file_items: Vec<BatchFileItem>,
        active_tasks: Arc<Mutex<HashMap<String, BatchProcessingTask>>>,
        file_items_map: Arc<Mutex<HashMap<String, Vec<BatchFileItem>>>>,
    ) -> Result<()> {
        let mut processed = 0;
        let mut failed = 0;

        for mut file_item in file_items {
            info!("处理文件: {:?}", file_item.input_file_path);

            // 构建输出文件路径
            let output_path = Self::generate_output_path(&file_item, &task_id)?;

            // 准备工作流执行请求
            let input_data = serde_json::json!({
                "input_image": file_item.input_file_path.to_string_lossy(),
                "output_path": output_path.to_string_lossy()
            });

            let execute_request = ExecuteWorkflowRequest {
                workflow_identifier: "1".to_string(), // 使用模板ID
                version: None,
                input_data,
                environment_id: None,
                execution_config_override: None,
            };

            // 执行工作流
            match workflow_service.execute_workflow(execute_request).await {
                Ok(response) => {
                    file_item.complete_processing(output_path);
                    processed += 1;
                    info!("文件处理成功: {:?}", file_item.input_file_path);
                }
                Err(e) => {
                    file_item.mark_failed(e.to_string());
                    failed += 1;
                    error!("文件处理失败: {:?}, 错误: {}", file_item.input_file_path, e);
                }
            }

            // 更新任务进度
            {
                let mut tasks = active_tasks.lock().unwrap();
                if let Some(task) = tasks.get_mut(&task_id) {
                    task.update_progress(processed, failed);
                }
            }

            // 更新文件项状态
            {
                let mut items = file_items_map.lock().unwrap();
                if let Some(items_vec) = items.get_mut(&task_id) {
                    if let Some(item) = items_vec.iter_mut().find(|i| i.id == file_item.id) {
                        *item = file_item;
                    }
                }
            }
        }

        info!("批量处理完成: 成功 {}, 失败 {}", processed, failed);
        Ok(())
    }

    /// 生成输出文件路径
    fn generate_output_path(file_item: &BatchFileItem, task_id: &str) -> Result<PathBuf> {
        let input_path = &file_item.input_file_path;
        let file_name = input_path.file_stem()
            .ok_or_else(|| anyhow!("无法获取文件名"))?;
        let extension = input_path.extension()
            .unwrap_or_default();

        // 生成输出文件名：原文件名_processed.扩展名
        let output_filename = format!("{}_processed.{}", 
            file_name.to_string_lossy(), 
            extension.to_string_lossy()
        );

        // 这里需要从任务中获取输出目录，简化处理
        let output_path = PathBuf::from("output").join(output_filename);
        Ok(output_path)
    }

    /// 获取批量任务
    pub fn get_batch_task(&self, task_id: &str) -> Option<BatchProcessingTask> {
        let tasks = self.active_tasks.lock().unwrap();
        tasks.get(task_id).cloned()
    }

    /// 获取所有批量任务
    pub fn get_all_batch_tasks(&self) -> Vec<BatchProcessingTask> {
        let tasks = self.active_tasks.lock().unwrap();
        tasks.values().cloned().collect()
    }

    /// 获取批量处理进度
    pub fn get_batch_progress(&self, task_id: &str) -> Option<BatchProcessingProgress> {
        let tasks = self.active_tasks.lock().unwrap();
        if let Some(task) = tasks.get(task_id) {
            Some(BatchProcessingProgress {
                task_id: task.id.clone(),
                status: task.status.clone(),
                total_files: task.total_files,
                processed_files: task.processed_files,
                failed_files: task.failed_files,
                current_file: None, // TODO: 实现当前处理文件跟踪
                progress_percentage: task.get_progress_percentage(),
                estimated_remaining_time: None, // TODO: 实现时间估算
            })
        } else {
            None
        }
    }

    /// 取消批量任务
    pub fn cancel_batch_task(&self, task_id: &str) -> Result<()> {
        let mut tasks = self.active_tasks.lock().unwrap();
        if let Some(task) = tasks.get_mut(task_id) {
            task.cancel();
            info!("批量任务已取消: {}", task_id);
            Ok(())
        } else {
            Err(anyhow!("批量任务不存在: {}", task_id))
        }
    }

    /// 更新任务
    fn update_task(&self, task: &BatchProcessingTask) -> Result<()> {
        let mut tasks = self.active_tasks.lock().unwrap();
        tasks.insert(task.id.clone(), task.clone());
        Ok(())
    }
}
