"""Multi-tenancy support for tenant-scoped authorization.

Provides tenant isolation so Tenant A's "admin" role is completely independent
of Tenant B's "admin" role. The engine evaluates only within the active
tenant's scope.

Usage:
    rp = PyAuthz()
    rp.add_role(Role(name="admin", permissions=["*:*"]), tenant="acme")
    rp.add_role(Role(name="admin", permissions=["documents:read"]), tenant="globex")

    # Evaluates only against acme's roles and policies
    rp.is_allowed(user, "write", doc, tenant_id="acme")
"""

from __future__ import annotations

from pyauthz.core.errors import ConfigError
from pyauthz.models.policy import Policy
from pyauthz.models.role import Role
from pyauthz.storage.memory import MemoryStorage


class TenantManager:
    """Manages tenant-scoped roles and policies.

    Each tenant has its own isolated set of roles and policies stored in
    a separate MemoryStorage instance. The default tenant (None) represents
    the global/shared scope.
    """

    def __init__(self) -> None:
        self._tenants: dict[str, MemoryStorage] = {}

    def get_storage(self, tenant: str) -> MemoryStorage:
        """Get or create the storage for a tenant.

        Args:
            tenant: The tenant identifier.

        Returns:
            The MemoryStorage for this tenant.
        """
        if tenant not in self._tenants:
            self._tenants[tenant] = MemoryStorage()
        return self._tenants[tenant]

    def has_tenant(self, tenant: str) -> bool:
        """Check if a tenant has been created."""
        return tenant in self._tenants

    def list_tenants(self) -> list[str]:
        """List all tenant identifiers."""
        return list(self._tenants.keys())

    def remove_tenant(self, tenant: str) -> None:
        """Remove a tenant and all its roles/policies.

        Raises:
            ConfigError: If the tenant does not exist.
        """
        if tenant not in self._tenants:
            raise ConfigError(f"Tenant '{tenant}' not found")
        del self._tenants[tenant]

    def add_role(self, role: Role, tenant: str) -> None:
        """Add a role to a specific tenant."""
        storage = self.get_storage(tenant)
        storage.add_role(role)

    def add_policy(self, policy: Policy, tenant: str) -> None:
        """Add a policy to a specific tenant."""
        storage = self.get_storage(tenant)
        storage.add_policy(policy)
