"""
Traefik proxy provider implementation.

Generates Traefik dynamic configuration in YAML format with support
for HTTP routers, services, and middleware plugins.
"""

import logging
import os
import re
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse

import requests
import yaml

from ..config import (
    AuthenticationConfig,
    BasicAuthConfig,
    Config,
    CORSPolicy,
    GlobalConfig,
    HeaderManipulation,
    HealthCheckConfig,
    LoadBalancerConfig,
    PassiveHealthCheck,
    RateLimitConfig,
    Route,
    Service,
    Upstream,
    UpstreamTarget,
)
from ..provider import Provider

logger = logging.getLogger(__name__)


class TraefikProvider(Provider):
    """Traefik reverse proxy and load balancer provider.

    Generates dynamic configuration for Traefik, a modern HTTP reverse
    proxy and load balancer with automatic service discovery and
    Let's Encrypt support.

    Output Format:
        YAML file with dynamic configuration:
        - http.routers: Routing rules with PathPrefix matching
        - http.services: Backend service definitions with load balancing
        - http.middlewares: Transformation and manipulation plugins

    Transformations:
        Implemented using middleware plugins.
        Note: Middleware plugins require custom Go development.
        Generated config includes placeholder middleware definitions
        for default value transformations.

    gRPC Support:
        Traefik supports gRPC via HTTP/2 automatically.
        Routes are configured the same as REST services.

    Limitations:
        - Middleware plugins require Go development
        - No native computed field support
        - Transformations need custom middleware implementation
        - Focus on routing/load balancing, not payload manipulation

    Ideal For:
        - Docker Swarm and Kubernetes
        - Container-based deployments
        - Development environments
        - Automatic service discovery

    Example:
        >>> provider = TraefikProvider()
        >>> provider.name()
        'traefik'
        >>> config = Config.from_yaml("gateway.yaml")
        >>> output = provider.generate(config)
        >>> "http:" in output
        True

    See Also:
        https://doc.traefik.io/traefik/routing/overview/
    """

    def name(self) -> str:
        """Return provider name.

        Returns:
            str: "traefik"
        """
        return "traefik"

    def validate(self, config: Config) -> bool:
        """Validate configuration for Traefik.

        Traefik has minimal validation requirements at config generation.
        Most validation occurs when Traefik loads the configuration.

        Args:
            config: Configuration to validate

        Returns:
            True (Traefik validates at runtime)

        Example:
            >>> provider = TraefikProvider()
            >>> config = Config(...)
            >>> provider.validate(config)
            True
        """
        logger.debug(f"Validating Traefik configuration: {len(config.services)} services")
        return True

    def generate(self, config: Config) -> str:
        """Generate Traefik dynamic configuration in YAML format.

        Creates Traefik dynamic config with routers, services, and
        optional middleware for transformations.

        Configuration Structure:
            - http:
                - routers: PathPrefix-based routing rules
                - services: LoadBalancer configurations
                - middlewares: Transformation plugins (if enabled)

        Args:
            config: Configuration object containing services

        Returns:
            Complete Traefik dynamic YAML configuration

        Example:
            >>> provider = TraefikProvider()
            >>> config = Config.from_yaml("config.yaml")
            >>> yaml_output = provider.generate(config)
            >>> "routers:" in yaml_output
            True
            >>> "services:" in yaml_output
            True
        """
        logger.info(f"Generating Traefik configuration for {len(config.services)} services")
        output = []
        output.append("# Traefik Configuration Generated by GAL")
        output.append("")

        # Logging configuration
        if config.global_config and config.global_config.logging:
            self._generate_traefik_logging(config.global_config.logging, output)

        # Metrics configuration
        if config.global_config and config.global_config.metrics:
            self._generate_traefik_metrics(config.global_config.metrics, output)

        output.append("http:")
        output.append("  routers:")

        for service in config.services:
            for i, route in enumerate(service.routes):
                router_name = f"{service.name}_router_{i}"
                output.append(f"    {router_name}:")
                output.append(f"      rule: 'PathPrefix(`{route.path_prefix}`)'")
                output.append(f"      service: {service.name}_service")

                # Collect middlewares for this route
                middlewares = []
                if route.authentication and route.authentication.enabled:
                    middlewares.append(f"{router_name}_auth")
                if service.transformation and service.transformation.enabled:
                    middlewares.append(f"{service.name}_transform")
                if route.rate_limit and route.rate_limit.enabled:
                    middlewares.append(f"{router_name}_ratelimit")
                if route.headers:
                    middlewares.append(f"{router_name}_headers")
                if route.cors and route.cors.enabled:
                    middlewares.append(f"{router_name}_cors")
                if route.circuit_breaker and route.circuit_breaker.enabled:
                    middlewares.append(f"{router_name}_circuitbreaker")
                if route.retry and route.retry.enabled:
                    middlewares.append(f"{router_name}_retry")

                # Body transformation - Traefik limitation
                if route.body_transformation and route.body_transformation.enabled:
                    logger.warning(
                        f"Body transformation configured for {service.name}/{route.path_prefix}, "
                        "but Traefik does not natively support request/response body transformation. "
                        "Consider using:\n"
                        "  1. ForwardAuth middleware with external transformation service\n"
                        "  2. Custom Traefik plugin (requires Go development)\n"
                        "  3. Alternative provider (Envoy, Kong, APISIX, Nginx, HAProxy) with native support"
                    )

                # Add middlewares if any
                if middlewares:
                    output.append("      middlewares:")
                    for mw in middlewares:
                        output.append(f"        - {mw}")

                output.append("")

        output.append("  services:")
        for service in config.services:
            self._generate_traefik_service(service, output)
            output.append("")

        # Middlewares for authentication, transformations, rate limiting, headers, and CORS
        has_authentication = any(
            route.authentication and route.authentication.enabled
            for service in config.services
            for route in service.routes
        )
        has_transformations = any(
            s.transformation and s.transformation.enabled for s in config.services
        )
        has_rate_limits = any(
            route.rate_limit and route.rate_limit.enabled
            for service in config.services
            for route in service.routes
        )
        has_headers = any(route.headers for service in config.services for route in service.routes)
        has_cors = any(
            route.cors and route.cors.enabled
            for service in config.services
            for route in service.routes
        )
        has_circuit_breakers = any(
            route.circuit_breaker and route.circuit_breaker.enabled
            for service in config.services
            for route in service.routes
        )
        has_retry = any(
            route.retry and route.retry.enabled
            for service in config.services
            for route in service.routes
        )

        if (
            has_authentication
            or has_transformations
            or has_rate_limits
            or has_headers
            or has_cors
            or has_circuit_breakers
            or has_retry
        ):
            output.append("  middlewares:")

            # Authentication middlewares
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.authentication and route.authentication.enabled:
                        router_name = f"{service.name}_router_{i}"
                        auth = route.authentication

                        if auth.type == "basic":
                            output.append(f"    {router_name}_auth:")
                            output.append("      basicAuth:")
                            if auth.basic_auth and auth.basic_auth.users:
                                output.append("        users:")
                                for username, password in auth.basic_auth.users.items():
                                    # Traefik expects htpasswd format, but for simplicity using plain format
                                    # In production, use: htpasswd -nb username password
                                    output.append(f"          - '{username}:{password}'")
                                if auth.basic_auth.realm:
                                    output.append(f"        realm: '{auth.basic_auth.realm}'")
                            output.append("")

                        elif auth.type == "api_key":
                            # Traefik doesn't have native API key auth, use forwardAuth to external service
                            output.append(f"    {router_name}_auth:")
                            output.append("      forwardAuth:")
                            output.append(
                                "        address: 'http://api-key-validator:8080/validate'"
                            )
                            key_name = auth.api_key.key_name if auth.api_key else "X-API-Key"
                            output.append("        authRequestHeaders:")
                            output.append(f"          - '{key_name}'")
                            output.append("")

                        elif auth.type == "jwt":
                            # Traefik uses forwardAuth for JWT validation
                            output.append(f"    {router_name}_auth:")
                            output.append("      forwardAuth:")
                            if auth.jwt and auth.jwt.jwks_uri:
                                output.append(
                                    f"        address: 'http://jwt-validator:8080/validate'"
                                )
                            else:
                                output.append(
                                    "        address: 'http://jwt-validator:8080/validate'"
                                )
                            output.append("        authRequestHeaders:")
                            output.append("          - 'Authorization'")
                            output.append("")

            # Transformation middlewares
            for service in config.services:
                if service.transformation and service.transformation.enabled:
                    output.append(f"    {service.name}_transform:")
                    output.append("      plugin:")
                    output.append(f"        {service.name}_transformer:")
                    output.append("          defaults:")
                    for key, value in service.transformation.defaults.items():
                        output.append(f"            {key}: '{value}'")
                    output.append("")

            # Rate limiting middlewares
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.rate_limit and route.rate_limit.enabled:
                        router_name = f"{service.name}_router_{i}"
                        output.append(f"    {router_name}_ratelimit:")
                        output.append("      rateLimit:")
                        output.append(f"        average: {route.rate_limit.requests_per_second}")
                        output.append(f"        burst: {route.rate_limit.burst}")
                        output.append("")

            # Header manipulation middlewares (route-level)
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.headers:
                        router_name = f"{service.name}_router_{i}"
                        headers = route.headers
                        output.append(f"    {router_name}_headers:")
                        output.append("      headers:")

                        # Request headers
                        if headers.request_add:
                            output.append("        customRequestHeaders:")
                            for key, value in headers.request_add.items():
                                output.append(f"          {key}: '{value}'")
                        if headers.request_remove:
                            output.append("        customRequestHeaders:")
                            for header_name in headers.request_remove:
                                output.append(
                                    f"          {header_name}: ''"
                                )  # Empty value removes header

                        # Response headers
                        if headers.response_add:
                            output.append("        customResponseHeaders:")
                            for key, value in headers.response_add.items():
                                output.append(f"          {key}: '{value}'")
                        if headers.response_remove:
                            output.append("        customResponseHeaders:")
                            for header_name in headers.response_remove:
                                output.append(
                                    f"          {header_name}: ''"
                                )  # Empty value removes header
                        output.append("")

            # Service-level header manipulation
            for service in config.services:
                if (
                    service.transformation
                    and service.transformation.enabled
                    and service.transformation.headers
                ):
                    headers = service.transformation.headers
                    output.append(f"    {service.name}_headers:")
                    output.append("      headers:")

                    # Request headers
                    if headers.request_add:
                        output.append("        customRequestHeaders:")
                        for key, value in headers.request_add.items():
                            output.append(f"          {key}: '{value}'")
                    if headers.request_remove:
                        output.append("        customRequestHeaders:")
                        for header_name in headers.request_remove:
                            output.append(f"          {header_name}: ''")

                    # Response headers
                    if headers.response_add:
                        output.append("        customResponseHeaders:")
                        for key, value in headers.response_add.items():
                            output.append(f"          {key}: '{value}'")
                    if headers.response_remove:
                        output.append("        customResponseHeaders:")
                        for header_name in headers.response_remove:
                            output.append(f"          {header_name}: ''")
                    output.append("")

            # CORS middlewares (route-level)
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.cors and route.cors.enabled:
                        router_name = f"{service.name}_router_{i}"
                        cors = route.cors
                        output.append(f"    {router_name}_cors:")
                        output.append("      headers:")
                        output.append("        accessControlAllowMethods:")
                        for method in cors.allowed_methods:
                            output.append(f"          - {method}")
                        output.append("        accessControlAllowOriginList:")
                        for origin in cors.allowed_origins:
                            output.append(f"          - '{origin}'")
                        if cors.allowed_headers:
                            output.append("        accessControlAllowHeaders:")
                            for header in cors.allowed_headers:
                                output.append(f"          - {header}")
                        if cors.expose_headers:
                            output.append("        accessControlExposeHeaders:")
                            for header in cors.expose_headers:
                                output.append(f"          - {header}")
                        output.append(
                            f"        accessControlAllowCredentials: {str(cors.allow_credentials).lower()}"
                        )
                        output.append(f"        accessControlMaxAge: {cors.max_age}")
                        output.append("")

            # Circuit Breaker middlewares (route-level)
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.circuit_breaker and route.circuit_breaker.enabled:
                        router_name = f"{service.name}_router_{i}"
                        cb = route.circuit_breaker
                        output.append(f"    {router_name}_circuitbreaker:")
                        output.append("      circuitBreaker:")

                        # Traefik uses expression-based circuit breaker
                        # Build expression based on unhealthy status codes and max failures
                        if cb.unhealthy_status_codes:
                            min_code = min(cb.unhealthy_status_codes)
                            max_code = max(cb.unhealthy_status_codes) + 1
                            # Calculate failure ratio threshold from max_failures
                            # Assuming a window of 10 requests, convert max_failures to ratio
                            failure_ratio = min(cb.max_failures / 10.0, 0.9)
                            expression = f"ResponseCodeRatio({min_code}, {max_code}, 0, 600) > {failure_ratio:.2f}"
                        else:
                            # Fallback to network error ratio
                            failure_ratio = min(cb.max_failures / 10.0, 0.9)
                            expression = f"NetworkErrorRatio() > {failure_ratio:.2f}"

                        output.append(f"        expression: '{expression}'")
                        output.append("")

            # Retry middlewares (route-level)
            for service in config.services:
                for i, route in enumerate(service.routes):
                    if route.retry and route.retry.enabled:
                        router_name = f"{service.name}_router_{i}"
                        retry = route.retry
                        output.append(f"    {router_name}_retry:")
                        output.append("      retry:")
                        output.append(f"        attempts: {retry.attempts}")
                        # Traefik uses initialInterval (equivalent to base_interval)
                        output.append(f"        initialInterval: {retry.base_interval}")
                        output.append("")

        result = "\n".join(output)
        logger.info(
            f"Traefik configuration generated: {len(result)} bytes, {len(config.services)} services"
        )
        return result

    def _generate_traefik_logging(self, logging_config, output: list):
        """Generate Traefik logging configuration.

        Args:
            logging_config: LoggingConfig object
            output: Output list to append YAML lines to
        """
        output.append("accessLog:")
        output.append(f"  filePath: {logging_config.access_log_path}")

        if logging_config.format == "json":
            output.append("  format: json")
        else:
            output.append("  format: common")

        # Custom fields
        if logging_config.custom_fields:
            output.append("  fields:")
            output.append("    defaultMode: keep")
            output.append("    headers:")
            output.append("      defaultMode: keep")
            for key, value in logging_config.custom_fields.items():
                output.append(f"      names:")
                output.append(f"        {key}: keep")

        output.append("")

    def _generate_traefik_metrics(self, metrics_config, output: list):
        """Generate Traefik metrics configuration.

        Args:
            metrics_config: MetricsConfig object
            output: Output list to append YAML lines to
        """
        if metrics_config.enabled and metrics_config.exporter in ("prometheus", "both"):
            output.append("metrics:")
            output.append("  prometheus:")
            output.append(f"    entryPoint: metrics")
            logger.info(
                f"Prometheus metrics enabled. Configure entryPoint 'metrics' on port {metrics_config.prometheus_port} in static config"
            )
            output.append("")

    def _generate_traefik_service(self, service, output: list):
        """Generate Traefik service configuration with health checks and load balancing.

        Creates Traefik service LoadBalancer configuration supporting:
        - Multiple servers with weights
        - Health checks (HTTP/HTTPS probing)
        - Sticky sessions
        - Load balancing (implicit round-robin or weighted)

        Args:
            service: Service object with upstream configuration
            output: Output list to append YAML lines to
        """
        output.append(f"    {service.name}_service:")
        output.append("      loadBalancer:")

        # Configure servers
        output.append("        servers:")
        if service.upstream.targets:
            # Multiple targets mode
            for target in service.upstream.targets:
                output.append(f"        - url: 'http://{target.host}:{target.port}'")
                if (
                    service.upstream.load_balancer
                    and service.upstream.load_balancer.algorithm == "weighted"
                ):
                    output.append(f"          weight: {target.weight}")
        else:
            # Simple mode (single host/port)
            output.append(
                f"        - url: 'http://{service.upstream.host}:{service.upstream.port}'"
            )

        # Configure sticky sessions
        if service.upstream.load_balancer and service.upstream.load_balancer.sticky_sessions:
            output.append("        sticky:")
            output.append("          cookie:")
            cookie_name = service.upstream.load_balancer.cookie_name or "galSession"
            output.append(f"            name: {cookie_name}")
            output.append("            httpOnly: true")

        # Configure health checks
        if service.upstream.health_check and service.upstream.health_check.active:
            active = service.upstream.health_check.active
            if active.enabled:
                output.append("        healthCheck:")
                output.append(f"          path: {active.http_path}")
                output.append(f"          interval: {active.interval}")
                output.append(f"          timeout: {active.timeout}")

        # Configure WebSocket support if any route has WebSocket enabled
        has_websocket = any(route.websocket and route.websocket.enabled for route in service.routes)
        if has_websocket:
            # Traefik supports WebSocket automatically, but we ensure proper configuration
            output.append("        passHostHeader: true")
            # Optional: Add responseForwarding for better WebSocket performance
            output.append("        responseForwarding:")
            output.append("          flushInterval: 100ms")

        # Configure timeout if any route has timeout configured
        has_timeout = any(route.timeout for route in service.routes)
        if has_timeout:
            # Find the first route with timeout configuration
            for route in service.routes:
                if route.timeout:
                    timeout = route.timeout
                    output.append("        serversTransport:")
                    # Traefik uses forwardingTimeouts
                    output.append("          forwardingTimeouts:")
                    output.append(f"            dialTimeout: {timeout.connect}")
                    output.append(f"            responseHeaderTimeout: {timeout.read}")
                    output.append(f"            idleConnTimeout: {timeout.idle}")
                    break

    def deploy(
        self, config: Config, output_file: Optional[str] = None, api_url: Optional[str] = None
    ) -> bool:
        """Deploy Traefik configuration.

        Deploys configuration via file-based approach (Traefik File Provider).
        Optionally checks if Traefik API is reachable for verification.

        Deployment Methods:
            1. File Provider (standard): Write dynamic config to file
            2. API check (optional): Verify Traefik can access the config

        Args:
            config: Configuration to deploy
            output_file: Path to write config file (default: traefik.yaml)
            api_url: Traefik API/Dashboard URL for verification
                    (default: http://localhost:8080)

        Returns:
            True if deployment successful

        Raises:
            IOError: If file write fails

        Example:
            >>> provider = TraefikProvider()
            >>> config = Config.from_yaml("config.yaml")
            >>> # File-based deployment
            >>> provider.deploy(config, output_file="/etc/traefik/dynamic/gal.yaml")
            True
            >>> # With API verification
            >>> provider.deploy(config, api_url="http://traefik:8080")
            True

        Note:
            Traefik automatically reloads configuration from file providers.
            No API call needed for deployment - just write the file!
        """
        logger.info(f"Deploying Traefik configuration to file: {output_file or 'traefik.yaml'}")
        # Generate configuration
        generated_config = self.generate(config)

        # Determine output file
        if output_file is None:
            output_file = "traefik.yaml"

        # Write configuration to file
        try:
            # Create directory if it doesn't exist
            os.makedirs(os.path.dirname(output_file) or ".", exist_ok=True)

            with open(output_file, "w") as f:
                f.write(generated_config)

            logger.info(f"Traefik configuration successfully written to {output_file}")
            print(f"✓ Traefik configuration written to {output_file}")
            print("  Traefik will auto-reload this file if configured with File Provider")
        except IOError as e:
            logger.error(f"Failed to write Traefik config file to {output_file}: {e}")
            print(f"✗ Failed to write config file: {e}")
            return False

        # Optionally verify Traefik API is reachable
        if api_url:
            api_url = api_url.rstrip("/")
            logger.debug(f"Checking Traefik API at {api_url}")
            try:
                # Check if Traefik API/Dashboard is reachable
                response = requests.get(f"{api_url}/api/overview", timeout=5)

                if response.status_code == 200:
                    logger.info(f"Traefik API is reachable at {api_url}")
                    print(f"✓ Traefik API is reachable at {api_url}")
                    print(f"  Dashboard: {api_url}/dashboard/")
                else:
                    logger.warning(f"Traefik API returned status {response.status_code}")
                    print(f"⚠ Traefik API returned status {response.status_code}")

            except requests.RequestException as e:
                logger.warning(f"Could not reach Traefik API at {api_url}: {e}")
                print(f"⚠ Could not reach Traefik API: {e}")
                print(f"  Config written to {output_file}")
                print("  Ensure Traefik File Provider is configured:")
                print(f"    --providers.file.filename={output_file}")

        logger.info("Traefik deployment completed successfully")
        return True

    def parse(self, provider_config: str) -> Config:
        """Parse Traefik YAML configuration to GAL format.

        Traefik has static config (entrypoints, providers) and
        dynamic config (routers, services, middlewares). This parser
        handles dynamic config files.

        Args:
            provider_config: Traefik YAML configuration string (dynamic config)

        Returns:
            Config: GAL configuration object

        Raises:
            ValueError: If config is invalid or cannot be parsed
        """
        logger.info("Parsing Traefik configuration to GAL format")

        try:
            traefik_config = yaml.safe_load(provider_config)
        except yaml.YAMLError as e:
            raise ValueError(f"Invalid YAML: {e}")

        if not traefik_config:
            raise ValueError("Empty configuration")

        self._import_warnings = []

        # Traefik structure: http.routers, http.services, http.middlewares
        # Create default global config
        global_config = GlobalConfig(host="0.0.0.0", port=80, timeout="30s")

        return Config(
            version="1.0",
            provider="traefik",
            global_config=global_config,
            services=self._parse_services(traefik_config),
        )

    def _parse_services(self, traefik_config: dict) -> List[Service]:
        """Parse Traefik services to GAL services."""
        gal_services = []

        http_config = traefik_config.get("http", {})
        traefik_services = http_config.get("services", {})
        traefik_routers = http_config.get("routers", {})
        traefik_middlewares = http_config.get("middlewares", {})

        for service_name, service_config in traefik_services.items():
            service = self._parse_service(
                service_name, service_config, traefik_routers, traefik_middlewares
            )
            if service:
                gal_services.append(service)

        return gal_services

    def _parse_service(
        self,
        service_name: str,
        service_config: dict,
        traefik_routers: dict,
        traefik_middlewares: dict,
    ) -> Optional[Service]:
        """Convert Traefik service to GAL service."""
        # Parse load balancer config
        load_balancer = service_config.get("loadBalancer", {})

        if not load_balancer:
            return None

        # Parse servers (targets)
        servers = load_balancer.get("servers", [])
        targets = []

        for server in servers:
            url = server.get("url")  # Format: "http://host:port"

            if not url:
                continue

            # Parse URL
            parsed = urlparse(url)
            host = parsed.hostname
            port = parsed.port or 80

            if not host:
                continue

            targets.append(UpstreamTarget(host=host, port=port))

        if not targets:
            return None

        # Parse health check
        health_check = self._parse_health_check(load_balancer)

        # Parse sticky sessions
        sticky = load_balancer.get("sticky", {})
        sticky_sessions = sticky.get("cookie") is not None

        cookie_name = None
        if sticky_sessions:
            cookie_config = sticky.get("cookie", {})
            cookie_name = cookie_config.get("name", "lb")

        # Upstream config
        upstream = Upstream(
            targets=targets,
            load_balancer=LoadBalancerConfig(
                algorithm="round_robin",  # Traefik default
                sticky_sessions=sticky_sessions,
                cookie_name=cookie_name,
            ),
            health_check=health_check,
        )

        # Parse routes for this service
        routes = []
        for router_name, router_config in traefik_routers.items():
            if router_config.get("service") == service_name:
                route = self._parse_router(router_name, router_config, traefik_middlewares)
                if route:
                    routes.append(route)

        return Service(
            name=service_name,
            type="rest",
            protocol="http",
            upstream=upstream,
            routes=routes,
        )

    def _parse_health_check(self, load_balancer: dict) -> Optional[HealthCheckConfig]:
        """Parse Traefik health check."""
        health_check = load_balancer.get("healthCheck", {})

        if not health_check:
            return None

        # Traefik OSS only supports passive health checks by default
        # Active health checks require Traefik Plus
        self._import_warnings.append(
            "Traefik OSS only supports passive health checks - config may be simplified"
        )

        return HealthCheckConfig(
            passive=PassiveHealthCheck(enabled=True, max_failures=3)  # Default
        )

    def _parse_router(
        self, router_name: str, router_config: dict, traefik_middlewares: dict
    ) -> Optional[Route]:
        """Parse Traefik router to GAL route."""
        # Parse rule (Traefik matcher)
        rule = router_config.get("rule", "")

        if not rule:
            return None

        # Extract path from rule
        path_prefix = self._extract_path_from_rule(rule)

        # Parse middlewares
        middleware_names = router_config.get("middlewares", [])

        rate_limit = None
        authentication = None
        headers = None
        cors = None

        for middleware_name in middleware_names:
            if middleware_name not in traefik_middlewares:
                continue

            middleware_config = traefik_middlewares[middleware_name]

            if "rateLimit" in middleware_config:
                rate_limit = self._parse_rate_limit_middleware(middleware_config["rateLimit"])
            elif "basicAuth" in middleware_config:
                authentication = self._parse_basic_auth_middleware(middleware_config["basicAuth"])
            elif "headers" in middleware_config:
                headers = self._parse_headers_middleware(middleware_config["headers"])
            elif "addPrefix" in middleware_config or "stripPrefix" in middleware_config:
                # Path manipulation - not directly mappable to GAL
                self._import_warnings.append(
                    f"Path manipulation middleware '{middleware_name}' not imported"
                )

        # Check for CORS in headers middleware
        if headers and headers.response_add:
            cors = self._extract_cors_from_headers(headers)

        return Route(
            path_prefix=path_prefix,
            rate_limit=rate_limit,
            authentication=authentication,
            headers=headers,
            cors=cors,
        )

    def _extract_path_from_rule(self, rule: str) -> str:
        """Extract path from Traefik rule.

        Examples:
            PathPrefix(`/api`) → /api
            Host(`example.com`) && PathPrefix(`/api`) → /api
            Path(`/api/v1`) → /api/v1
        """
        # Try PathPrefix first
        path_match = re.search(r"PathPrefix\(`([^`]+)`\)", rule)
        if path_match:
            return path_match.group(1)

        # Try exact Path
        path_match = re.search(r"Path\(`([^`]+)`\)", rule)
        if path_match:
            return path_match.group(1)

        # Default
        return "/"

    def _parse_rate_limit_middleware(self, config: dict) -> RateLimitConfig:
        """Parse Traefik rateLimit middleware."""
        average = config.get("average", 100)
        burst = config.get("burst", 200)

        # Traefik average is per second
        return RateLimitConfig(
            enabled=True,
            requests_per_second=average,
            burst=burst,
            key_type="ip_address",
        )

    def _parse_basic_auth_middleware(self, config: dict) -> AuthenticationConfig:
        """Parse Traefik basicAuth middleware."""
        # Users are hashed in Traefik, cannot import plaintext
        self._import_warnings.append("Basic auth users are hashed - configure manually in GAL")

        return AuthenticationConfig(
            enabled=True, type="basic", basic_auth=BasicAuthConfig(users={}, realm="Protected")
        )

    def _parse_headers_middleware(self, config: dict) -> HeaderManipulation:
        """Parse Traefik headers middleware."""
        custom_request_headers = config.get("customRequestHeaders", {})
        custom_response_headers = config.get("customResponseHeaders", {})

        request_add = custom_request_headers if custom_request_headers else None
        response_add = custom_response_headers if custom_response_headers else None

        return HeaderManipulation(request_add=request_add, response_add=response_add)

    def _extract_cors_from_headers(self, headers: HeaderManipulation) -> Optional[CORSPolicy]:
        """Extract CORS config from response headers."""
        if not headers.response_add:
            return None

        cors_headers = {}
        for key, value in headers.response_add.items():
            if key.startswith("Access-Control-"):
                cors_headers[key] = value

        if not cors_headers:
            return None

        # Build CORS config
        allowed_origins_str = cors_headers.get("Access-Control-Allow-Origin", "*")
        allowed_origins = [allowed_origins_str] if allowed_origins_str != "*" else ["*"]

        allowed_methods_str = cors_headers.get(
            "Access-Control-Allow-Methods", "GET,POST,PUT,DELETE"
        )
        allowed_methods = allowed_methods_str.split(",")

        allowed_headers_str = cors_headers.get("Access-Control-Allow-Headers")
        allowed_headers = allowed_headers_str.split(",") if allowed_headers_str else None

        allow_credentials = cors_headers.get("Access-Control-Allow-Credentials") == "true"

        max_age = cors_headers.get("Access-Control-Max-Age", "86400")

        # Remove CORS headers from response_add (they're now in cors config)
        for key in list(headers.response_add.keys()):
            if key.startswith("Access-Control-"):
                del headers.response_add[key]

        return CORSPolicy(
            enabled=True,
            allowed_origins=allowed_origins,
            allowed_methods=allowed_methods,
            allowed_headers=allowed_headers,
            allow_credentials=allow_credentials,
            max_age=max_age,
        )

    def get_import_warnings(self) -> List[str]:
        """Return warnings from last import."""
        return getattr(self, "_import_warnings", [])
