use anyhow::{Result, anyhow};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use tokio::fs;
use tracing::{info, warn};

/// 工作流元数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowMetadata {
    pub id: String,
    pub name: String,
    pub description: Option<String>,
    pub version: String,
    pub author: Option<String>,
    pub tags: Vec<String>,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
    pub file_path: String,
    pub file_size: u64,
    pub is_valid: bool,
    pub validation_errors: Vec<String>,
}

/// 工作流节点信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowNodeInfo {
    pub node_id: String,
    pub node_type: String,
    pub title: Option<String>,
    pub inputs: HashMap<String, Value>,
    pub outputs: Vec<String>,
}

/// 工作流验证结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowValidationResult {
    pub is_valid: bool,
    pub errors: Vec<String>,
    pub warnings: Vec<String>,
    pub node_count: usize,
    pub input_nodes: Vec<WorkflowNodeInfo>,
    pub output_nodes: Vec<WorkflowNodeInfo>,
}

/// 工作流管理服务
/// 遵循 Tauri 开发规范的业务逻辑设计原则
pub struct WorkflowManagementService {
    workflow_directory: PathBuf,
}

impl WorkflowManagementService {
    /// 创建新的工作流管理服务实例
    pub fn new(workflow_directory: Option<String>) -> Result<Self> {
        let workflow_dir = if let Some(dir) = workflow_directory {
            PathBuf::from(dir)
        } else {
            // 默认工作流目录
            let mut default_dir = std::env::current_dir()?;
            default_dir.push("workflows");
            default_dir
        };

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

        Ok(Self {
            workflow_directory: workflow_dir,
        })
    }

    /// 扫描工作流目录并返回所有工作流文件
    pub async fn scan_workflows(&self) -> Result<Vec<WorkflowMetadata>> {
        info!("扫描工作流目录: {:?}", self.workflow_directory);
        
        let mut workflows = Vec::new();
        let mut entries = fs::read_dir(&self.workflow_directory).await?;

        while let Some(entry) = entries.next_entry().await? {
            let path = entry.path();
            
            if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("json") {
                match self.load_workflow_metadata(&path).await {
                    Ok(metadata) => workflows.push(metadata),
                    Err(e) => {
                        warn!("加载工作流元数据失败: {:?} - {}", path, e);
                    }
                }
            }
        }

        info!("扫描完成，找到 {} 个工作流文件", workflows.len());
        Ok(workflows)
    }

    /// 加载工作流元数据
    pub async fn load_workflow_metadata(&self, file_path: &Path) -> Result<WorkflowMetadata> {
        let content = fs::read_to_string(file_path).await?;
        let file_size = content.len() as u64;
        
        // 解析工作流JSON
        let workflow: Value = serde_json::from_str(&content)?;
        
        // 验证工作流
        let validation_result = self.validate_workflow(&workflow).await?;
        
        // 提取元数据
        let file_name = file_path.file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("unknown")
            .to_string();
        
        let metadata = WorkflowMetadata {
            id: uuid::Uuid::new_v4().to_string(),
            name: file_name.clone(),
            description: None,
            version: "1.0.0".to_string(),
            author: None,
            tags: Vec::new(),
            created_at: chrono::Utc::now(),
            updated_at: chrono::Utc::now(),
            file_path: file_path.to_string_lossy().to_string(),
            file_size,
            is_valid: validation_result.is_valid,
            validation_errors: validation_result.errors,
        };

        Ok(metadata)
    }

    /// 验证工作流文件
    pub async fn validate_workflow(&self, workflow: &Value) -> Result<WorkflowValidationResult> {
        let mut errors = Vec::new();
        let mut warnings = Vec::new();
        let mut input_nodes = Vec::new();
        let mut output_nodes = Vec::new();

        // 检查基本结构
        if !workflow.is_object() {
            errors.push("工作流必须是JSON对象".to_string());
            return Ok(WorkflowValidationResult {
                is_valid: false,
                errors,
                warnings,
                node_count: 0,
                input_nodes,
                output_nodes,
            });
        }

        let workflow_obj = workflow.as_object().unwrap();
        let node_count = workflow_obj.len();

        // 验证每个节点
        for (node_id, node_data) in workflow_obj {
            if let Some(node_obj) = node_data.as_object() {
                // 检查必需字段
                if !node_obj.contains_key("class_type") {
                    errors.push(format!("节点 {} 缺少 class_type 字段", node_id));
                    continue;
                }

                let class_type = node_obj.get("class_type")
                    .and_then(|v| v.as_str())
                    .unwrap_or("unknown");

                let node_info = WorkflowNodeInfo {
                    node_id: node_id.clone(),
                    node_type: class_type.to_string(),
                    title: node_obj.get("_meta")
                        .and_then(|m| m.get("title"))
                        .and_then(|t| t.as_str())
                        .map(|s| s.to_string()),
                    inputs: node_obj.get("inputs")
                        .and_then(|i| i.as_object())
                        .cloned()
                        .unwrap_or_default()
                        .into_iter()
                        .collect(),
                    outputs: Vec::new(), // 简化处理，实际应该分析输出
                };

                // 分类节点类型
                match class_type {
                    "LoadImage" | "LoadImageMask" => input_nodes.push(node_info),
                    "SaveImage" | "PreviewImage" => output_nodes.push(node_info),
                    _ => {}
                }
            } else {
                errors.push(format!("节点 {} 不是有效的对象", node_id));
            }
        }

        // 检查是否有输入和输出节点
        if input_nodes.is_empty() {
            warnings.push("工作流中没有找到输入节点".to_string());
        }
        
        if output_nodes.is_empty() {
            warnings.push("工作流中没有找到输出节点".to_string());
        }

        let is_valid = errors.is_empty();

        Ok(WorkflowValidationResult {
            is_valid,
            errors,
            warnings,
            node_count,
            input_nodes,
            output_nodes,
        })
    }

    /// 保存工作流文件
    pub async fn save_workflow(&self, name: &str, workflow: &Value) -> Result<String> {
        let file_name = format!("{}.json", name);
        let file_path = self.workflow_directory.join(&file_name);
        
        // 格式化JSON
        let formatted_content = serde_json::to_string_pretty(workflow)?;
        
        // 保存文件
        fs::write(&file_path, formatted_content).await?;
        
        info!("工作流已保存: {:?}", file_path);
        Ok(file_path.to_string_lossy().to_string())
    }

    /// 删除工作流文件
    pub async fn delete_workflow(&self, file_path: &str) -> Result<()> {
        let path = Path::new(file_path);
        
        if !path.exists() {
            return Err(anyhow!("工作流文件不存在: {}", file_path));
        }
        
        fs::remove_file(path).await?;
        info!("工作流已删除: {}", file_path);
        Ok(())
    }

    /// 复制工作流文件
    pub async fn copy_workflow(&self, source_path: &str, new_name: &str) -> Result<String> {
        let source = Path::new(source_path);
        
        if !source.exists() {
            return Err(anyhow!("源工作流文件不存在: {}", source_path));
        }
        
        let content = fs::read_to_string(source).await?;
        let workflow: Value = serde_json::from_str(&content)?;
        
        self.save_workflow(new_name, &workflow).await
    }

    /// 获取工作流目录路径
    pub fn get_workflow_directory(&self) -> &Path {
        &self.workflow_directory
    }

    /// 设置工作流目录
    pub async fn set_workflow_directory(&mut self, directory: String) -> Result<()> {
        let new_dir = PathBuf::from(directory);
        
        if !new_dir.exists() {
            fs::create_dir_all(&new_dir).await?;
        }
        
        self.workflow_directory = new_dir;
        info!("工作流目录已更新: {:?}", self.workflow_directory);
        Ok(())
    }
}
