"""Extract data from FHIR Bundle resources."""

from __future__ import annotations

from typing import Any

from fhir_agent_tools._parse import _error, _parse_resource


def get_bundle_entries(
    bundle: str | dict | Any,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Extract all resources from Bundle entries.

    Returns {success, data} with data as list of raw resource dicts.
    Each entry.resource is included.
    """
    try:
        if bundle is None or (isinstance(bundle, str) and bundle.strip() == ""):
            err = _error("empty_input", "No input provided")
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(err["error"])
            return err

        resource = _parse_resource(bundle, "Bundle")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        entries = []
        for entry in resource.entry or []:
            res = getattr(entry, "resource", None)
            if res is not None:
                entries.append(res.model_dump() if hasattr(res, "model_dump") else res)

        result = {"success": True, "data": entries}
        if raise_on_error:
            return result["data"]
        return result

    except Exception as e:
        err = _error("unexpected_error", str(e), details=repr(e))
        if raise_on_error:
            from fhir_agent_tools._parse import FhirExtractError
            raise FhirExtractError(err["error"])
        return err


def get_resources_by_type(
    bundle: str | dict | Any,
    resource_type: str,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Filter Bundle entries by resourceType.

    Returns {success, data} with data as list of matching resources.
    """
    try:
        if bundle is None or (isinstance(bundle, str) and bundle.strip() == ""):
            err = _error("empty_input", "No input provided")
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(err["error"])
            return err

        resource = _parse_resource(bundle, "Bundle")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        rt_lower = resource_type.strip().lower()
        entries = []
        for entry in resource.entry or []:
            res = getattr(entry, "resource", None)
            if res is not None:
                rt = None
                if hasattr(res, "get_resource_type"):
                    rt = res.get_resource_type()
                else:
                    rt = getattr(res, "resourceType", None) or getattr(res, "resource_type", None)
                if hasattr(res, "model_dump") and rt is None:
                    d = res.model_dump()
                    rt = d.get("resourceType")
                if rt and str(rt).lower() == rt_lower:
                    entries.append(res.model_dump() if hasattr(res, "model_dump") else res)

        result = {"success": True, "data": entries}
        if raise_on_error:
            return result["data"]
        return result

    except Exception as e:
        err = _error("unexpected_error", str(e), details=repr(e))
        if raise_on_error:
            from fhir_agent_tools._parse import FhirExtractError
            raise FhirExtractError(err["error"])
        return err


def get_bundle_total(
    bundle: str | dict | Any,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Get total match count from searchset Bundle.

    Returns {success, data} with data as int or None if not present.
    """
    try:
        if bundle is None or (isinstance(bundle, str) and bundle.strip() == ""):
            err = _error("empty_input", "No input provided")
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(err["error"])
            return err

        resource = _parse_resource(bundle, "Bundle")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        total = getattr(resource, "total", None)
        result = {"success": True, "data": int(total) if total is not None else None}
        if raise_on_error:
            return result["data"]
        return result

    except Exception as e:
        err = _error("unexpected_error", str(e), details=repr(e))
        if raise_on_error:
            from fhir_agent_tools._parse import FhirExtractError
            raise FhirExtractError(err["error"])
        return err
