from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.binder import Binder
from ...models.error_response import ErrorResponse
from ...models.update_binder_input import UpdateBinderInput
from ...types import Response


def _get_kwargs(
    collection_id: UUID,
    binder_id: UUID,
    *,
    body: UpdateBinderInput,
) -> dict[str, Any]:
    headers: dict[str, Any] = {}

    _kwargs: dict[str, Any] = {
        "method": "put",
        "url": f"/v1/collection/{collection_id}/binders/{binder_id}",
    }

    _kwargs["json"] = body.to_dict()

    headers["Content-Type"] = "application/json"

    _kwargs["headers"] = headers
    return _kwargs


def _parse_response(
    *, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Binder, ErrorResponse]]:
    if response.status_code == 200:
        response_200 = Binder.from_dict(response.json())

        return response_200

    if response.status_code == 201:
        response_201 = Binder.from_dict(response.json())

        return response_201

    if response.status_code == 400:
        response_400 = ErrorResponse.from_dict(response.json())

        return response_400

    if response.status_code == 401:
        response_401 = ErrorResponse.from_dict(response.json())

        return response_401

    if response.status_code == 404:
        response_404 = ErrorResponse.from_dict(response.json())

        return response_404

    if response.status_code == 500:
        response_500 = ErrorResponse.from_dict(response.json())

        return response_500

    if client.raise_on_unexpected_status:
        raise errors.UnexpectedStatus(response.status_code, response.content)
    else:
        return None


def _build_response(
    *, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Binder, ErrorResponse]]:
    return Response(
        status_code=HTTPStatus(response.status_code),
        content=response.content,
        headers=response.headers,
        parsed=_parse_response(client=client, response=response),
    )


def sync_detailed(
    collection_id: UUID,
    binder_id: UUID,
    *,
    client: AuthenticatedClient,
    body: UpdateBinderInput,
) -> Response[Union[Binder, ErrorResponse]]:
    """Update binder

     Update an existing binder's properties.

    **Path Parameters:**
    - **collectionId**: UUID of the parent collection
    - **binderId**: UUID of the binder to update

    **Updatable Fields:**
    - **name**: New binder name (must be unique within collection)
    - **description**: Updated description
    - **type**: Change binder type (showcase, for_sale, for_trade, organizing)
    - **isPublic**: Toggle visibility
    - **sortOrder**: Adjust display order

    **Important Notes:**
    - Cannot change the parent collection
    - Binder ID remains the same
    - Cards in binder are not affected
    - Name must remain unique

    **Use Cases:**
    - Rename binder
    - Change binder purpose
    - Update description
    - Adjust privacy settings

    Args:
        collection_id (UUID):
        binder_id (UUID):
        body (UpdateBinderInput):

    Raises:
        errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
        httpx.TimeoutException: If the request takes longer than Client.timeout.

    Returns:
        Response[Union[Binder, ErrorResponse]]
    """

    kwargs = _get_kwargs(
        collection_id=collection_id,
        binder_id=binder_id,
        body=body,
    )

    response = client.get_httpx_client().request(
        **kwargs,
    )

    return _build_response(client=client, response=response)


def sync(
    collection_id: UUID,
    binder_id: UUID,
    *,
    client: AuthenticatedClient,
    body: UpdateBinderInput,
) -> Optional[Union[Binder, ErrorResponse]]:
    """Update binder

     Update an existing binder's properties.

    **Path Parameters:**
    - **collectionId**: UUID of the parent collection
    - **binderId**: UUID of the binder to update

    **Updatable Fields:**
    - **name**: New binder name (must be unique within collection)
    - **description**: Updated description
    - **type**: Change binder type (showcase, for_sale, for_trade, organizing)
    - **isPublic**: Toggle visibility
    - **sortOrder**: Adjust display order

    **Important Notes:**
    - Cannot change the parent collection
    - Binder ID remains the same
    - Cards in binder are not affected
    - Name must remain unique

    **Use Cases:**
    - Rename binder
    - Change binder purpose
    - Update description
    - Adjust privacy settings

    Args:
        collection_id (UUID):
        binder_id (UUID):
        body (UpdateBinderInput):

    Raises:
        errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
        httpx.TimeoutException: If the request takes longer than Client.timeout.

    Returns:
        Union[Binder, ErrorResponse]
    """

    return sync_detailed(
        collection_id=collection_id,
        binder_id=binder_id,
        client=client,
        body=body,
    ).parsed


async def asyncio_detailed(
    collection_id: UUID,
    binder_id: UUID,
    *,
    client: AuthenticatedClient,
    body: UpdateBinderInput,
) -> Response[Union[Binder, ErrorResponse]]:
    """Update binder

     Update an existing binder's properties.

    **Path Parameters:**
    - **collectionId**: UUID of the parent collection
    - **binderId**: UUID of the binder to update

    **Updatable Fields:**
    - **name**: New binder name (must be unique within collection)
    - **description**: Updated description
    - **type**: Change binder type (showcase, for_sale, for_trade, organizing)
    - **isPublic**: Toggle visibility
    - **sortOrder**: Adjust display order

    **Important Notes:**
    - Cannot change the parent collection
    - Binder ID remains the same
    - Cards in binder are not affected
    - Name must remain unique

    **Use Cases:**
    - Rename binder
    - Change binder purpose
    - Update description
    - Adjust privacy settings

    Args:
        collection_id (UUID):
        binder_id (UUID):
        body (UpdateBinderInput):

    Raises:
        errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
        httpx.TimeoutException: If the request takes longer than Client.timeout.

    Returns:
        Response[Union[Binder, ErrorResponse]]
    """

    kwargs = _get_kwargs(
        collection_id=collection_id,
        binder_id=binder_id,
        body=body,
    )

    response = await client.get_async_httpx_client().request(**kwargs)

    return _build_response(client=client, response=response)


async def asyncio(
    collection_id: UUID,
    binder_id: UUID,
    *,
    client: AuthenticatedClient,
    body: UpdateBinderInput,
) -> Optional[Union[Binder, ErrorResponse]]:
    """Update binder

     Update an existing binder's properties.

    **Path Parameters:**
    - **collectionId**: UUID of the parent collection
    - **binderId**: UUID of the binder to update

    **Updatable Fields:**
    - **name**: New binder name (must be unique within collection)
    - **description**: Updated description
    - **type**: Change binder type (showcase, for_sale, for_trade, organizing)
    - **isPublic**: Toggle visibility
    - **sortOrder**: Adjust display order

    **Important Notes:**
    - Cannot change the parent collection
    - Binder ID remains the same
    - Cards in binder are not affected
    - Name must remain unique

    **Use Cases:**
    - Rename binder
    - Change binder purpose
    - Update description
    - Adjust privacy settings

    Args:
        collection_id (UUID):
        binder_id (UUID):
        body (UpdateBinderInput):

    Raises:
        errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
        httpx.TimeoutException: If the request takes longer than Client.timeout.

    Returns:
        Union[Binder, ErrorResponse]
    """

    return (
        await asyncio_detailed(
            collection_id=collection_id,
            binder_id=binder_id,
            client=client,
            body=body,
        )
    ).parsed
