use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use uuid::Uuid;
use validator::Validate;

// --- Dictionary DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct DictionaryItemResp {
    pub id: Uuid,
    pub dictionary_id: Uuid,
    pub label: String,
    pub value: String,
    pub sort_order: i32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub color: Option<String>,
    pub version: i32,
}

#[derive(Debug, Serialize, ToSchema)]
pub struct DictionaryResp {
    pub id: Uuid,
    pub name: String,
    pub code: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub items: Vec<DictionaryItemResp>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CreateDictionaryReq {
    #[validate(length(min = 1, max = 100, message = "字典名称不能为空"))]
    pub name: String,
    #[validate(length(min = 1, max = 50, message = "字典编码不能为空"))]
    pub code: String,
    pub description: Option<String>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateDictionaryReq {
    #[validate(length(min = 1, max = 100, message = "字典名称不能为空且不超过100字符"))]
    pub name: Option<String>,
    pub description: Option<String>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CreateDictionaryItemReq {
    #[validate(length(min = 1, max = 100, message = "标签不能为空"))]
    pub label: String,
    #[validate(length(min = 1, max = 100, message = "值不能为空"))]
    pub value: String,
    pub sort_order: Option<i32>,
    pub color: Option<String>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateDictionaryItemReq {
    #[validate(length(min = 1, max = 100, message = "标签不能为空且不超过100字符"))]
    pub label: Option<String>,
    #[validate(length(min = 1, max = 100, message = "值不能为空且不超过100字符"))]
    pub value: Option<String>,
    pub sort_order: Option<i32>,
    pub color: Option<String>,
    pub version: i32,
}

// --- Menu DTOs ---

#[derive(Debug, Serialize, ToSchema, Clone)]
pub struct MenuResp {
    pub id: Uuid,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<Uuid>,
    pub title: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub path: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub icon: Option<String>,
    pub sort_order: i32,
    pub visible: bool,
    pub menu_type: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub permission: Option<String>,
    pub children: Vec<MenuResp>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CreateMenuReq {
    pub parent_id: Option<Uuid>,
    #[validate(length(min = 1, max = 100, message = "菜单标题不能为空"))]
    pub title: String,
    pub path: Option<String>,
    pub icon: Option<String>,
    pub sort_order: Option<i32>,
    pub visible: Option<bool>,
    #[validate(length(min = 1, message = "菜单类型不能为空"))]
    pub menu_type: Option<String>,
    pub permission: Option<String>,
    pub role_ids: Option<Vec<Uuid>>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateMenuReq {
    #[validate(length(min = 1, max = 100, message = "菜单标题不能为空且不超过100字符"))]
    pub title: Option<String>,
    pub path: Option<String>,
    pub icon: Option<String>,
    pub sort_order: Option<i32>,
    pub visible: Option<bool>,
    pub permission: Option<String>,
    pub role_ids: Option<Vec<Uuid>>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct BatchSaveMenusReq {
    #[validate(length(min = 1, message = "菜单列表不能为空"), nested)]
    pub menus: Vec<MenuItemReq>,
}

#[derive(Debug, Serialize, Deserialize, Validate, ToSchema)]
pub struct MenuItemReq {
    pub id: Option<Uuid>,
    pub parent_id: Option<Uuid>,
    #[validate(length(min = 1, max = 100, message = "菜单标题不能为空"))]
    pub title: String,
    pub path: Option<String>,
    pub icon: Option<String>,
    pub sort_order: Option<i32>,
    pub visible: Option<bool>,
    pub menu_type: Option<String>,
    pub permission: Option<String>,
    pub role_ids: Option<Vec<Uuid>>,
    /// 乐观锁版本号。更新已有菜单时必填。
    pub version: Option<i32>,
}

// --- Setting DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct SettingResp {
    pub id: Uuid,
    pub scope: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub scope_id: Option<Uuid>,
    pub setting_key: String,
    pub setting_value: serde_json::Value,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateSettingReq {
    pub setting_value: serde_json::Value,
    /// 乐观锁版本号。更新已有设置时必填，创建新设置时忽略。
    pub version: Option<i32>,
}

/// 内部参数结构体，用于减少 SettingService::set 的参数数量。
pub struct SetSettingParams {
    pub key: String,
    pub scope: String,
    pub scope_id: Option<Uuid>,
    pub value: serde_json::Value,
    /// 乐观锁版本号。更新已有设置时用于校验。
    pub version: Option<i32>,
}

// --- Numbering Rule DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct NumberingRuleResp {
    pub id: Uuid,
    pub name: String,
    pub code: String,
    pub prefix: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub date_format: Option<String>,
    pub seq_length: i32,
    pub seq_start: i32,
    pub seq_current: i64,
    pub separator: String,
    pub reset_cycle: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub last_reset_date: Option<String>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CreateNumberingRuleReq {
    #[validate(length(min = 1, max = 100, message = "规则名称不能为空"))]
    pub name: String,
    #[validate(length(min = 1, max = 50, message = "规则编码不能为空"))]
    pub code: String,
    pub prefix: Option<String>,
    pub date_format: Option<String>,
    pub seq_length: Option<i32>,
    pub seq_start: Option<i32>,
    pub separator: Option<String>,
    pub reset_cycle: Option<String>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateNumberingRuleReq {
    #[validate(length(min = 1, max = 100, message = "规则名称不能为空且不超过100字符"))]
    pub name: Option<String>,
    pub prefix: Option<String>,
    pub date_format: Option<String>,
    pub seq_length: Option<i32>,
    pub separator: Option<String>,
    pub reset_cycle: Option<String>,
    pub version: i32,
}

#[derive(Debug, Serialize, ToSchema)]
pub struct GenerateNumberResp {
    pub number: String,
}

// --- Theme DTOs (stored via settings) ---

#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
pub struct ThemeResp {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub primary_color: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub logo_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sidebar_style: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub brand_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub brand_slogan: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub brand_features: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub brand_copyright: Option<String>,
}

/// 品牌信息公开响应（不含内部配置）
#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
pub struct PublicBrandResp {
    pub brand_name: String,
    pub brand_slogan: String,
    pub brand_features: String,
    pub brand_copyright: String,
}

// --- Language DTOs (stored via settings) ---

#[derive(Debug, Serialize, ToSchema)]
pub struct LanguageResp {
    pub code: String,
    pub name: String,
    pub is_active: bool,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateLanguageReq {
    pub is_active: bool,
    #[validate(length(min = 1, max = 100, message = "语言名称不能为空且不超过100字符"))]
    pub name: Option<String>,
}

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

    // ---- CreateDictionaryReq 验证 ----

    #[test]
    fn create_dictionary_req_valid() {
        let req = CreateDictionaryReq {
            name: "状态字典".to_string(),
            code: "status".to_string(),
            description: Some("通用状态".to_string()),
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn create_dictionary_req_empty_name_fails() {
        let req = CreateDictionaryReq {
            name: "".to_string(),
            code: "status".to_string(),
            description: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_req_empty_code_fails() {
        let req = CreateDictionaryReq {
            name: "状态字典".to_string(),
            code: "".to_string(),
            description: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_req_name_too_long_fails() {
        let req = CreateDictionaryReq {
            name: "x".repeat(101),
            code: "status".to_string(),
            description: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_req_code_too_long_fails() {
        let req = CreateDictionaryReq {
            name: "状态字典".to_string(),
            code: "x".repeat(51),
            description: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_req_max_boundary_ok() {
        let req = CreateDictionaryReq {
            name: "x".repeat(100),
            code: "x".repeat(50),
            description: None,
        };
        assert!(req.validate().is_ok());
    }

    // ---- CreateDictionaryItemReq 验证 ----

    #[test]
    fn create_dictionary_item_req_valid() {
        let req = CreateDictionaryItemReq {
            label: "启用".to_string(),
            value: "active".to_string(),
            sort_order: Some(1),
            color: Some("#00FF00".to_string()),
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn create_dictionary_item_req_empty_label_fails() {
        let req = CreateDictionaryItemReq {
            label: "".to_string(),
            value: "active".to_string(),
            sort_order: None,
            color: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_item_req_empty_value_fails() {
        let req = CreateDictionaryItemReq {
            label: "启用".to_string(),
            value: "".to_string(),
            sort_order: None,
            color: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_item_req_label_too_long_fails() {
        let req = CreateDictionaryItemReq {
            label: "x".repeat(101),
            value: "active".to_string(),
            sort_order: None,
            color: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_item_req_value_too_long_fails() {
        let req = CreateDictionaryItemReq {
            label: "启用".to_string(),
            value: "x".repeat(101),
            sort_order: None,
            color: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_dictionary_item_req_min_boundary_ok() {
        let req = CreateDictionaryItemReq {
            label: "x".to_string(),
            value: "x".to_string(),
            sort_order: None,
            color: None,
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn create_dictionary_item_req_max_boundary_ok() {
        let req = CreateDictionaryItemReq {
            label: "x".repeat(100),
            value: "x".repeat(100),
            sort_order: Some(99),
            color: Some("#FFFFFF".to_string()),
        };
        assert!(req.validate().is_ok());
    }

    // ---- CreateMenuReq 验证 ----

    #[test]
    fn create_menu_req_valid() {
        let req = CreateMenuReq {
            parent_id: None,
            title: "系统设置".to_string(),
            path: Some("/settings".to_string()),
            icon: Some("SettingOutlined".to_string()),
            sort_order: Some(1),
            visible: Some(true),
            menu_type: Some("menu".to_string()),
            permission: None,
            role_ids: None,
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn create_menu_req_empty_title_fails() {
        let req = CreateMenuReq {
            parent_id: None,
            title: "".to_string(),
            path: None,
            icon: None,
            sort_order: None,
            visible: None,
            menu_type: None,
            permission: None,
            role_ids: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_menu_req_title_too_long_fails() {
        let req = CreateMenuReq {
            parent_id: None,
            title: "x".repeat(101),
            path: None,
            icon: None,
            sort_order: None,
            visible: None,
            menu_type: None,
            permission: None,
            role_ids: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_menu_req_title_max_boundary_ok() {
        let req = CreateMenuReq {
            parent_id: None,
            title: "x".repeat(100),
            path: None,
            icon: None,
            sort_order: None,
            visible: None,
            menu_type: None,
            permission: None,
            role_ids: None,
        };
        assert!(req.validate().is_ok());
    }

    // ---- BatchSaveMenusReq 验证 ----

    #[test]
    fn batch_save_menus_req_valid() {
        let req = BatchSaveMenusReq {
            menus: vec![MenuItemReq {
                id: None,
                parent_id: None,
                title: "首页".to_string(),
                path: Some("/home".to_string()),
                icon: None,
                sort_order: Some(0),
                visible: Some(true),
                menu_type: Some("menu".to_string()),
                permission: None,
                role_ids: None,
                version: None,
            }],
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn batch_save_menus_req_empty_list_fails() {
        let req = BatchSaveMenusReq { menus: vec![] };
        assert!(req.validate().is_err());
    }

    #[test]
    fn batch_save_menus_req_item_empty_title_fails() {
        let req = BatchSaveMenusReq {
            menus: vec![MenuItemReq {
                id: None,
                parent_id: None,
                title: "".to_string(),
                path: None,
                icon: None,
                sort_order: None,
                visible: None,
                menu_type: None,
                permission: None,
                role_ids: None,
                version: None,
            }],
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn batch_save_menus_req_item_title_too_long_fails() {
        let req = BatchSaveMenusReq {
            menus: vec![MenuItemReq {
                id: None,
                parent_id: None,
                title: "x".repeat(101),
                path: None,
                icon: None,
                sort_order: None,
                visible: None,
                menu_type: None,
                permission: None,
                role_ids: None,
                version: None,
            }],
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn batch_save_menus_req_multiple_items_ok() {
        let req = BatchSaveMenusReq {
            menus: vec![
                MenuItemReq {
                    id: None,
                    parent_id: None,
                    title: "菜单A".to_string(),
                    path: Some("/a".to_string()),
                    icon: None,
                    sort_order: Some(0),
                    visible: Some(true),
                    menu_type: Some("menu".to_string()),
                    permission: None,
                    role_ids: None,
                    version: None,
                },
                MenuItemReq {
                    id: None,
                    parent_id: None,
                    title: "菜单B".to_string(),
                    path: Some("/b".to_string()),
                    icon: None,
                    sort_order: Some(1),
                    visible: Some(true),
                    menu_type: Some("menu".to_string()),
                    permission: None,
                    role_ids: None,
                    version: Some(1),
                },
            ],
        };
        assert!(req.validate().is_ok());
    }

    // ---- CreateNumberingRuleReq 验证 ----

    #[test]
    fn create_numbering_rule_req_valid() {
        let req = CreateNumberingRuleReq {
            name: "订单编号".to_string(),
            code: "ORDER".to_string(),
            prefix: Some("ORD".to_string()),
            date_format: Some("%Y%m%d".to_string()),
            seq_length: Some(4),
            seq_start: Some(1),
            separator: Some("-".to_string()),
            reset_cycle: Some("daily".to_string()),
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn create_numbering_rule_req_empty_name_fails() {
        let req = CreateNumberingRuleReq {
            name: "".to_string(),
            code: "ORDER".to_string(),
            prefix: None,
            date_format: None,
            seq_length: None,
            seq_start: None,
            separator: None,
            reset_cycle: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_numbering_rule_req_empty_code_fails() {
        let req = CreateNumberingRuleReq {
            name: "订单编号".to_string(),
            code: "".to_string(),
            prefix: None,
            date_format: None,
            seq_length: None,
            seq_start: None,
            separator: None,
            reset_cycle: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_numbering_rule_req_name_too_long_fails() {
        let req = CreateNumberingRuleReq {
            name: "x".repeat(101),
            code: "ORDER".to_string(),
            prefix: None,
            date_format: None,
            seq_length: None,
            seq_start: None,
            separator: None,
            reset_cycle: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_numbering_rule_req_code_too_long_fails() {
        let req = CreateNumberingRuleReq {
            name: "订单编号".to_string(),
            code: "x".repeat(51),
            prefix: None,
            date_format: None,
            seq_length: None,
            seq_start: None,
            separator: None,
            reset_cycle: None,
        };
        assert!(req.validate().is_err());
    }

    #[test]
    fn create_numbering_rule_req_max_boundary_ok() {
        let req = CreateNumberingRuleReq {
            name: "x".repeat(100),
            code: "x".repeat(50),
            prefix: None,
            date_format: None,
            seq_length: None,
            seq_start: None,
            separator: None,
            reset_cycle: None,
        };
        assert!(req.validate().is_ok());
    }

    // ---- UpdateSettingReq 验证 ----

    #[test]
    fn update_setting_req_valid() {
        let req = UpdateSettingReq {
            setting_value: serde_json::json!({"key": "value"}),
            version: Some(1),
        };
        assert!(req.validate().is_ok());
    }

    #[test]
    fn update_setting_req_without_version_ok() {
        let req = UpdateSettingReq {
            setting_value: serde_json::json!("hello"),
            version: None,
        };
        assert!(req.validate().is_ok());
    }
}
