"""
Credential Resolution - Key Vault Integration

Secrets are stored directly in the source config YAML under the 'secrets' key.
Each value is a Key Vault secret name that gets resolved at runtime.

Example source config:
    secrets:
      access_token: my-notion-access-token
      database_id: my-notion-db-id

The secret names are resolved via notebookutils.credentials.getSecret()
using a central Key Vault URL provided as a parameter.
"""

import re
from typing import Any, Dict, Optional


class CredentialResolver:
    """
    Resolves credentials from source config secrets and Key Vault.

    Usage:
        resolver = CredentialResolver(vault_url="https://my-vault.vault.azure.net/")
        creds = resolver.resolve_from_source_config(source_config)
        # creds = {"access_token": "actual_secret_value", "database_id": "actual_value"}
    """

    def __init__(self, vault_url: str):
        """
        Initialize credential resolver.

        Args:
            vault_url: Azure Key Vault URL
        """
        self.vault_url = vault_url
        self._cache: Dict[str, str] = {}

    @staticmethod
    def _strip_ref(value: str) -> str:
        """Strip legacy ${...} wrapper from secret names if present."""
        if value.startswith("${") and value.endswith("}"):
            return value[2:-1]
        return value

    def _get_secret(self, secret_name: str) -> str:
        """
        Fetch a secret from Key Vault.

        Uses caching to avoid repeated calls for the same secret.

        Args:
            secret_name: Name of the secret in Key Vault

        Returns:
            Secret value
        """
        secret_name = self._strip_ref(secret_name)
        if secret_name in self._cache:
            return self._cache[secret_name]

        try:
            import notebookutils
            value = notebookutils.credentials.getSecret(self.vault_url, secret_name)
        except ImportError:
            # For local testing, try environment variable
            import os
            value = os.environ.get(f"SECRET_{secret_name.replace('-', '_').upper()}", "")
            if not value:
                raise RuntimeError(
                    f"notebookutils not available and no env var found for: {secret_name}"
                )

        self._cache[secret_name] = value
        return value

    def resolve_from_source_config(
        self,
        source_config: Dict[str, Any],
    ) -> Dict[str, str]:
        """
        Resolve credentials from a source config's secrets dict.

        Each value in the secrets dict is a Key Vault secret name
        that gets resolved to its actual value.

        Args:
            source_config: Source configuration dictionary with 'secrets' key

        Returns:
            Dictionary of field name to credential value

        Raises:
            ValueError: If no secrets specified in source config
        """
        secrets = source_config.get("secrets")
        if not secrets:
            raise ValueError("No 'secrets' specified in source config")

        resolved = {}
        for field_name, secret_name in secrets.items():
            if isinstance(secret_name, str) and secret_name:
                resolved[field_name] = self._get_secret(secret_name)
            else:
                resolved[field_name] = secret_name

        return resolved


def resolve_credentials(
    source_config: Dict[str, Any],
    vault_url: str,
) -> Dict[str, str]:
    """
    Convenience function to resolve credentials from source config.

    Args:
        source_config: Source configuration with 'secrets' key
        vault_url: Azure Key Vault URL

    Returns:
        Dictionary of resolved credentials
    """
    resolver = CredentialResolver(vault_url)
    return resolver.resolve_from_source_config(source_config)
