from typing import Any

import httpx


class IrisAdapter:
    def __init__(self, base_url: str, api_key: str) -> None:
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key

    def _headers(self) -> dict[str, str]:
        return {"Authorization": f"Bearer {self.api_key}"} if self.api_key else {}

    async def create_case(self, payload: dict[str, Any]) -> dict[str, Any]:
        headers = self._headers()
        async with httpx.AsyncClient(verify=False, timeout=20.0) as client:
            v2_url = f"{self.base_url}/api/v2/cases"
            response = await client.post(v2_url, json=payload, headers=headers)

            if response.status_code == 404:
                legacy_url = f"{self.base_url}/manage/cases/add"
                response = await client.post(legacy_url, json=payload, headers=headers)
                active_url = legacy_url
            else:
                active_url = v2_url

            try:
                response.raise_for_status()
            except httpx.HTTPStatusError as exc:
                detail = response.text.strip()
                raise RuntimeError(
                    f"IRIS returned {response.status_code} for {active_url}. Response: {detail}"
                ) from exc
            return response.json() if response.content else {"status_code": response.status_code}

    async def update_case(self, case_id: str, payload: dict[str, Any]) -> dict[str, Any]:
        headers = self._headers()
        async with httpx.AsyncClient(verify=False, timeout=20.0) as client:
            v2_url = f"{self.base_url}/api/v2/cases/{case_id}"
            response = await client.put(v2_url, json=payload, headers=headers)

            if response.status_code == 404:
                legacy_url = f"{self.base_url}/manage/cases/update/{case_id}"
                response = await client.post(legacy_url, json=payload, headers=headers)
                active_url = legacy_url
            else:
                active_url = v2_url

            try:
                response.raise_for_status()
            except httpx.HTTPStatusError as exc:
                detail = response.text.strip()
                raise RuntimeError(
                    f"IRIS returned {response.status_code} for {active_url}. Response: {detail}"
                ) from exc
            return response.json() if response.content else {"status_code": response.status_code}

    async def whoami(self) -> dict[str, Any]:
        headers = self._headers()
        url = f"{self.base_url}/user/whoami"
        async with httpx.AsyncClient(verify=False, timeout=20.0) as client:
            response = await client.get(url, headers=headers)
            response.raise_for_status()
            return response.json() if response.content else {"status_code": response.status_code}

    async def list_cases(self, limit: int = 50, offset: int = 0) -> dict[str, Any]:
        headers = self._headers()
        safe_limit = max(1, limit)
        safe_offset = max(0, offset)
        v2_url = f"{self.base_url}/api/v2/cases"
        params = {"limit": safe_limit, "offset": safe_offset}
        async with httpx.AsyncClient(verify=False, timeout=20.0) as client:
            response = await client.get(v2_url, params=params, headers=headers)
            active_url = v2_url

            # Older IRIS releases may not expose /api/v2/cases for listing.
            if response.status_code == 404:
                legacy_url = f"{self.base_url}/manage/cases/list"
                legacy_attempts: list[tuple[str, dict[str, Any] | None, dict[str, Any] | None]] = [
                    ("post", None, {"start": safe_offset, "length": safe_limit, "draw": 1}),
                    ("post", None, {"page": (safe_offset // safe_limit) + 1, "per_page": safe_limit}),
                    ("get", {"limit": safe_limit, "offset": safe_offset}, None),
                ]

                for method, legacy_params, legacy_payload in legacy_attempts:
                    if method == "post":
                        response = await client.post(
                            legacy_url,
                            params=legacy_params,
                            json=legacy_payload,
                            headers=headers,
                        )
                    else:
                        response = await client.get(
                            legacy_url,
                            params=legacy_params,
                            headers=headers,
                        )
                    active_url = legacy_url
                    if response.status_code not in {404, 405, 415}:
                        break

            try:
                response.raise_for_status()
            except httpx.HTTPStatusError as exc:
                detail = response.text.strip()
                raise RuntimeError(
                    f"IRIS returned {response.status_code} for {active_url}. Response: {detail}"
                ) from exc

            if not response.content:
                return {"status_code": response.status_code}

            result = response.json()
            if isinstance(result, dict) and isinstance(result.get("data"), list):
                total = result.get("recordsTotal")
                if not isinstance(total, int):
                    total = len(result["data"])
                return {
                    "items": result["data"],
                    "total": total,
                    "limit": safe_limit,
                    "offset": safe_offset,
                    "source": "legacy_manage_cases_list",
                    "raw": result,
                }
            return result
