// Copyright (c) 2026 Kirky.X
//
// Licensed under the MIT License
// See LICENSE file in the project root for full license information.

//! Permission 单元测试

use dbnexus::permission::{PermissionAction, PermissionConfig, PermissionContext, RolePolicy, TablePermission};
use std::num::NonZeroUsize;
use std::sync::Arc;
use tokio::sync::RwLock;

mod advanced_test;
mod provider_test;
mod rbac_test;

/// TEST-P-001: 缓存失效测试
#[tokio::test]
async fn test_cache_invalidation() {
    let config = Arc::new(PermissionConfig {
        roles: vec![(
            "admin".to_string(),
            RolePolicy {
                tables: vec![TablePermission {
                    name: "users".to_string(),
                    operations: vec![PermissionAction::Select],
                }],
            },
        )]
        .into_iter()
        .collect(),
    });

    let cache = Arc::new(RwLock::new(lru::LruCache::new(NonZeroUsize::new(256).unwrap())));

    let mut ctx = PermissionContext::with_config("admin".to_string(), cache.clone(), config.clone());

    // 第一次检查应该从配置加载
    assert!(ctx.check_table_access("users", &PermissionAction::Select).await);

    // 失效缓存
    ctx.invalidate_cache().await;

    // 修改配置
    let new_config = Arc::new(PermissionConfig {
        roles: vec![(
            "admin".to_string(),
            RolePolicy {
                tables: vec![TablePermission {
                    name: "users".to_string(),
                    operations: vec![PermissionAction::Select, PermissionAction::Insert],
                }],
            },
        )]
        .into_iter()
        .collect(),
    });

    ctx.update_config(new_config);

    // 第二次检查应该从新配置加载
    assert!(ctx.check_table_access("users", &PermissionAction::Insert).await);
}

/// TEST-P-002: 通配符访问限制测试
#[tokio::test]
async fn test_wildcard_system_table_restriction() {
    let policy = RolePolicy {
        tables: vec![TablePermission {
            name: "*".to_string(),
            operations: vec![PermissionAction::Select],
        }],
    };

    // 允许访问普通表
    assert!(policy.allows("users", &PermissionAction::Select));

    // 拒绝访问系统表
    assert!(!policy.allows("sqlite_master", &PermissionAction::Select));
    assert!(!policy.allows("sqlite_sequence", &PermissionAction::Select));
    assert!(!policy.allows("information_schema.columns", &PermissionAction::Select));
    assert!(!policy.allows("pg_catalog.pg_tables", &PermissionAction::Select));
    assert!(!policy.allows("mysql.user", &PermissionAction::Select));
}

/// TEST-P-003: 角色验证测试
#[tokio::test]
async fn test_role_validation() {
    let config = PermissionConfig {
        roles: vec![
            (
                "admin".to_string(),
                RolePolicy {
                    tables: vec![TablePermission {
                        name: "*".to_string(),
                        operations: vec![PermissionAction::Select],
                    }],
                },
            ),
            (
                "user".to_string(),
                RolePolicy {
                    tables: vec![TablePermission {
                        name: "users".to_string(),
                        operations: vec![PermissionAction::Select],
                    }],
                },
            ),
        ]
        .into_iter()
        .collect(),
    };

    // 预定义角色应该被识别
    assert!(config.is_role_defined("admin"));
    assert!(config.is_role_defined("user"));

    // 未定义的角色应该被拒绝
    assert!(!config.is_role_defined("guest"));
    assert!(!config.is_role_defined("hacker"));
}

/// TEST-P-004: 缓存自动加载测试
#[tokio::test]
async fn test_cache_auto_load() {
    let config = Arc::new(PermissionConfig {
        roles: vec![(
            "admin".to_string(),
            RolePolicy {
                tables: vec![TablePermission {
                    name: "users".to_string(),
                    operations: vec![PermissionAction::Select],
                }],
            },
        )]
        .into_iter()
        .collect(),
    });

    let cache = Arc::new(RwLock::new(lru::LruCache::new(NonZeroUsize::new(256).unwrap())));

    let ctx = PermissionContext::with_config("admin".to_string(), cache.clone(), config.clone());

    // 缓存为空，应该自动加载
    assert!(ctx.check_table_access("users", &PermissionAction::Select).await);

    // 缓存已加载，应该从缓存读取
    assert!(ctx.check_table_access("users", &PermissionAction::Select).await);
}
