"""ServiceCatalog loader — reads profiles/service_catalog/{cloud}.yaml.

Each cloud has a curated list of services with resource types,
compliance surface, and default configuration.
"""

from __future__ import annotations

from functools import lru_cache
from pathlib import Path
from typing import Any

import yaml
from pydantic import BaseModel, ConfigDict

from complyform.core.errors import ServiceCatalogNotFoundError

_PROFILES_DIR = Path(__file__).resolve().parent.parent.parent / "profiles"


class ServiceDefinition(BaseModel):
    """Single service from profiles/service_catalog/{cloud}.yaml."""

    model_config = ConfigDict(strict=True, frozen=True)

    id: str
    display_name: str
    category: str
    resource_types: list[str]
    compliance_surface: list[str]
    default_config: dict[str, Any]


class ServiceCatalog(BaseModel):
    """All services for one cloud provider."""

    model_config = ConfigDict(strict=True, frozen=True)

    cloud: str
    services: list[ServiceDefinition]

    def get_service(self, service_id: str) -> ServiceDefinition | None:
        """Look up a service by ID."""
        for svc in self.services:
            if svc.id == service_id:
                return svc
        return None

    def get_services_by_category(self, category: str) -> list[ServiceDefinition]:
        """Filter services by category."""
        return [s for s in self.services if s.category == category]

    def list_service_ids(self) -> list[str]:
        """Return all service IDs."""
        return [s.id for s in self.services]


@lru_cache(maxsize=3)
def load_service_catalog(cloud: str) -> ServiceCatalog:
    """Load profiles/service_catalog/{cloud}.yaml. Raises if file missing."""
    path = _PROFILES_DIR / "service_catalog" / f"{cloud}.yaml"
    if not path.exists():
        raise ServiceCatalogNotFoundError(cloud)

    raw = yaml.safe_load(path.read_text(encoding="utf-8"))
    services = [ServiceDefinition.model_validate(s) for s in raw.get("services", [])]
    return ServiceCatalog(cloud=cloud, services=services)


def _reset_cache() -> None:
    """Clear cached catalogs — for testing only."""
    load_service_catalog.cache_clear()
