import re
from dataclasses import dataclass
from typing import Dict, Pattern, Tuple

from auditor.core.base import Validator
from auditor.validators.llm import (
    OpenAIValidator,
    AnthropicValidator,
    GeminiValidator,
    DeepSeekValidator,
    GroqValidator,
    PerplexityValidator,
    HuggingFaceValidator,
)


@dataclass(frozen=True)
class ProviderConfig:
    """Configuration for an API provider."""
    pattern: Pattern[str]
    validator: Validator


class ValidatorFactory:
    """
    Factory class that manages validator registration and lookup.
    
    This class follows the Factory pattern and provides a centralized
    registry for API key patterns and their validators. New providers
    can be added by calling the register() method.
    
    Attributes:
        _registry: Internal storage for provider configurations
        
    Example:
        # Register a custom validator
        ValidatorFactory.register(
            "custom",
            r"custom-[a-z0-9]{32}",
            CustomValidator()
        )
        
        # Get all registered providers
        for name, config in ValidatorFactory.get_all().items():
            print(f"{name}: {config.pattern.pattern}")
    """
    
    _registry: Dict[str, ProviderConfig] = {}
    
    @classmethod
    def _initialize_defaults(cls) -> None:
        """Initialize the factory with default provider configurations."""
        defaults = {
            "anthropic": (r'sk-ant-api03-[a-zA-Z0-9-]{80,}', AnthropicValidator()),
            "openai": (r'sk-[a-zA-Z0-9]{48,}', OpenAIValidator()),
            "deepseek": (r'sk-[a-fA-F0-9]{32}', DeepSeekValidator()),
            "gemini": (r'AIzaSy[a-zA-Z0-9_-]{33}', GeminiValidator()),
            "groq": (r'gsk_[a-zA-Z0-9]{36}', GroqValidator()),
            "perplexity": (r'pplx-[a-zA-Z0-9]{43}', PerplexityValidator()),
            "huggingface": (r'hf_[a-zA-Z0-9]{34}', HuggingFaceValidator()),
        }
        
        for name, (pattern, validator) in defaults.items():
            cls._registry[name] = ProviderConfig(
                pattern=re.compile(pattern),
                validator=validator
            )
    
    @classmethod
    def register(cls, name: str, pattern: str, validator: Validator) -> None:
        """
        Register a new provider configuration.
        
        Args:
            name: Unique identifier for the provider
            pattern: Regex pattern to match API keys
            validator: Validator instance to verify keys
            
        Raises:
            ValueError: If name is already registered
        """
        if name in cls._registry:
            raise ValueError(f"Provider '{name}' is already registered")
        
        cls._registry[name] = ProviderConfig(
            pattern=re.compile(pattern),
            validator=validator
        )
    
    @classmethod
    def unregister(cls, name: str) -> bool:
        """
        Remove a provider from the registry.
        
        Args:
            name: The provider name to remove
            
        Returns:
            True if removed, False if not found
        """
        if name in cls._registry:
            del cls._registry[name]
            return True
        return False
    
    @classmethod
    def get(cls, name: str) -> ProviderConfig | None:
        """Get a specific provider configuration."""
        cls._ensure_initialized()
        return cls._registry.get(name)
    
    @classmethod
    def get_all(cls) -> Dict[str, ProviderConfig]:
        """Get all registered provider configurations."""
        cls._ensure_initialized()
        return cls._registry.copy()
    
    @classmethod
    def get_config(cls) -> Dict[str, Tuple[str, Validator]]:
        """
        Get configuration in legacy format for backward compatibility.
        
        Returns:
            Dict mapping provider names to (pattern_str, validator) tuples
        """
        cls._ensure_initialized()
        return {
            name: (config.pattern.pattern, config.validator)
            for name, config in cls._registry.items()
        }
    
    @classmethod
    def _ensure_initialized(cls) -> None:
        """Ensure default providers are registered."""
        if not cls._registry:
            cls._initialize_defaults()
    
    @classmethod
    def list_providers(cls) -> list[str]:
        """Get a list of all registered provider names."""
        cls._ensure_initialized()
        return list(cls._registry.keys())
