from bfabric import Bfabric, BfabricAuth, BfabricClientConfig
from bfabric.config.config_data import ConfigData
from cachetools import TTLCache
from loguru import logger

from bfabric_web_apps.utils.config import settings
from bfabric_web_apps.utils.url_utils import normalize_url

# Cache for power user wrappers, keyed by normalized base_url
# TTL of 1 hour, max 10 instances (one per B-Fabric instance)
_power_user_cache = TTLCache(maxsize=10, ttl=3600)


def get_power_user_wrapper(token_data):
    """
    Initializes and returns a Bfabric power user instance for the given B-Fabric instance.

    Reads power user credentials from settings based on the base_url from token_data.
    Results are cached per base_url to avoid re-creating wrappers.

    Args:
        token_data (dict): A dictionary containing token information.
            Required key: "webbase_data" - the B-Fabric base URL

    Returns:
        Bfabric: A Bfabric instance initialized with power user credentials
        for the same B-Fabric instance as the token.

    Raises:
        ValueError: If webbase_data is missing or credentials are not configured.
    """
    base_url = token_data.get("webbase_data")

    if not base_url:
        raise ValueError("token_data must contain 'webbase_data' field")

    # Normalize URL for cache key
    normalized_base_url = normalize_url(base_url)

    # Check cache first
    if normalized_base_url in _power_user_cache:
        return _power_user_cache[normalized_base_url]

    normalized_credentials = {normalize_url(url): creds
                             for url, creds in settings.POWER_USER_CREDENTIALS.items()}

    # Get power user credentials for this instance
    credentials = normalized_credentials.get(normalized_base_url)
    if not credentials:
        raise ValueError(
            f"No power user credentials configured for B-Fabric instance '{base_url}'. "
            f"Please add credentials to POWER_USER_CREDENTIALS in settings."
        )

    client_config = BfabricClientConfig(base_url=base_url)
    config_data = ConfigData(client=client_config, auth=credentials)
    wrapper = Bfabric(config_data=config_data)

    # Cache for future requests
    _power_user_cache[normalized_base_url] = wrapper

    logger.info(f"Cached power user wrapper for {credentials.login}")

    return wrapper