"""Extract data from FHIR MedicationRequest resources."""

from __future__ import annotations

from typing import Any

from fhir_agent_tools._parse import _error, _parse_resource
from fhir_agent_tools._utils import format_codeable_concept, format_period, format_reference


def _get_medication(resource: Any) -> str:
    """Extract medication from MedicationRequest (CodeableConcept or Reference)."""
    med = getattr(resource, "medicationCodeableConcept", None)
    if med is not None:
        return format_codeable_concept(med)
    ref = getattr(resource, "medicationReference", None)
    if ref is not None:
        return format_reference(ref)
    return ""


def _format_dosage(dosage: Any) -> dict[str, Any] | None:
    """Format dosage instruction."""
    if dosage is None:
        return None
    text = getattr(dosage, "text", None)
    route = format_codeable_concept(getattr(dosage, "route", None))
    timing = getattr(dosage, "timing", None)
    dose = getattr(dosage, "doseAndRate", None)
    dose_val = None
    if dose:
        dr = dose[0] if isinstance(dose, list) else dose
        dv = getattr(dr, "doseQuantity", None) or getattr(dr, "doseRange", None)
        if dv is not None:
            dose_val = str(getattr(dv, "value", dv)) if hasattr(dv, "value") else str(dv)
    return {
        "text": str(text) if text else None,
        "route": route,
        "dose": dose_val,
    }


def get_medication_request_summary(
    medication_request: str | dict | Any,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Extract key MedicationRequest fields for LLM consumption."""
    try:
        if medication_request is None or (
            isinstance(medication_request, str) and medication_request.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(medication_request, "MedicationRequest")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        dosage_list = []
        for d in getattr(resource, "dosageInstruction", None) or []:
            fmt = _format_dosage(d)
            if fmt:
                dosage_list.append(fmt)

        data = {
            "id": getattr(resource, "id", None),
            "medication": _get_medication(resource),
            "status": str(getattr(resource, "status", None)) if getattr(resource, "status", None) else None,
            "intent": str(getattr(resource, "intent", None)) if getattr(resource, "intent", None) else None,
            "subject": format_reference(getattr(resource, "subject", None)),
            "authoredOn": str(getattr(resource, "authoredOn", None)) if getattr(resource, "authoredOn", None) else None,
            "dosageInstruction": dosage_list,
        }

        result = {"success": True, "data": data}
        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_medication_request_medication(
    medication_request: str | dict | Any,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Get medication name/code from MedicationRequest."""
    try:
        if medication_request is None or (
            isinstance(medication_request, str) and medication_request.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(medication_request, "MedicationRequest")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        med = _get_medication(resource)
        result = {"success": True, "data": med}
        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_medication_request_dosage(
    medication_request: str | dict | Any,
    *,
    raise_on_error: bool = False,
) -> dict[str, Any]:
    """Get dosage instructions from MedicationRequest."""
    try:
        if medication_request is None or (
            isinstance(medication_request, str) and medication_request.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(medication_request, "MedicationRequest")
        if isinstance(resource, dict):
            if raise_on_error:
                from fhir_agent_tools._parse import FhirExtractError
                raise FhirExtractError(resource["error"])
            return resource

        dosage_list = []
        for d in getattr(resource, "dosageInstruction", None) or []:
            fmt = _format_dosage(d)
            if fmt:
                dosage_list.append(fmt)

        result = {"success": True, "data": dosage_list}
        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
