use axum::Router;
use axum::routing::{get, post, put};
use uuid::Uuid;

use erp_core::error::AppResult;
use erp_core::events::EventBus;
use erp_core::module::{ErpModule, PermissionDescriptor};

use crate::handler::{
    dictionary_handler, language_handler, menu_handler, numbering_handler, setting_handler,
    theme_handler,
};

/// Config module implementing the `ErpModule` trait.
///
/// Manages system configuration: dictionaries, menus, settings,
/// numbering rules, languages, and themes.
pub struct ConfigModule;

impl ConfigModule {
    pub fn new() -> Self {
        Self
    }

    /// Build protected (authenticated) routes for the config module.
    pub fn protected_routes<S>() -> Router<S>
    where
        crate::config_state::ConfigState: axum::extract::FromRef<S>,
        S: Clone + Send + Sync + 'static,
    {
        Router::new()
            // Dictionary routes
            .route(
                "/config/dictionaries",
                get(dictionary_handler::list_dictionaries)
                    .post(dictionary_handler::create_dictionary),
            )
            .route(
                "/config/dictionaries/{id}",
                put(dictionary_handler::update_dictionary)
                    .delete(dictionary_handler::delete_dictionary),
            )
            .route(
                "/config/dictionaries/items",
                get(dictionary_handler::list_items_by_code),
            )
            .route(
                "/config/dictionaries/{dict_id}/items",
                post(dictionary_handler::create_item),
            )
            .route(
                "/config/dictionaries/{dict_id}/items/{item_id}",
                put(dictionary_handler::update_item).delete(dictionary_handler::delete_item),
            )
            // Menu routes
            .route(
                "/config/menus",
                get(menu_handler::get_menus)
                    .post(menu_handler::create_menu)
                    .put(menu_handler::batch_save_menus),
            )
            .route(
                "/config/menus/{id}",
                put(menu_handler::update_menu).delete(menu_handler::delete_menu),
            )
            // User menu tree (no special permission required)
            .route("/menus/user", get(menu_handler::get_user_menus))
            // Setting routes
            .route(
                "/config/settings/{key}",
                get(setting_handler::get_setting)
                    .put(setting_handler::update_setting)
                    .delete(setting_handler::delete_setting),
            )
            // Numbering rule routes
            .route(
                "/config/numbering-rules",
                get(numbering_handler::list_numbering_rules)
                    .post(numbering_handler::create_numbering_rule),
            )
            .route(
                "/config/numbering-rules/{id}",
                put(numbering_handler::update_numbering_rule)
                    .delete(numbering_handler::delete_numbering_rule),
            )
            .route(
                "/config/numbering-rules/{id}/generate",
                post(numbering_handler::generate_number),
            )
            // Theme routes
            .route(
                "/config/themes",
                get(theme_handler::get_theme).put(theme_handler::update_theme),
            )
            // Language routes
            .route("/config/languages", get(language_handler::list_languages))
            .route(
                "/config/languages/{code}",
                put(language_handler::update_language),
            )
    }

    /// Build public (unauthenticated) routes for the config module.
    pub fn public_routes<S>() -> Router<S>
    where
        S: Clone + Send + Sync + 'static,
    {
        Router::new().route("/public/brand", get(theme_handler::get_public_brand))
    }
}

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

#[async_trait::async_trait]
impl ErpModule for ConfigModule {
    fn name(&self) -> &str {
        "config"
    }

    fn version(&self) -> &str {
        env!("CARGO_PKG_VERSION")
    }

    fn dependencies(&self) -> Vec<&str> {
        vec!["auth"]
    }

    fn register_event_handlers(&self, _bus: &EventBus) {}

    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(())
    }

    fn permissions(&self) -> Vec<PermissionDescriptor> {
        vec![
            PermissionDescriptor {
                code: "dictionary.list".into(),
                name: "查看字典".into(),
                description: "查看数据字典".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "dictionary.create".into(),
                name: "创建字典".into(),
                description: "创建数据字典".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "dictionary.update".into(),
                name: "编辑字典".into(),
                description: "编辑数据字典".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "dictionary.delete".into(),
                name: "删除字典".into(),
                description: "删除数据字典".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "menu.list".into(),
                name: "查看菜单".into(),
                description: "查看菜单配置".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "menu.update".into(),
                name: "编辑菜单".into(),
                description: "编辑菜单配置".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "setting.read".into(),
                name: "查看配置".into(),
                description: "查看系统参数".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "setting.update".into(),
                name: "编辑配置".into(),
                description: "编辑系统参数".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "setting.delete".into(),
                name: "删除配置".into(),
                description: "删除系统参数".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "numbering.list".into(),
                name: "查看编号规则".into(),
                description: "查看编号规则".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "numbering.create".into(),
                name: "创建编号规则".into(),
                description: "创建编号规则".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "numbering.update".into(),
                name: "编辑编号规则".into(),
                description: "编辑编号规则".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "numbering.delete".into(),
                name: "删除编号规则".into(),
                description: "删除编号规则".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "numbering.generate".into(),
                name: "生成编号".into(),
                description: "生成文档编号".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "theme.read".into(),
                name: "查看主题".into(),
                description: "查看主题设置".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "theme.update".into(),
                name: "编辑主题".into(),
                description: "编辑主题设置".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "language.list".into(),
                name: "查看语言".into(),
                description: "查看语言配置".into(),
                module: "config".into(),
            },
            PermissionDescriptor {
                code: "language.update".into(),
                name: "编辑语言".into(),
                description: "编辑语言设置".into(),
                module: "config".into(),
            },
        ]
    }

    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
}
