{#
    This is a custom template derived from:
    https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/endpoint_module.py.jinja
#}
from http import HTTPStatus
from typing import Any, Optional, Union, cast

{# CHANGE START (1) - switch out httpx for requests #}
{# import httpx #}
import requests
{# CHANGE END (1) #}

from ...client import AuthenticatedClient, Client
{# CHANGE START (2) - add missing Unset import #}
{# CHANGE START (19) - import check_nested_instance #}
from ...types import Response, UNSET, Unset, check_nested_instance
{# CHANGE END (19) #}
{# CHANGE END (2) #}
from ... import errors

{% for relative in endpoint.relative_imports | sort %}
{{ relative }}
{% endfor %}

{% from "endpoint_macros.py.jinja" import header_params, cookie_params, query_params,
    arguments, client, kwargs, parse_response, docstring, body_to_kwarg %}

{% set return_string = endpoint.response_type() %}
{% set parsed_responses = (endpoint.responses | length > 0) and return_string != "Any" %}

{# CHANGE START (3) - expose endpoint query parameters #}
QUERY_PARAMS = {
    {% for parameter in endpoint.query_parameters %}
    "{{ parameter.name }}": {{ parameter.get_type_string(no_optional=True) }},
    {% endfor %}
}
{# CHANGE END (3) #}

{# CHANGE START (4) - expose request body type if exists #}
{% if endpoint.bodies | length >= 1 %}
REQUEST_BODY_TYPE = {{ endpoint.bodies[0].prop.get_type_string() }}
{% endif %}
{# CHANGE END (4) #}

def _get_kwargs(
{# CHANGE START (5) - include client in arguments #}
    {{ arguments(endpoint, include_client=True) | indent(4) }}
{# CHANGE END (5) #}
) -> dict[str, Any]:
    {{ header_params(endpoint) | indent(4) }}

    {{ cookie_params(endpoint) | indent(4) }}

    {{ query_params(endpoint) | indent(4) }}

    _kwargs: dict[str, Any] = {
        {# CHANGE START (6) - don't include method in kwargs #}
        {# "method": "{{ endpoint.method }}", #}
        {# CHANGE END (6) #}
        {% if endpoint.path_parameters %}
        {# CHANGE START (7) - use base URL from client #}
        "url": f"{client.base_url}{{ endpoint.path }}".format(
        {# CHANGE END (7) #}
        {%- for parameter in endpoint.path_parameters -%}
        {{parameter.python_name}}={{parameter.python_name}},
        {%- endfor -%}
        ),
        {% else %}
        {# CHANGE START (8) - use base URL from client #}
        "url": f"{client.base_url}{{ endpoint.path }}",
        {# CHANGE END (8) #}
        {% endif %}
        {% if endpoint.query_parameters %}
        "params": params,
        {% endif %}
        {% if endpoint.cookie_parameters %}
        "cookies": cookies,
        {% endif %}
    }

{% if endpoint.bodies | length > 1 %}
{% for body in endpoint.bodies %}
    {# CHANGE START (9) - keep only application/json content type #}
    {% if body.content_type == "application/json" %}
    {# CHANGE START (20) - use check_nested_instance instead of raw isinstance #}
    {# if isinstance(body, {{body.prop.get_type_string() }}): #}
    if check_nested_instance(body, {{body.prop.get_type_string() }}):
    {# CHANGE END (20) #}
        {% set destination = "_" + body.body_type + "_body" %}
        {{ body_to_kwarg(body, destination) | indent(8) }}
        _kwargs["{{ body.body_type.value }}"] = {{ destination }}
        headers["Content-Type"] = "{{ body.content_type }}"
    {% endif %}
    {# CHANGE END (9) #}
{% endfor %}
{% elif endpoint.bodies | length == 1 %}
{% set body = endpoint.bodies[0] %}
    {{ body_to_kwarg(body, "_body") | indent(4) }}
    _kwargs["{{ body.body_type.value }}"] = _body
    {% if body.content_type != "multipart/form-data" %}{# Need httpx to set the boundary automatically #}
    headers["Content-Type"] = "{{ body.content_type }}"
    {% endif %}
{% endif %}

{# CHANGE START (10) - fill in headers always #}
{# {% if endpoint.header_parameters or endpoint.bodies | length > 0 %} #}
    _kwargs["headers"] = headers
{# {% endif %} #}
{# CHANGE END (10) #}
    return _kwargs

{# CHANGE START (11) - switch out httpx for requests  #}
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: requests.Response) -> Optional[{{ return_string }}]:
{# CHANGE END (11) #}
    {% for response in endpoint.responses %}
    if response.status_code == {{ response.status_code.value }}:
        {% if parsed_responses %}{% import "property_templates/" + response.prop.template as prop_template %}
        {% if prop_template.construct %}
        {{ prop_template.construct(response.prop, response.source.attribute) | indent(8) }}
        {% elif response.source.return_type == response.prop.get_type_string()  %}
        {{ response.prop.python_name }} = {{ response.source.attribute }}
        {% else %}
        {{ response.prop.python_name }} = cast({{ response.prop.get_type_string() }}, {{ response.source.attribute }})
        {% endif %}
        return {{ response.prop.python_name }}
        {% else %}
        return None
        {% endif %}
    {% endfor %}
    {# TODO: consider using this once we switch to the more advanced httpx client #}
    {# CHANGE START (12) - don't use UnexpectedStatus raising #}
    {# if client.raise_on_unexpected_status:
        raise errors.UnexpectedStatus(response.status_code, response.content)
    else:
        return None #}
    {# CHANGE END (12) #}

{# CHANGE START (13) - switch out httpx for requests  #}
def _build_response(*, client: Union[AuthenticatedClient, Client], response: requests.Response) -> Response[{{ return_string }}]:
{# CHANGE END (13) #}
    return Response(
        status_code=HTTPStatus(response.status_code),
        content=response.content,
        headers=response.headers,
        parsed=_parse_response(client=client, response=response),
    )


def sync_detailed(
    {{ arguments(endpoint) | indent(4) }}
) -> Response[{{ return_string }}]:
    {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }}

    kwargs = _get_kwargs(
        {# CHANGE START (14) - include client in passed arguments #}
        {{ kwargs(endpoint, include_client=True) }}
        {# CHANGE END (14) #}
    )

    {# CHANGE START (15) - use basic requests calls instead of httpx client #}
    {# response = client.get_httpx_client().request(
        **kwargs,
    ) #}
    response = requests.{{ endpoint.method }}(
        verify=client.verify_ssl,
        auth=client.auth,
        timeout=client.timeout,
        **kwargs,
    )
    {# CHANGE END (15) #}
    {# CHANGE START (16) - call raise for status #}
    response.raise_for_status()
    {# CHANGE END (16) #}

    return _build_response(client=client, response=response)

{% if parsed_responses %}
def sync(
    {{ arguments(endpoint) | indent(4) }}
) -> Optional[{{ return_string }}]:
    {{ docstring(endpoint, return_string, is_detailed=false) | indent(4) }}

    return sync_detailed(
        {{ kwargs(endpoint) }}
    ).parsed
{% endif %}

async def asyncio_detailed(
    {{ arguments(endpoint) | indent(4) }}
) -> Response[{{ return_string }}]:
    {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }}

    {# CHANGE START (17) - include client in passed arguments #}
    kwargs = _get_kwargs(
        {{ kwargs(endpoint, include_client=True) }}
    )
    {# CHANGE END (17) #}

    {# CHANGE START (18) - async session with aiohttp instead of httpx client #}
    {# response = await client.get_async_httpx_client().request(
        **kwargs
    ) #}
    async with client.get_async_session().{{ endpoint.method }}(
        verify_ssl=client.verify_ssl, raise_for_status=True, **kwargs
    ) as response:
        content = await response.read()
        resp = requests.Response()
        resp.status_code = response.status
        resp._content = content

    return _build_response(client=client, response=resp)
    {# CHANGE END (18) #}

{% if parsed_responses %}
async def asyncio(
    {{ arguments(endpoint) | indent(4) }}
) -> Optional[{{ return_string }}]:
    {{ docstring(endpoint, return_string, is_detailed=false) | indent(4) }}

    return (await asyncio_detailed(
        {{ kwargs(endpoint) }}
    )).parsed
{% endif %}
