"""RegistryService — auto-detect container registry from cluster endpoint.

Pattern matching: EKS → ECR, GKE → Artifact Registry, AKS → ACR.
Local cluster detection: localhost/127.0.0.1 endpoints.
"""

from __future__ import annotations

import os
import re
from collections.abc import Callable
from typing import TYPE_CHECKING

from kuberoku import branding

if TYPE_CHECKING:
    from kuberoku.factory import KuberokuFactory


class RegistryService:
    """Auto-detect container registry from cluster configuration."""

    def __init__(self, factory: KuberokuFactory) -> None:
        self._factory = factory
        self._cached_registry: str | None = None
        self._cached_local: bool | None = None

    def detect(self, on_step: Callable[[str], None] | None = None) -> str | None:
        """Detect registry from cluster endpoint. Returns None if unknown."""
        # Check env var override
        env_registry = os.environ.get(f"{branding.ENV_PREFIX}REGISTRY")
        if env_registry:
            return env_registry

        if self.is_local_cluster():
            return None

        endpoint = self._get_cluster_endpoint()
        if not endpoint:
            return None

        return self._detect_from_endpoint(endpoint)

    def get_or_detect(self, on_step: Callable[[str], None] | None = None) -> str:
        """Get configured registry or auto-detect. Returns '' for local clusters."""
        if self._cached_registry is not None:
            return self._cached_registry

        registry = self.detect(on_step=on_step)
        if registry:
            self._cached_registry = registry
            return registry

        self._cached_registry = ""
        return ""

    def is_local_cluster(self) -> bool:
        """Check if the cluster is local (localhost, 127.0.0.1, etc.)."""
        if self._cached_local is not None:
            return self._cached_local

        endpoint = self._get_cluster_endpoint()
        if not endpoint:
            self._cached_local = True  # Default to local if can't determine
            return True

        local_patterns = [
            "localhost",
            "127.0.0.1",
            "0.0.0.0",
            "host.docker.internal",
            "kubernetes.docker.internal",
        ]
        endpoint_lower = endpoint.lower()
        is_local = any(p in endpoint_lower for p in local_patterns)

        # Also check common local k8s ports
        if ":6443" in endpoint and any(p in endpoint_lower for p in local_patterns):
            is_local = True

        self._cached_local = is_local
        return is_local

    def local_load_command(self, image: str) -> list[str]:
        """Get the command to load an image into a local cluster."""
        # Try to detect local cluster type
        endpoint = self._get_cluster_endpoint()
        if not endpoint:
            return []

        # k3d
        if "k3d" in endpoint.lower() or os.environ.get("K3D_CLUSTER"):
            return ["k3d", "image", "import", image]
        # kind
        if "kind" in endpoint.lower() or os.environ.get("KIND_CLUSTER_NAME"):
            return ["kind", "load", "docker-image", image]
        # minikube
        if "minikube" in endpoint.lower():
            return ["minikube", "image", "load", image]

        # For other local clusters (Colima, Docker Desktop, Rancher Desktop,
        # MicroK8s, etc.), use the KUBEROKU_LOCAL_LOAD env var — handled by
        # BuildService._local_load().
        return []

    def _get_cluster_endpoint(self) -> str:
        """Get the current cluster endpoint from kubeconfig."""
        try:
            return self._factory.k8s.cluster_endpoint
        except Exception:
            return ""

    def _detect_from_endpoint(self, endpoint: str) -> str | None:
        """Detect registry from cluster API server endpoint."""
        # EKS → ECR
        if "eks.amazonaws.com" in endpoint:
            # Extract region from endpoint (e.g., us-east-1)
            region_match = re.search(r"\.([\w]+-[\w]+-\d+)\.eks\.amazonaws\.com", endpoint)
            region = region_match.group(1) if region_match else "us-east-1"
            # Account ID not available from endpoint alone — use placeholder
            return f"<account>.dkr.ecr.{region}.amazonaws.com"

        # GKE → Artifact Registry
        if "gke.goog" in endpoint or "container.googleapis.com" in endpoint:
            region_match = re.search(r"([\w-]+)-gke", endpoint)
            region = region_match.group(1) if region_match else "us-central1"
            return f"{region}-docker.pkg.dev"

        # AKS → ACR
        if "azmk8s.io" in endpoint:
            name_match = re.search(r"([\w-]+)\.azmk8s\.io", endpoint)
            if name_match:
                name = name_match.group(1)
                return f"{name}.azurecr.io"

        return None
