# src/anypoint_sdk/resources/apis.py
from __future__ import annotations

from dataclasses import asdict, dataclass
from typing import Any, Dict, Iterable, List, Optional

from .._http import HttpClient
from .._logging import LoggerLike, default_logger


@dataclass(frozen=True)
class ApiInstance:
    id: int
    groupId: str
    assetId: str
    assetVersion: Optional[str] = None
    productVersion: Optional[str] = None
    environmentId: Optional[str] = None
    instanceLabel: Optional[str] = None
    status: Optional[str] = None
    technology: Optional[str] = None
    activeContractsCount: Optional[int] = None
    exchangeAssetName: Optional[str] = None  # from enclosing asset object


def _to_instance(asset: Dict[str, Any], inst: Dict[str, Any]) -> ApiInstance:
    return ApiInstance(
        id=int(inst.get("id", 0)),
        groupId=str(inst.get("groupId", asset.get("groupId", ""))),
        assetId=str(inst.get("assetId", asset.get("assetId", ""))),
        assetVersion=(inst.get("assetVersion")),
        productVersion=(inst.get("productVersion")),
        environmentId=(inst.get("environmentId")),
        instanceLabel=(inst.get("instanceLabel")),
        status=(inst.get("status")),
        technology=(inst.get("technology")),
        activeContractsCount=inst.get("activeContractsCount"),
        exchangeAssetName=asset.get("exchangeAssetName"),
    )


def _dedupe(instances: Iterable[ApiInstance]) -> List[ApiInstance]:
    seen: set[int] = set()
    out: List[ApiInstance] = []
    for i in instances:
        if i.id and i.id not in seen:
            seen.add(i.id)
            out.append(i)
    return out


class APIs:
    """
    API Manager resources, minimal surface for listing and fetching instances.
    """

    def __init__(
        self, http: HttpClient, *, logger: Optional[LoggerLike] = None
    ) -> None:
        self._http = http
        self._log = logger or default_logger().child("resources.apis")

    def list_instances(
        self,
        org_id: str,
        env_id: str,
        *,
        offset: int = 0,
        limit: int = 200,
    ) -> List[Dict[str, Any]]:
        """
        List API instances in an environment.
        Returns a flattened list of dicts with keys like:
        id, groupId, assetId, assetVersion, productVersion, environmentId,
        instanceLabel, status, technology, activeContractsCount, exchangeAssetName.
        """
        r = self._http.get(
            f"/apimanager/api/v1/organizations/{org_id}/environments/{env_id}/apis",
            params={"offset": offset, "limit": limit},
        )
        payload = r.json() or {}
        assets = payload.get("assets")
        if not isinstance(assets, list):
            assets = []

        instances: List[ApiInstance] = []
        for asset in assets:
            if not isinstance(asset, dict):
                continue
            for inst in asset.get("apis") or []:
                if isinstance(inst, dict):
                    instances.append(_to_instance(asset, inst))

        flat = [asdict(x) for x in _dedupe(instances)]
        self._log.debug(
            "Listed %d API instances for org=%s env=%s", len(flat), org_id, env_id
        )
        return flat

    def get_instance(
        self,
        org_id: str,
        env_id: str,
        api_id: int | str,
    ) -> Dict[str, Any]:
        """
        Fetch full details for a single API instance id.
        Returns the JSON object as provided by the API Manager detail endpoint.
        """
        r = self._http.get(
            f"/apimanager/api/v1/organizations/{org_id}/environments/{env_id}/apis/{api_id}"
        )
        return r.json() or {}
