# This file was auto-generated by Fern from our API Definition.

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.error_response import ErrorResponse
from .types.get_dimensions_id_response import GetDimensionsIdResponse
from .types.get_dimensions_root_response import GetDimensionsRootResponse
from .types.post_dimensions_bulk_request_dimensions_item import PostDimensionsBulkRequestDimensionsItem
from .types.post_dimensions_bulk_response import PostDimensionsBulkResponse
from .types.post_dimensions_root_request_ottimate_type import PostDimensionsRootRequestOttimateType
from .types.post_dimensions_root_response import PostDimensionsRootResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawDimensionsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def get_dimensions_root(
        self,
        *,
        ottimate_company_id: typing.Optional[int] = None,
        erp_type: typing.Optional[str] = None,
        detail: typing.Optional[typing.Literal["basic"]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[GetDimensionsRootResponse]:
        """
        Returns a paginated list of dimensions, filterable by company and type. The `detail=basic` query parameter returns a simplified response.

        Parameters
        ----------
        ottimate_company_id : typing.Optional[int]
            Filter dimensions by company ID

        erp_type : typing.Optional[str]
            Filter dimensions by ERP type

        detail : typing.Optional[typing.Literal["basic"]]
            Specify the level of detail in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[GetDimensionsRootResponse]
            Successful response with paginated dimension list
        """
        _response = self._client_wrapper.httpx_client.request(
            "dimensions",
            method="GET",
            params={
                "ottimate_company_id": ottimate_company_id,
                "erp_type": erp_type,
                "detail": detail,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetDimensionsRootResponse,
                    parse_obj_as(
                        type_=GetDimensionsRootResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def post_dimensions_root(
        self,
        *,
        ottimate_company_id: int,
        erp_type: str,
        ottimate_type: PostDimensionsRootRequestOttimateType,
        name: str,
        code: str,
        reference_id: str,
        erp_dimension_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PostDimensionsRootResponse]:
        """
        Creates a new dimension with the provided details. The `reference_id` and `erp_dimension_id` are required for a successful creation.

        Parameters
        ----------
        ottimate_company_id : int
            The Ottimate company ID this dimension belongs to

        erp_type : str
            The dimension category label as displayed in the client's ERP system (e.g., 'Account', 'GLACCOUNT', 'Department'). This is client-specific.

        ottimate_type : PostDimensionsRootRequestOttimateType
            Ottimate's standardized dimension type code for consistent categorization.

        name : str
            Display name of the dimension

        code : str
            The GL code or short identifier for this dimension in the client's ERP system

        reference_id : str
            A unique reference identifier that tracks this dimension across all client systems (ERP, inventory management, Ottimate)

        erp_dimension_id : str
            The identifier assigned to this dimension by the client's ERP software

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[PostDimensionsRootResponse]
            Successfully created
        """
        _response = self._client_wrapper.httpx_client.request(
            "dimensions",
            method="POST",
            json={
                "ottimate_company_id": ottimate_company_id,
                "erp_type": erp_type,
                "ottimate_type": ottimate_type,
                "name": name,
                "code": code,
                "reference_id": reference_id,
                "erp_dimension_id": erp_dimension_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PostDimensionsRootResponse,
                    parse_obj_as(
                        type_=PostDimensionsRootResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dimensions_id(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetDimensionsIdResponse]:
        """
        Returns detailed information for a single dimension using its unique ID.

        Parameters
        ----------
        id : str
            The unique ID of the dimension

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[GetDimensionsIdResponse]
            Successful response with dimension details
        """
        _response = self._client_wrapper.httpx_client.request(
            f"dimensions/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetDimensionsIdResponse,
                    parse_obj_as(
                        type_=GetDimensionsIdResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def post_dimensions_bulk(
        self,
        *,
        ottimate_company_id: int,
        dimensions: typing.Sequence[PostDimensionsBulkRequestDimensionsItem],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PostDimensionsBulkResponse]:
        """
        Allows for the creation or updating of multiple dimensions in a single request. The request body should contain a `ottimate_company_id` and an array of `dimensions`. Maximum 100 dimensions per request.

        Parameters
        ----------
        ottimate_company_id : int
            The Ottimate company ID these dimensions belong to

        dimensions : typing.Sequence[PostDimensionsBulkRequestDimensionsItem]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[PostDimensionsBulkResponse]
            Successfully created or updated
        """
        _response = self._client_wrapper.httpx_client.request(
            "dimensions/bulk",
            method="POST",
            json={
                "ottimate_company_id": ottimate_company_id,
                "dimensions": convert_and_respect_annotation_metadata(
                    object_=dimensions,
                    annotation=typing.Sequence[PostDimensionsBulkRequestDimensionsItem],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PostDimensionsBulkResponse,
                    parse_obj_as(
                        type_=PostDimensionsBulkResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawDimensionsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def get_dimensions_root(
        self,
        *,
        ottimate_company_id: typing.Optional[int] = None,
        erp_type: typing.Optional[str] = None,
        detail: typing.Optional[typing.Literal["basic"]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[GetDimensionsRootResponse]:
        """
        Returns a paginated list of dimensions, filterable by company and type. The `detail=basic` query parameter returns a simplified response.

        Parameters
        ----------
        ottimate_company_id : typing.Optional[int]
            Filter dimensions by company ID

        erp_type : typing.Optional[str]
            Filter dimensions by ERP type

        detail : typing.Optional[typing.Literal["basic"]]
            Specify the level of detail in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[GetDimensionsRootResponse]
            Successful response with paginated dimension list
        """
        _response = await self._client_wrapper.httpx_client.request(
            "dimensions",
            method="GET",
            params={
                "ottimate_company_id": ottimate_company_id,
                "erp_type": erp_type,
                "detail": detail,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetDimensionsRootResponse,
                    parse_obj_as(
                        type_=GetDimensionsRootResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def post_dimensions_root(
        self,
        *,
        ottimate_company_id: int,
        erp_type: str,
        ottimate_type: PostDimensionsRootRequestOttimateType,
        name: str,
        code: str,
        reference_id: str,
        erp_dimension_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PostDimensionsRootResponse]:
        """
        Creates a new dimension with the provided details. The `reference_id` and `erp_dimension_id` are required for a successful creation.

        Parameters
        ----------
        ottimate_company_id : int
            The Ottimate company ID this dimension belongs to

        erp_type : str
            The dimension category label as displayed in the client's ERP system (e.g., 'Account', 'GLACCOUNT', 'Department'). This is client-specific.

        ottimate_type : PostDimensionsRootRequestOttimateType
            Ottimate's standardized dimension type code for consistent categorization.

        name : str
            Display name of the dimension

        code : str
            The GL code or short identifier for this dimension in the client's ERP system

        reference_id : str
            A unique reference identifier that tracks this dimension across all client systems (ERP, inventory management, Ottimate)

        erp_dimension_id : str
            The identifier assigned to this dimension by the client's ERP software

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[PostDimensionsRootResponse]
            Successfully created
        """
        _response = await self._client_wrapper.httpx_client.request(
            "dimensions",
            method="POST",
            json={
                "ottimate_company_id": ottimate_company_id,
                "erp_type": erp_type,
                "ottimate_type": ottimate_type,
                "name": name,
                "code": code,
                "reference_id": reference_id,
                "erp_dimension_id": erp_dimension_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PostDimensionsRootResponse,
                    parse_obj_as(
                        type_=PostDimensionsRootResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dimensions_id(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetDimensionsIdResponse]:
        """
        Returns detailed information for a single dimension using its unique ID.

        Parameters
        ----------
        id : str
            The unique ID of the dimension

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[GetDimensionsIdResponse]
            Successful response with dimension details
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"dimensions/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetDimensionsIdResponse,
                    parse_obj_as(
                        type_=GetDimensionsIdResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def post_dimensions_bulk(
        self,
        *,
        ottimate_company_id: int,
        dimensions: typing.Sequence[PostDimensionsBulkRequestDimensionsItem],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PostDimensionsBulkResponse]:
        """
        Allows for the creation or updating of multiple dimensions in a single request. The request body should contain a `ottimate_company_id` and an array of `dimensions`. Maximum 100 dimensions per request.

        Parameters
        ----------
        ottimate_company_id : int
            The Ottimate company ID these dimensions belong to

        dimensions : typing.Sequence[PostDimensionsBulkRequestDimensionsItem]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[PostDimensionsBulkResponse]
            Successfully created or updated
        """
        _response = await self._client_wrapper.httpx_client.request(
            "dimensions/bulk",
            method="POST",
            json={
                "ottimate_company_id": ottimate_company_id,
                "dimensions": convert_and_respect_annotation_metadata(
                    object_=dimensions,
                    annotation=typing.Sequence[PostDimensionsBulkRequestDimensionsItem],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PostDimensionsBulkResponse,
                    parse_obj_as(
                        type_=PostDimensionsBulkResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorResponse,
                        parse_obj_as(
                            type_=ErrorResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
