use sea_orm::{ActiveModelTrait, Set};
use uuid::Uuid;

use crate::entity::{permission, role, role_permission, user, user_credential, user_role};
use crate::error::AuthError;

use super::password;

/// Permission definitions to seed for every new tenant.
/// Each tuple is: (code, name, resource, action, description)
///
/// 编码使用点分隔 (`resource.action`)，与 handler 中的 `require_permission` 调用保持一致。
const DEFAULT_PERMISSIONS: &[(&str, &str, &str, &str, &str)] = &[
    // === Auth module ===
    ("user.list", "查看用户列表", "user", "list", "查看用户列表"),
    ("user.create", "创建用户", "user", "create", "创建新用户"),
    ("user.read", "查看用户详情", "user", "read", "查看用户信息"),
    ("user.update", "编辑用户", "user", "update", "编辑用户信息"),
    ("user.delete", "删除用户", "user", "delete", "软删除用户"),
    ("role.list", "查看角色列表", "role", "list", "查看角色列表"),
    ("role.create", "创建角色", "role", "create", "创建新角色"),
    ("role.read", "查看角色详情", "role", "read", "查看角色信息"),
    ("role.update", "编辑角色", "role", "update", "编辑角色"),
    ("role.delete", "删除角色", "role", "delete", "删除角色"),
    (
        "permission.list",
        "查看权限",
        "permission",
        "list",
        "查看权限列表",
    ),
    (
        "organization.list",
        "查看组织列表",
        "organization",
        "list",
        "查看组织列表",
    ),
    (
        "organization.create",
        "创建组织",
        "organization",
        "create",
        "创建组织",
    ),
    (
        "organization.update",
        "编辑组织",
        "organization",
        "update",
        "编辑组织",
    ),
    (
        "organization.delete",
        "删除组织",
        "organization",
        "delete",
        "删除组织",
    ),
    (
        "department.list",
        "查看部门列表",
        "department",
        "list",
        "查看部门列表",
    ),
    (
        "department.create",
        "创建部门",
        "department",
        "create",
        "创建部门",
    ),
    (
        "department.update",
        "编辑部门",
        "department",
        "update",
        "编辑部门",
    ),
    (
        "department.delete",
        "删除部门",
        "department",
        "delete",
        "删除部门",
    ),
    (
        "position.list",
        "查看岗位列表",
        "position",
        "list",
        "查看岗位列表",
    ),
    (
        "position.create",
        "创建岗位",
        "position",
        "create",
        "创建岗位",
    ),
    (
        "position.update",
        "编辑岗位",
        "position",
        "update",
        "编辑岗位",
    ),
    (
        "position.delete",
        "删除岗位",
        "position",
        "delete",
        "删除岗位",
    ),
    // === Config module ===
    (
        "dictionary.list",
        "查看字典",
        "dictionary",
        "list",
        "查看数据字典",
    ),
    (
        "dictionary.create",
        "创建字典",
        "dictionary",
        "create",
        "创建数据字典",
    ),
    (
        "dictionary.update",
        "编辑字典",
        "dictionary",
        "update",
        "编辑数据字典",
    ),
    (
        "dictionary.delete",
        "删除字典",
        "dictionary",
        "delete",
        "删除数据字典",
    ),
    ("menu.list", "查看菜单", "menu", "list", "查看菜单配置"),
    ("menu.update", "编辑菜单", "menu", "update", "编辑菜单配置"),
    (
        "setting.read",
        "查看配置",
        "setting",
        "read",
        "查看系统参数",
    ),
    (
        "setting.update",
        "编辑配置",
        "setting",
        "update",
        "编辑系统参数",
    ),
    (
        "setting.delete",
        "删除配置",
        "setting",
        "delete",
        "删除系统参数",
    ),
    (
        "numbering.list",
        "查看编号规则",
        "numbering",
        "list",
        "查看编号规则",
    ),
    (
        "numbering.create",
        "创建编号规则",
        "numbering",
        "create",
        "创建编号规则",
    ),
    (
        "numbering.update",
        "编辑编号规则",
        "numbering",
        "update",
        "编辑编号规则",
    ),
    (
        "numbering.delete",
        "删除编号规则",
        "numbering",
        "delete",
        "删除编号规则",
    ),
    (
        "numbering.generate",
        "生成编号",
        "numbering",
        "generate",
        "生成文档编号",
    ),
    ("theme.read", "查看主题", "theme", "read", "查看主题设置"),
    (
        "theme.update",
        "编辑主题",
        "theme",
        "update",
        "编辑主题设置",
    ),
    (
        "language.list",
        "查看语言",
        "language",
        "list",
        "查看语言配置",
    ),
    (
        "language.update",
        "编辑语言",
        "language",
        "update",
        "编辑语言设置",
    ),
    // === Workflow module ===
    (
        "workflow.create",
        "创建流程",
        "workflow",
        "create",
        "创建流程定义",
    ),
    (
        "workflow.list",
        "查看流程",
        "workflow",
        "list",
        "查看流程列表",
    ),
    (
        "workflow.read",
        "查看流程详情",
        "workflow",
        "read",
        "查看流程定义详情",
    ),
    (
        "workflow.update",
        "编辑流程",
        "workflow",
        "update",
        "编辑流程定义",
    ),
    (
        "workflow.publish",
        "发布流程",
        "workflow",
        "publish",
        "发布流程定义",
    ),
    (
        "workflow.start",
        "发起流程",
        "workflow",
        "start",
        "发起流程实例",
    ),
    (
        "workflow.approve",
        "审批任务",
        "workflow",
        "approve",
        "审批流程任务",
    ),
    (
        "workflow.delegate",
        "委派任务",
        "workflow",
        "delegate",
        "委派流程任务",
    ),
    // === Message module ===
    (
        "message.list",
        "查看消息",
        "message",
        "list",
        "查看消息列表",
    ),
    ("message.send", "发送消息", "message", "send", "发送新消息"),
    (
        "message.template.list",
        "查看消息模板",
        "message.template",
        "list",
        "查看消息模板列表",
    ),
    (
        "message.template.create",
        "创建消息模板",
        "message.template",
        "create",
        "创建消息模板",
    ),
    (
        "message.template.manage",
        "管理消息模板",
        "message.template",
        "manage",
        "编辑、删除消息模板",
    ),
    // === Plugin module ===
    (
        "plugin.admin",
        "插件管理",
        "plugin",
        "admin",
        "管理插件全生命周期",
    ),
    ("plugin.list", "查看插件", "plugin", "list", "查看插件列表"),
    // === Server level ===
    (
        "tenant.manage",
        "租户管理",
        "tenant",
        "manage",
        "管理租户级设置（密钥轮换等）",
    ),
];

/// Indices of read-only (list/read) permissions within DEFAULT_PERMISSIONS.
const READ_PERM_INDICES: &[usize] = &[
    0,  // user.list
    2,  // user.read
    5,  // role.list
    7,  // role.read
    10, // permission.list
    11, // organization.list
    15, // department.list
    19, // position.list
    23, // dictionary.list
    28, // menu.list
    30, // setting.read
    32, // numbering.list
    37, // theme.read
    39, // language.list
    43, // workflow.list
    44, // workflow.read
    49, // message.list
    51, // message.template.list
    54, // plugin.list
];

/// Seed default auth data for a new tenant.
///
/// Creates:
/// - 56 permissions covering auth/config/workflow/message/plugin modules
/// - An "admin" system role with all permissions
/// - A "viewer" system role with read-only permissions
/// - A super-admin user with the admin role and a password credential
pub async fn seed_tenant_auth(
    db: &sea_orm::DatabaseConnection,
    tenant_id: Uuid,
    super_admin_password: &str,
) -> Result<(), AuthError> {
    let now = chrono::Utc::now();
    let system_user_id = Uuid::nil();

    // 1. Create permissions
    let mut perm_ids: Vec<Uuid> = Vec::with_capacity(DEFAULT_PERMISSIONS.len());
    for (code, name, resource, action, desc) in DEFAULT_PERMISSIONS {
        let perm_id = Uuid::now_v7();
        perm_ids.push(perm_id);

        let perm = permission::ActiveModel {
            id: Set(perm_id),
            tenant_id: Set(tenant_id),
            code: Set(code.to_string()),
            name: Set(name.to_string()),
            resource: Set(resource.to_string()),
            action: Set(action.to_string()),
            description: Set(Some(desc.to_string())),
            created_at: Set(now),
            updated_at: Set(now),
            created_by: Set(system_user_id),
            updated_by: Set(system_user_id),
            deleted_at: Set(None),
            version: Set(1),
        };
        perm.insert(db)
            .await
            .map_err(|e| AuthError::Validation(e.to_string()))?;
    }

    // 2. Create "admin" role with all permissions
    let admin_role_id = Uuid::now_v7();
    let admin_role = role::ActiveModel {
        id: Set(admin_role_id),
        tenant_id: Set(tenant_id),
        name: Set("管理员".to_string()),
        code: Set("admin".to_string()),
        description: Set(Some("系统管理员，拥有所有权限".to_string())),
        is_system: Set(true),
        created_at: Set(now),
        updated_at: Set(now),
        created_by: Set(system_user_id),
        updated_by: Set(system_user_id),
        deleted_at: Set(None),
        version: Set(1),
    };
    admin_role
        .insert(db)
        .await
        .map_err(|e| AuthError::Validation(e.to_string()))?;

    // Assign all permissions to admin role
    for perm_id in &perm_ids {
        let rp = role_permission::ActiveModel {
            role_id: Set(admin_role_id),
            permission_id: Set(*perm_id),
            tenant_id: Set(tenant_id),
            data_scope: Set("all".to_string()),
            created_at: Set(now),
            updated_at: Set(now),
            created_by: Set(system_user_id),
            updated_by: Set(system_user_id),
            deleted_at: Set(None),
            version: Set(1),
        };
        rp.insert(db)
            .await
            .map_err(|e| AuthError::Validation(e.to_string()))?;
    }

    // 3. Create "viewer" role with read-only permissions
    let viewer_role_id = Uuid::now_v7();
    let viewer_role = role::ActiveModel {
        id: Set(viewer_role_id),
        tenant_id: Set(tenant_id),
        name: Set("查看者".to_string()),
        code: Set("viewer".to_string()),
        description: Set(Some("只读用户，可查看所有数据".to_string())),
        is_system: Set(true),
        created_at: Set(now),
        updated_at: Set(now),
        created_by: Set(system_user_id),
        updated_by: Set(system_user_id),
        deleted_at: Set(None),
        version: Set(1),
    };
    viewer_role
        .insert(db)
        .await
        .map_err(|e| AuthError::Validation(e.to_string()))?;

    // Assign read permissions to viewer role
    for idx in READ_PERM_INDICES {
        if *idx < perm_ids.len() {
            let rp = role_permission::ActiveModel {
                role_id: Set(viewer_role_id),
                permission_id: Set(perm_ids[*idx]),
                tenant_id: Set(tenant_id),
                data_scope: Set("all".to_string()),
                created_at: Set(now),
                updated_at: Set(now),
                created_by: Set(system_user_id),
                updated_by: Set(system_user_id),
                deleted_at: Set(None),
                version: Set(1),
            };
            rp.insert(db)
                .await
                .map_err(|e| AuthError::Validation(e.to_string()))?;
        }
    }

    // 4. Create super admin user
    let admin_user_id = Uuid::now_v7();
    let password_hash = password::hash_password(super_admin_password)?;

    let admin_user = user::ActiveModel {
        id: Set(admin_user_id),
        tenant_id: Set(tenant_id),
        username: Set("admin".to_string()),
        email: Set(None),
        phone: Set(None),
        display_name: Set(Some("系统管理员".to_string())),
        avatar_url: Set(None),
        status: Set("active".to_string()),
        last_login_at: Set(None),
        created_at: Set(now),
        updated_at: Set(now),
        created_by: Set(system_user_id),
        updated_by: Set(system_user_id),
        deleted_at: Set(None),
        version: Set(1),
    };
    admin_user
        .insert(db)
        .await
        .map_err(|e| AuthError::Validation(e.to_string()))?;

    // Create password credential for admin user
    let cred = user_credential::ActiveModel {
        id: Set(Uuid::now_v7()),
        tenant_id: Set(tenant_id),
        user_id: Set(admin_user_id),
        credential_type: Set("password".to_string()),
        credential_data: Set(Some(serde_json::json!({ "hash": password_hash }))),
        verified: Set(true),
        created_at: Set(now),
        updated_at: Set(now),
        created_by: Set(system_user_id),
        updated_by: Set(system_user_id),
        deleted_at: Set(None),
        version: Set(1),
    };
    cred.insert(db)
        .await
        .map_err(|e| AuthError::Validation(e.to_string()))?;

    // 5. Assign admin role to admin user
    let user_role_assignment = user_role::ActiveModel {
        user_id: Set(admin_user_id),
        role_id: Set(admin_role_id),
        tenant_id: Set(tenant_id),
        created_at: Set(now),
        updated_at: Set(now),
        created_by: Set(system_user_id),
        updated_by: Set(system_user_id),
        deleted_at: Set(None),
        version: Set(1),
    };
    user_role_assignment
        .insert(db)
        .await
        .map_err(|e| AuthError::Validation(e.to_string()))?;

    tracing::info!(
        tenant_id = %tenant_id,
        admin_user_id = %admin_user_id,
        "Seeded tenant auth: admin user, 2 roles, {} permissions",
        DEFAULT_PERMISSIONS.len()
    );

    Ok(())
}
