//! Admin API module
//!
//! This module provides the AdminApi trait and types for managing
//! IAM users, policies, groups, service accounts, and cluster operations.

mod cluster;
pub mod tier;
mod types;

pub use cluster::{
    BackendInfo, BackendType, BucketsInfo, ClusterInfo, DecommissionPoolStatus, DecommissionStatus,
    DiskInfo, HealDriveInfo, HealDriveInfos, HealResultItem, HealScanMode, HealStartRequest,
    HealStatus, HealTaskRequest, HealingDiskInfo, MemStats, ObjectsInfo, PoolDecommissionInfo,
    PoolErasureSetInfo, PoolStatus, PoolTarget, RebalanceCleanupWarnings, RebalancePoolProgress,
    RebalancePoolStatus, RebalanceStartResult, RebalanceStatus, ServerInfo, UsageInfo,
};
pub use tier::{
    TierAliyun, TierAzure, TierConfig, TierCreds, TierGCS, TierHuaweicloud, TierMinIO, TierR2,
    TierRustFS, TierS3, TierTencent, TierType,
};
pub use types::{
    AccessKeyDetails, AccessKeyInfo, BucketQuota, CreateServiceAccountRequest, Group, GroupStatus,
    LdapAccessKeyInfo, OpenIdAccessKeyInfo, Policy, PolicyEntity, PolicyInfo, ServiceAccount,
    ServiceAccountCreateResponse, ServiceAccountCredentials, SetPolicyRequest,
    UpdateGroupMembersRequest, User, UserStatus,
};

use async_trait::async_trait;

use crate::error::Result;

/// Admin API trait for IAM and cluster management operations
///
/// This trait defines the interface for managing users, policies, groups,
/// service accounts, and cluster operations on S3-compatible storage systems
/// that support the RustFS/MinIO Admin API.
#[async_trait]
pub trait AdminApi: Send + Sync {
    // ==================== Cluster Operations ====================

    /// Get cluster information including servers, disks, and usage
    async fn cluster_info(&self) -> Result<ClusterInfo>;

    /// Get current heal status
    async fn heal_status(&self) -> Result<HealStatus>;

    /// Start a heal operation
    async fn heal_start(&self, request: HealStartRequest) -> Result<HealStatus>;

    /// Get status for a token-scoped heal task
    async fn heal_task_status(&self, request: HealTaskRequest) -> Result<HealStatus>;

    /// Stop a running heal operation
    async fn heal_stop(&self) -> Result<()>;

    /// Stop a token-scoped heal task
    async fn heal_task_stop(&self, request: HealTaskRequest) -> Result<HealStatus>;

    /// List storage pools
    async fn list_pools(&self) -> Result<Vec<PoolStatus>>;

    /// Get storage pool status
    async fn pool_status(&self, target: PoolTarget) -> Result<PoolStatus>;

    /// Start decommissioning one or more storage pools
    async fn decommission_start(&self, target: PoolTarget) -> Result<()>;

    /// Cancel decommissioning a storage pool
    async fn decommission_cancel(&self, target: PoolTarget) -> Result<()>;

    /// Clear failed or canceled decommissioning metadata for a storage pool
    async fn decommission_clear(&self, target: PoolTarget) -> Result<()>;

    /// Get decommissioning status
    async fn decommission_status(&self, target: Option<PoolTarget>) -> Result<DecommissionStatus>;

    /// Start a rebalance operation
    async fn rebalance_start(&self) -> Result<RebalanceStartResult>;

    /// Get rebalance status
    async fn rebalance_status(&self) -> Result<RebalanceStatus>;

    /// Stop a running rebalance operation
    async fn rebalance_stop(&self) -> Result<()>;

    // ==================== User Operations ====================

    /// List all users
    async fn list_users(&self) -> Result<Vec<User>>;

    /// Get user information
    async fn get_user(&self, access_key: &str) -> Result<User>;

    /// Create a new user
    async fn create_user(&self, access_key: &str, secret_key: &str) -> Result<User>;

    /// Delete a user
    async fn delete_user(&self, access_key: &str) -> Result<()>;

    /// Set user status (enable/disable)
    async fn set_user_status(&self, access_key: &str, status: UserStatus) -> Result<()>;

    // ==================== Policy Operations ====================

    /// List all policies
    async fn list_policies(&self) -> Result<Vec<PolicyInfo>>;

    /// Get policy information
    async fn get_policy(&self, name: &str) -> Result<Policy>;

    /// Create a new policy
    async fn create_policy(&self, name: &str, policy_document: &str) -> Result<()>;

    /// Delete a policy
    async fn delete_policy(&self, name: &str) -> Result<()>;

    /// Attach policy to a user or group
    async fn attach_policy(
        &self,
        policy_names: &[String],
        entity_type: PolicyEntity,
        entity_name: &str,
    ) -> Result<()>;

    /// Detach policy from a user or group
    async fn detach_policy(
        &self,
        policy_names: &[String],
        entity_type: PolicyEntity,
        entity_name: &str,
    ) -> Result<()>;

    // ==================== Group Operations ====================

    /// List all groups
    async fn list_groups(&self) -> Result<Vec<String>>;

    /// Get group information
    async fn get_group(&self, name: &str) -> Result<Group>;

    /// Create a new group
    async fn create_group(&self, name: &str, members: Option<&[String]>) -> Result<Group>;

    /// Delete a group
    async fn delete_group(&self, name: &str) -> Result<()>;

    /// Set group status (enable/disable)
    async fn set_group_status(&self, name: &str, status: GroupStatus) -> Result<()>;

    /// Add members to a group
    async fn add_group_members(&self, group: &str, members: &[String]) -> Result<()>;

    /// Remove members from a group
    async fn remove_group_members(&self, group: &str, members: &[String]) -> Result<()>;

    // ==================== Service Account Operations ====================

    /// List service accounts for a user
    async fn list_service_accounts(&self, user: Option<&str>) -> Result<Vec<ServiceAccount>>;

    /// Get service account information
    async fn get_service_account(&self, access_key: &str) -> Result<ServiceAccount>;

    /// Create a new service account
    async fn create_service_account(
        &self,
        request: CreateServiceAccountRequest,
    ) -> Result<ServiceAccount>;

    /// Delete a service account
    async fn delete_service_account(&self, access_key: &str) -> Result<()>;

    /// Get information for any access key type.
    async fn get_access_key_info(&self, access_key: &str) -> Result<AccessKeyInfo>;

    // ==================== Bucket Quota Operations ====================

    /// Set bucket quota in bytes
    async fn set_bucket_quota(&self, bucket: &str, quota: u64) -> Result<BucketQuota>;

    /// Get bucket quota information
    async fn get_bucket_quota(&self, bucket: &str) -> Result<BucketQuota>;

    /// Clear bucket quota
    async fn clear_bucket_quota(&self, bucket: &str) -> Result<BucketQuota>;

    // ==================== Tier Operations ====================

    /// List all configured storage tiers
    async fn list_tiers(&self) -> Result<Vec<TierConfig>>;

    /// Get tier statistics
    async fn tier_stats(&self) -> Result<serde_json::Value>;

    /// Add a new storage tier
    async fn add_tier(&self, config: TierConfig) -> Result<()>;

    /// Edit tier credentials
    async fn edit_tier(&self, name: &str, creds: TierCreds) -> Result<()>;

    /// Remove a storage tier
    async fn remove_tier(&self, name: &str, force: bool) -> Result<()>;

    // ==================== Replication Target Operations ====================

    /// Set a remote replication target for a bucket, returns the ARN
    async fn set_remote_target(
        &self,
        bucket: &str,
        target: crate::replication::BucketTarget,
        update: bool,
    ) -> Result<String>;

    /// List remote replication targets for a bucket
    async fn list_remote_targets(
        &self,
        bucket: &str,
    ) -> Result<Vec<crate::replication::BucketTarget>>;

    /// Remove a remote replication target
    async fn remove_remote_target(&self, bucket: &str, arn: &str) -> Result<()>;

    /// Get replication metrics for a bucket
    async fn replication_metrics(&self, bucket: &str) -> Result<serde_json::Value>;
}

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

    // Test that types are re-exported correctly
    #[test]
    fn test_user_status_reexport() {
        assert_eq!(UserStatus::Enabled.to_string(), "enabled");
        assert_eq!(UserStatus::Disabled.to_string(), "disabled");
    }

    #[test]
    fn test_group_status_reexport() {
        assert_eq!(GroupStatus::Enabled.to_string(), "enabled");
        assert_eq!(GroupStatus::Disabled.to_string(), "disabled");
    }

    #[test]
    fn test_policy_entity_reexport() {
        assert_eq!(PolicyEntity::User.to_string(), "user");
        assert_eq!(PolicyEntity::Group.to_string(), "group");
    }

    #[test]
    fn test_user_new() {
        let user = User::new("testuser");
        assert_eq!(user.access_key, "testuser");
        assert_eq!(user.status, UserStatus::Enabled);
    }

    #[test]
    fn test_group_new() {
        let group = Group::new("developers");
        assert_eq!(group.name, "developers");
        assert_eq!(group.status, GroupStatus::Enabled);
    }

    #[test]
    fn test_policy_new() {
        let policy = Policy::new("readonly", r#"{"Version":"2012-10-17","Statement":[]}"#);
        assert_eq!(policy.name, "readonly");
        assert!(policy.parse_document().is_ok());
    }

    #[test]
    fn test_service_account_new() {
        let sa = ServiceAccount::new("AKIAIOSFODNN7EXAMPLE");
        assert_eq!(sa.access_key, "AKIAIOSFODNN7EXAMPLE");
        assert!(sa.secret_key.is_none());
    }
}
