"""
Keycloak Authentication - Models, Config, and Exceptions.
"""

import os
import logging
from typing import Optional, Dict, Any, List
from dataclasses import dataclass

logger = logging.getLogger(__name__)


@dataclass
class KeycloakConfig:
    """Keycloak connection configuration."""
    server_url: str
    realm: str
    client_id: str
    client_secret: Optional[str] = None
    verify_ssl: bool = True

    @property
    def issuer_url(self) -> str:
        return f"{self.server_url}/realms/{self.realm}"

    @property
    def jwks_url(self) -> str:
        return f"{self.issuer_url}/protocol/openid-connect/certs"

    @property
    def token_url(self) -> str:
        return f"{self.issuer_url}/protocol/openid-connect/token"

    @property
    def userinfo_url(self) -> str:
        return f"{self.issuer_url}/protocol/openid-connect/userinfo"


@dataclass
class KeycloakUser:
    """User information extracted from Keycloak token."""
    user_id: str
    email: str
    email_verified: bool
    name: Optional[str]
    given_name: Optional[str]
    family_name: Optional[str]
    realm_roles: List[str]
    client_roles: Dict[str, List[str]]
    groups: List[str]
    tenant_id: Optional[str]
    raw_claims: Dict[str, Any]

    def has_realm_role(self, role: str) -> bool:
        return role in self.realm_roles

    def has_client_role(self, client_id: str, role: str) -> bool:
        client_roles = self.client_roles.get(client_id, [])
        return role in client_roles

    def is_admin(self) -> bool:
        return self.has_realm_role("admin") or self.has_realm_role("schul_admin")

    def is_teacher(self) -> bool:
        return self.has_realm_role("teacher") or self.has_realm_role("lehrer")


class KeycloakAuthError(Exception):
    """Base exception for Keycloak authentication errors."""
    pass


class TokenExpiredError(KeycloakAuthError):
    """Token has expired."""
    pass


class TokenInvalidError(KeycloakAuthError):
    """Token is invalid."""
    pass


class KeycloakConfigError(KeycloakAuthError):
    """Keycloak configuration error."""
    pass


def get_keycloak_config_from_env() -> Optional[KeycloakConfig]:
    """Create KeycloakConfig from environment variables."""
    server_url = os.environ.get("KEYCLOAK_SERVER_URL")
    realm = os.environ.get("KEYCLOAK_REALM")
    client_id = os.environ.get("KEYCLOAK_CLIENT_ID")

    if not all([server_url, realm, client_id]):
        logger.info("Keycloak not configured, using local JWT only")
        return None

    return KeycloakConfig(
        server_url=server_url,
        realm=realm,
        client_id=client_id,
        client_secret=os.environ.get("KEYCLOAK_CLIENT_SECRET"),
        verify_ssl=os.environ.get("KEYCLOAK_VERIFY_SSL", "true").lower() == "true"
    )
