# coding: utf-8
#
# This code was auto generated by AfterShip SDK Generator.
# Do not edit the class manually.

import json
from typing import Union, Annotated

from pydantic import Field

from tracking.models import (
    CreateTrackingRequest,
    CreateTrackingResponse,
    DeleteTrackingByIdResponse,
    GetTrackingByIdResponse,
    GetTrackingsResponse,
    MarkTrackingCompletedByIdRequest,
    MarkTrackingCompletedByIdResponse,
    RetrackTrackingByIdResponse,
    UpdateTrackingByIdRequest,
    UpdateTrackingByIdResponse,
)
from tracking.request import ApiClient, validate_params


class TrackingApi(ApiClient):
    """TrackingApi api implements"""

    @validate_params
    def create_tracking(
        self, create_tracking_request: Union[CreateTrackingRequest, dict], **kwargs
    ) -> CreateTrackingResponse:
        """
        Create a tracking.<div style="visibility:hidden; height: 0"></div>
        :param create_tracking_request:
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
        """
        url = "/tracking/2025-07/trackings"

        body = create_tracking_request
        if not isinstance(body, dict):
            body = create_tracking_request.model_dump(exclude_none=True)
        body = json.dumps(body)

        result = self._request("POST", url=url, body=body, **kwargs)
        return CreateTrackingResponse().from_dict(result)

    @validate_params
    def delete_tracking_by_id(
        self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
    ) -> DeleteTrackingByIdResponse:
        """
        Delete a tracking.
        :param tracking_id: str. tracking ID.
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
        """
        url = f"/tracking/2025-07/trackings/{tracking_id}"

        result = self._request("DELETE", url=url, **kwargs)
        return DeleteTrackingByIdResponse().from_dict(result)

    @validate_params
    def get_tracking_by_id(
        self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
    ) -> GetTrackingByIdResponse:
        """
        Get tracking results of a single tracking.
        :param tracking_id: str. tracking ID.
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
            query params:
                **fields**: str. List of fields to include in the response. Use comma for multiple values. Fields to include: `destination_postal_code`, `tracking_ship_date`, `tracking_account_number`, `tracking_key`, `origin_country_region`, `destination_country_region`, `destination_state`, `title`, `order_id`, `tag`, `checkpoints`
                **lang**: str. Translate checkpoint messages from the carrier’s provided language to the target language. Supported target languages include:</br>&nbsp;&nbsp;&nbsp;&nbsp;- English (en)</br>&nbsp;&nbsp;&nbsp;&nbsp;- French (fr)</br>&nbsp;&nbsp;&nbsp;&nbsp;- French Canadian (fr-CA)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Arabic (ar)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Bulgarian (bg)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Catalan (ca)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Croatian (hr)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Czech (cs)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Danish (da)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Dutch (nl)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Estonian (et)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Filipino (tl)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Finnish (fi)</br>&nbsp;&nbsp;&nbsp;&nbsp;- German (de)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Greek (el)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Hebrew (he)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Hindi (hi)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Hungarian (hu)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Indonesian (id)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Italian (it)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Japanese (ja)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Korean (ko)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Latvian (lv)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Lithuanian (lt)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Malay (ms)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Polish (pl)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Portuguese (pt)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Romanian (ro)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Russian (ru)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Serbian (sr)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Slovak (sk)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Slovenian (sl)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Spanish (es)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Swedish (sv)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Thai (th)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Turkish (tr)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Ukrainian (uk)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Vietnamese (vi)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Simplified Chinese (zh-Hans)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Traditional Chinese (zh-Hant)</br>&nbsp;&nbsp;&nbsp;&nbsp;- Norwegian (nb)</br>
        """
        url = f"/tracking/2025-07/trackings/{tracking_id}"
        params_keys = {
            "fields",
            "lang",
        }
        params = {key: kwargs.pop(key) for key in params_keys if key in kwargs}

        result = self._request("GET", url=url, params=params, **kwargs)
        return GetTrackingByIdResponse().from_dict(result)

    @validate_params
    def get_trackings(self, **kwargs) -> GetTrackingsResponse:
        """
        Get tracking results of multiple trackings.<div style="visibility:hidden; height: 0"></div>
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
            query params:
                **cursor**: str. A string representing the cursor value for the current page of results.
                **limit**: int. Number of trackings each page contain. (Default: 100, Max: 200)
                **keyword**: str. Search the content of the tracking record fields: `tracking_number`, `title`, `order_id`, `customers[x].name`, `custom_fields`, `customers[x].email`, `customers[x].phone_number`
                **tracking_numbers**: str. Tracking number of shipments. Use comma to separate multiple values (Example: RA123456789US,LE123456789US). Supports up to 50 tracking numbers.
                **slug**: str. Unique courier code Use comma for multiple values. (Example: dhl,ups,usps)
                **transit_time**: int. Total delivery time in days.- When the shipment is delivered: Transit time = Delivered date - Picked up date- When the shipment is not delivered: Transit time = Current date - Picked up dateValue as `null` for the shipment without pickup date.
                **origin**: str. Origin country/region of trackings. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
                **destination**: str. Destination country/region of trackings. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
                **tag**: str. Current status of tracking. Values include `Pending`, `InfoReceived`, `InTransit`, `OutForDelivery`, `AttemptFail`, `Delivered`, `AvailableForPickup`, `Exception`, `Expired` (See tag definition)
                **created_at_min**: str. Start date and time of trackings created. AfterShip only stores data of 120 days. Please make sure the value of the parameter is properly escaped in
                **created_at_max**: str. End date and time of trackings created. Please make sure the value of the parameter is properly escaped in
                **updated_at_min**: str. Start date and time of trackings updated. Please make sure the value of the parameter is properly escaped in
                **updated_at_max**: str. End date and time of trackings updated. Please make sure the value of the parameter is properly escaped in
                **fields**: str. List of fields to include in the response. Use comma for multiple values. Available options: `title`, `order_id`, `tag`, `checkpoints`. Example: `title,order_id`
                **return_to_sender**: str. Select return to sender, the value should be `true` or `false`, with optional comma separated.
                **courier_destination_country_region**: str. Destination country/region of trackings returned by courier. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
                **shipment_tags**: str. Tags you added to your shipments to help categorize and filter them easily. Use a comma to separate multiple values (Example: a,b)
                **order_id**: str. A globally-unique identifier for the order. Use comma for multiple values.(Example: 6845a095a27a4caeb27487806f058add,4845a095a27a4caeb27487806f058abc)
        """
        url = "/tracking/2025-07/trackings"
        params_keys = {
            "cursor",
            "limit",
            "keyword",
            "tracking_numbers",
            "slug",
            "transit_time",
            "origin",
            "destination",
            "tag",
            "created_at_min",
            "created_at_max",
            "updated_at_min",
            "updated_at_max",
            "fields",
            "return_to_sender",
            "courier_destination_country_region",
            "shipment_tags",
            "order_id",
        }
        params = {key: kwargs.pop(key) for key in params_keys if key in kwargs}

        result = self._request("GET", url=url, params=params, **kwargs)
        return GetTrackingsResponse().from_dict(
            {
                "pagination": result.get("pagination"),
                "trackings": result.get("trackings"),
            }
        )

    @validate_params
    def mark_tracking_completed_by_id(
        self,
        tracking_id: Annotated[str, Field(min_length=1)],
        mark_tracking_completed_by_id_request: Union[MarkTrackingCompletedByIdRequest, dict],
        **kwargs,
    ) -> MarkTrackingCompletedByIdResponse:
        """
        Mark a tracking as completed. The tracking won't auto update until retrack it.
        :param tracking_id: str. tracking id.
        :param mark_tracking_completed_by_id_request:
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
        """
        url = f"/tracking/2025-07/trackings/{tracking_id}/mark-as-completed"

        body = mark_tracking_completed_by_id_request
        if not isinstance(body, dict):
            body = mark_tracking_completed_by_id_request.model_dump(exclude_none=True)
        body = json.dumps(body)

        result = self._request("POST", url=url, body=body, **kwargs)
        return MarkTrackingCompletedByIdResponse().from_dict(result)

    @validate_params
    def retrack_tracking_by_id(
        self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
    ) -> RetrackTrackingByIdResponse:
        """
        Retrack an expired tracking. Max 3 times per tracking.
        :param tracking_id: str. tracking id.
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
        """
        url = f"/tracking/2025-07/trackings/{tracking_id}/retrack"

        result = self._request("POST", url=url, **kwargs)
        return RetrackTrackingByIdResponse().from_dict(result)

    @validate_params
    def update_tracking_by_id(
        self,
        tracking_id: Annotated[str, Field(min_length=1)],
        update_tracking_by_id_request: Union[UpdateTrackingByIdRequest, dict],
        **kwargs,
    ) -> UpdateTrackingByIdResponse:
        """
        Update a tracking.
        :param tracking_id: str. tracking ID.
        :param update_tracking_by_id_request:
        :param kwargs:
            request options:
                **headers** (dict): support custom headers.
                **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
                    verify the identity of requested hosts. Either `True` (default CA bundle),
                    a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
                    (which will disable verification).
        """
        url = f"/tracking/2025-07/trackings/{tracking_id}"

        body = update_tracking_by_id_request
        if not isinstance(body, dict):
            body = update_tracking_by_id_request.model_dump(exclude_none=True)
        body = json.dumps(body)

        result = self._request("PUT", url=url, body=body, **kwargs)
        return UpdateTrackingByIdResponse().from_dict(result)
