use std::any::Any;
use std::collections::HashMap;
use std::sync::Arc;

use uuid::Uuid;

use crate::error::{AppError, AppResult};
use crate::events::EventBus;

/// 权限描述符，用于模块声明自己需要的权限。
///
/// 各业务模块通过 `ErpModule::permissions()` 返回此列表，
/// 由 erp-server 在启动时统一注册到权限表。
#[derive(Clone, Debug)]
pub struct PermissionDescriptor {
    /// 权限编码，全局唯一，格式建议 `{模块}.{动作}` 如 `plugin.admin`
    pub code: String,
    /// 权限显示名称
    pub name: String,
    /// 权限描述
    pub description: String,
    /// 所属模块名称
    pub module: String,
}

/// 模块类型
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModuleType {
    /// 内置模块（编译时链接）
    Builtin,
    /// 插件模块（运行时加载）
    Plugin,
}

/// 模块启动上下文 — 在 on_startup 时提供给模块
pub struct ModuleContext {
    pub db: sea_orm::DatabaseConnection,
    pub event_bus: EventBus,
}

/// 模块注册接口
/// 所有业务模块（Auth, Workflow, Message, Config, 行业模块）都实现此 trait
#[async_trait::async_trait]
pub trait ErpModule: Send + Sync {
    /// 模块名称（唯一标识）
    fn name(&self) -> &str;

    /// 模块唯一 ID（默认等于 name）
    fn id(&self) -> &str {
        self.name()
    }

    /// 模块版本
    fn version(&self) -> &str {
        env!("CARGO_PKG_VERSION")
    }

    /// 模块类型
    fn module_type(&self) -> ModuleType {
        ModuleType::Builtin
    }

    /// 依赖的其他模块名称
    fn dependencies(&self) -> Vec<&str> {
        vec![]
    }

    /// 注册事件处理器
    fn register_event_handlers(&self, _bus: &EventBus) {}

    /// 模块启动钩子 — 服务启动时调用
    async fn on_startup(&self, _ctx: &ModuleContext) -> AppResult<()> {
        Ok(())
    }

    /// 模块关闭钩子 — 服务关闭时调用
    async fn on_shutdown(&self) -> AppResult<()> {
        Ok(())
    }

    /// 健康检查
    async fn health_check(&self) -> AppResult<serde_json::Value> {
        Ok(serde_json::json!({"status": "healthy"}))
    }

    /// 租户创建时的初始化钩子。
    ///
    /// 用于为新建租户创建默认角色、管理员用户等初始数据。
    async fn on_tenant_created(
        &self,
        _tenant_id: Uuid,
        _db: &sea_orm::DatabaseConnection,
        _event_bus: &EventBus,
    ) -> AppResult<()> {
        Ok(())
    }

    /// 租户删除时的清理钩子。
    ///
    /// 用于软删除该租户下的所有关联数据。
    async fn on_tenant_deleted(
        &self,
        _tenant_id: Uuid,
        _db: &sea_orm::DatabaseConnection,
    ) -> AppResult<()> {
        Ok(())
    }

    /// 返回此模块需要注册的权限列表。
    ///
    /// 默认返回空列表，有权限需求的模块（如 plugin）可覆写此方法。
    fn permissions(&self) -> Vec<PermissionDescriptor> {
        vec![]
    }

    /// Downcast support: return `self` as `&dyn Any` for concrete type access.
    ///
    /// This allows the server crate to retrieve module-specific methods
    /// (e.g. `AuthModule::public_routes()`) that are not part of the trait.
    fn as_any(&self) -> &dyn Any;
}

/// 模块注册器 — 用 Arc 包装使其可 Clone（用于 Axum State）
#[derive(Clone, Default)]
pub struct ModuleRegistry {
    modules: Arc<Vec<Arc<dyn ErpModule>>>,
}

impl ModuleRegistry {
    pub fn new() -> Self {
        Self {
            modules: Arc::new(vec![]),
        }
    }

    pub fn register(mut self, module: impl ErpModule + 'static) -> Self {
        tracing::info!(
            module = module.name(),
            id = module.id(),
            version = module.version(),
            module_type = ?module.module_type(),
            "Module registered"
        );
        let mut modules = (*self.modules).clone();
        modules.push(Arc::new(module));
        self.modules = Arc::new(modules);
        self
    }

    pub fn register_handlers(&self, bus: &EventBus) {
        for module in self.modules.iter() {
            module.register_event_handlers(bus);
        }
    }

    pub fn modules(&self) -> &[Arc<dyn ErpModule>] {
        &self.modules
    }

    /// 按名称获取模块
    pub fn get_module(&self, name: &str) -> Option<Arc<dyn ErpModule>> {
        self.modules.iter().find(|m| m.name() == name).cloned()
    }

    /// 按拓扑排序返回模块（依赖在前，被依赖在后）
    ///
    /// 使用 Kahn 算法，环检测返回 Validation 错误。
    pub fn sorted_modules(&self) -> AppResult<Vec<Arc<dyn ErpModule>>> {
        let modules = &*self.modules;
        let n = modules.len();
        if n == 0 {
            return Ok(vec![]);
        }

        // 构建名称到索引的映射
        let name_to_idx: HashMap<&str, usize> = modules
            .iter()
            .enumerate()
            .map(|(i, m)| (m.name(), i))
            .collect();

        // 构建邻接表和入度
        let mut adjacency: Vec<Vec<usize>> = vec![vec![]; n];
        let mut in_degree: Vec<usize> = vec![0; n];

        for (idx, module) in modules.iter().enumerate() {
            for dep in module.dependencies() {
                if let Some(&dep_idx) = name_to_idx.get(dep) {
                    adjacency[dep_idx].push(idx);
                    in_degree[idx] += 1;
                }
                // 依赖未注册的模块不阻断（可能是可选依赖）
            }
        }

        // Kahn 算法
        let mut queue: Vec<usize> = (0..n).filter(|&i| in_degree[i] == 0).collect();
        let mut sorted_indices = Vec::with_capacity(n);

        while let Some(idx) = queue.pop() {
            sorted_indices.push(idx);
            for &next in &adjacency[idx] {
                in_degree[next] -= 1;
                if in_degree[next] == 0 {
                    queue.push(next);
                }
            }
        }

        if sorted_indices.len() != n {
            let cycle_modules: Vec<&str> = (0..n)
                .filter(|i| !sorted_indices.contains(i))
                .filter_map(|i| modules.get(i).map(|m| m.name()))
                .collect();
            return Err(AppError::Validation(format!(
                "模块依赖存在循环: {}",
                cycle_modules.join(", ")
            )));
        }

        Ok(sorted_indices
            .into_iter()
            .map(|i| modules[i].clone())
            .collect())
    }

    /// 按拓扑顺序启动所有模块
    pub async fn startup_all(&self, ctx: &ModuleContext) -> AppResult<()> {
        let sorted = self.sorted_modules()?;
        for module in sorted {
            tracing::info!(module = module.name(), "Starting module");
            module.on_startup(ctx).await?;
            tracing::info!(module = module.name(), "Module started");
        }
        Ok(())
    }

    /// 按拓扑逆序关闭所有模块
    pub async fn shutdown_all(&self) -> AppResult<()> {
        let sorted = self.sorted_modules()?;
        for module in sorted.into_iter().rev() {
            tracing::info!(module = module.name(), "Shutting down module");
            if let Err(e) = module.on_shutdown().await {
                tracing::error!(module = module.name(), error = %e, "Module shutdown failed");
            }
        }
        Ok(())
    }

    /// 对所有模块执行健康检查
    pub async fn health_check_all(&self) -> Vec<(String, AppResult<serde_json::Value>)> {
        let mut results = Vec::with_capacity(self.modules.len());
        for module in self.modules.iter() {
            let result = module.health_check().await;
            results.push((module.name().to_string(), result));
        }
        results
    }
}

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

    struct TestModule {
        name: &'static str,
        deps: Vec<&'static str>,
    }

    #[async_trait::async_trait]
    impl ErpModule for TestModule {
        fn name(&self) -> &str {
            self.name
        }
        fn dependencies(&self) -> Vec<&str> {
            self.deps.clone()
        }
        fn as_any(&self) -> &dyn Any {
            self
        }
    }

    #[test]
    fn sorted_modules_empty() {
        let registry = ModuleRegistry::new();
        let sorted = registry.sorted_modules().unwrap();
        assert!(sorted.is_empty());
    }

    #[test]
    fn sorted_modules_no_deps() {
        let registry = ModuleRegistry::new()
            .register(TestModule {
                name: "a",
                deps: vec![],
            })
            .register(TestModule {
                name: "b",
                deps: vec![],
            });
        let sorted = registry.sorted_modules().unwrap();
        assert_eq!(sorted.len(), 2);
    }

    #[test]
    fn sorted_modules_with_deps() {
        let registry = ModuleRegistry::new()
            .register(TestModule {
                name: "auth",
                deps: vec![],
            })
            .register(TestModule {
                name: "plugin",
                deps: vec!["auth", "config"],
            })
            .register(TestModule {
                name: "config",
                deps: vec!["auth"],
            });
        let sorted = registry.sorted_modules().unwrap();
        let names: Vec<&str> = sorted.iter().map(|m| m.name()).collect();
        let auth_pos = names.iter().position(|&n| n == "auth").unwrap();
        let config_pos = names.iter().position(|&n| n == "config").unwrap();
        let plugin_pos = names.iter().position(|&n| n == "plugin").unwrap();
        assert!(auth_pos < config_pos);
        assert!(config_pos < plugin_pos);
    }

    #[test]
    fn sorted_modules_circular_dep() {
        let registry = ModuleRegistry::new()
            .register(TestModule {
                name: "a",
                deps: vec!["b"],
            })
            .register(TestModule {
                name: "b",
                deps: vec!["a"],
            });
        let result = registry.sorted_modules();
        assert!(result.is_err());
        match result.err().unwrap() {
            AppError::Validation(msg) => assert!(msg.contains("循环")),
            other => panic!("Expected Validation, got {:?}", other),
        }
    }

    #[test]
    fn get_module_found() {
        let registry = ModuleRegistry::new().register(TestModule {
            name: "auth",
            deps: vec![],
        });
        assert!(registry.get_module("auth").is_some());
        assert!(registry.get_module("unknown").is_none());
    }
}
