"""
Kindred AI SDK - URL rewriting logic.
"""

from typing import Dict, Optional
from urllib.parse import urlparse, urlunparse, ParseResult


def _rewrite_url(original_url: str, rules: Dict[str, str]) -> str:
    """
    Rewrite a URL based on routing rules.
    
    Args:
        original_url: The original URL to potentially rewrite
        rules: Dictionary mapping original hostnames to new destinations.
               Special key "*" or "__all__" matches all hostnames.
        
    Returns:
        The rewritten URL if a rule matches, otherwise the original URL
        
    Example:
        >>> rules = {"api.stripe.com": "http://localhost:8080/stripe-mock"}
        >>> _rewrite_url("https://api.stripe.com/v1/charges", rules)
        'http://localhost:8080/stripe-mock/v1/charges'
        
        >>> rules = {"*": "http://localhost:8080/proxy"}
        >>> _rewrite_url("https://api.example.com/v1/endpoint", rules)
        'http://localhost:8080/proxy/v1/endpoint'
    """
    if not rules:
        return original_url
    
    try:
        parsed = urlparse(original_url)
        hostname = parsed.netloc.split(':')[0]  # Remove port if present
        
        # Check for catch-all pattern first (but only if no specific match exists)
        catch_all_key = None
        if "*" in rules:
            catch_all_key = "*"
        elif "__all__" in rules:
            catch_all_key = "__all__"
        
        # Check for exact hostname match
        if hostname in rules:
            destination = rules[hostname]
            dest_parsed = urlparse(destination)
            
            # Build new URL preserving path, query, and fragment from original
            new_parsed = ParseResult(
                scheme=dest_parsed.scheme or parsed.scheme,
                netloc=dest_parsed.netloc,
                path=_combine_paths(dest_parsed.path, parsed.path),
                params=parsed.params,
                query=parsed.query,
                fragment=parsed.fragment
            )
            
            return urlunparse(new_parsed)
        
        # Check for subdomain matches (e.g., "*.example.com" -> "api.example.com")
        for rule_host, destination in rules.items():
            if rule_host.startswith("*."):
                domain = rule_host[2:]  # Remove "*."
                if hostname.endswith("." + domain) or hostname == domain:
                    dest_parsed = urlparse(destination)
                    new_parsed = ParseResult(
                        scheme=dest_parsed.scheme or parsed.scheme,
                        netloc=dest_parsed.netloc,
                        path=_combine_paths(dest_parsed.path, parsed.path),
                        params=parsed.params,
                        query=parsed.query,
                        fragment=parsed.fragment
                    )
                    return urlunparse(new_parsed)
        
        # If no specific match, use catch-all if present
        if catch_all_key:
            destination = rules[catch_all_key]
            dest_parsed = urlparse(destination)
            new_parsed = ParseResult(
                scheme=dest_parsed.scheme or parsed.scheme,
                netloc=dest_parsed.netloc,
                path=_combine_paths(dest_parsed.path, parsed.path),
                params=parsed.params,
                query=parsed.query,
                fragment=parsed.fragment
            )
            return urlunparse(new_parsed)
        
    except Exception as e:
        # If URL parsing fails, return original URL
        # In production, you might want to log this
        return original_url
    
    return original_url


def _combine_paths(base_path: str, additional_path: str) -> str:
    """
    Combine two URL paths intelligently.
    
    Args:
        base_path: The base path (may end with /)
        additional_path: The additional path (may start with /)
        
    Returns:
        Combined path
        
    Example:
        >>> _combine_paths("/api", "/v1/endpoint")
        '/api/v1/endpoint'
        >>> _combine_paths("/api/", "/v1/endpoint")
        '/api/v1/endpoint'
        >>> _combine_paths("/api", "v1/endpoint")
        '/api/v1/endpoint'
    """
    # Remove trailing slash from base_path
    base_path = base_path.rstrip('/')
    
    # Ensure additional_path starts with /
    if not additional_path.startswith('/'):
        additional_path = '/' + additional_path
    
    return base_path + additional_path


def validate_rules(rules: Dict[str, str]) -> None:
    """
    Validate routing rules dictionary.
    
    Args:
        rules: Dictionary mapping hostnames to destinations.
               Special keys "*" or "__all__" are allowed for catch-all routing.
        
    Raises:
        ValueError: If rules are invalid
    """
    if not isinstance(rules, dict):
        raise ValueError("Rules must be a dictionary")
    
    for hostname, destination in rules.items():
        # Allow catch-all patterns
        if hostname not in ("*", "__all__"):
            if not isinstance(hostname, str) or not hostname:
                raise ValueError(f"Invalid hostname in rules: {hostname}")
        
        if not isinstance(destination, str) or not destination:
            raise ValueError(f"Invalid destination in rules: {destination}")
        
        # Validate that destination is a valid URL
        try:
            parsed = urlparse(destination)
            if not parsed.netloc:
                raise ValueError(
                    f"Destination '{destination}' must include a hostname (netloc)"
                )
        except Exception as e:
            raise ValueError(f"Invalid destination URL '{destination}': {e}")

