# coding: utf-8

"""
Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT.
"""

from __future__ import annotations

from json import loads
from re import match
from sys import version_info
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, ConfigDict, field_validator

if version_info >= (3, 11):
    from typing import Self
else:
    from typing_extensions import Self


from algoliasearch.composition.models.exhaustive import Exhaustive
from algoliasearch.composition.models.facet_stats import FacetStats
from algoliasearch.composition.models.hit import Hit
from algoliasearch.composition.models.redirect import Redirect
from algoliasearch.composition.models.rendering_content import RenderingContent
from algoliasearch.composition.models.results_composition_info_response import (
    ResultsCompositionInfoResponse,
)

_ALIASES = {
    "ab_test_id": "abTestID",
    "ab_test_variant_id": "abTestVariantID",
    "around_lat_lng": "aroundLatLng",
    "automatic_radius": "automaticRadius",
    "exhaustive": "exhaustive",
    "applied_rules": "appliedRules",
    "exhaustive_facets_count": "exhaustiveFacetsCount",
    "exhaustive_nb_hits": "exhaustiveNbHits",
    "exhaustive_typo": "exhaustiveTypo",
    "facets": "facets",
    "facets_stats": "facets_stats",
    "index": "index",
    "index_used": "indexUsed",
    "message": "message",
    "nb_sorted_hits": "nbSortedHits",
    "parsed_query": "parsedQuery",
    "processing_time_ms": "processingTimeMS",
    "processing_timings_ms": "processingTimingsMS",
    "query_after_removal": "queryAfterRemoval",
    "redirect": "redirect",
    "rendering_content": "renderingContent",
    "server_time_ms": "serverTimeMS",
    "server_used": "serverUsed",
    "user_data": "userData",
    "query_id": "queryID",
    "automatic_insights": "_automaticInsights",
    "page": "page",
    "nb_hits": "nbHits",
    "nb_pages": "nbPages",
    "hits_per_page": "hitsPerPage",
    "hits": "hits",
    "query": "query",
    "params": "params",
    "compositions": "compositions",
}


def _alias_generator(name: str) -> str:
    return _ALIASES.get(name, name)


class SearchResultsItem(BaseModel):
    """
    SearchResultsItem
    """

    ab_test_id: Optional[int] = None
    """ A/B test ID. This is only included in the response for indices that are part of an A/B test. """
    ab_test_variant_id: Optional[int] = None
    """ Variant ID. This is only included in the response for indices that are part of an A/B test. """
    around_lat_lng: Optional[str] = None
    """ Computed geographical location. """
    automatic_radius: Optional[str] = None
    """ Distance from a central coordinate provided by `aroundLatLng`. """
    exhaustive: Optional[Exhaustive] = None
    applied_rules: Optional[List[object]] = None
    """ Rules applied to the query. """
    exhaustive_facets_count: Optional[bool] = None
    """ See the `facetsCount` field of the `exhaustive` object in the response. """
    exhaustive_nb_hits: Optional[bool] = None
    """ See the `nbHits` field of the `exhaustive` object in the response. """
    exhaustive_typo: Optional[bool] = None
    """ See the `typo` field of the `exhaustive` object in the response. """
    facets: Optional[Dict[str, Dict[str, int]]] = None
    """ Facet counts. """
    facets_stats: Optional[Dict[str, FacetStats]] = None
    """ Statistics for numerical facets. """
    index: Optional[str] = None
    """ Index name used for the query. """
    index_used: Optional[str] = None
    """ Index name used for the query. During A/B testing, the targeted index isn't always the index used by the query. """
    message: Optional[str] = None
    """ Warnings about the query. """
    nb_sorted_hits: Optional[int] = None
    """ Number of hits selected and sorted by the relevant sort algorithm. """
    parsed_query: Optional[str] = None
    """ Post-[normalization](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/#what-does-normalization-mean) query string that will be searched. """
    processing_time_ms: Optional[int] = None
    """ Time the server took to process the request, in milliseconds. """
    processing_timings_ms: Optional[object] = None
    """ Experimental. List of processing steps and their times, in milliseconds. You can use this list to investigate performance issues. """
    query_after_removal: Optional[str] = None
    """ Markup text indicating which parts of the original query have been removed to retrieve a non-empty result set. """
    redirect: Optional[Redirect] = None
    rendering_content: Optional[RenderingContent] = None
    server_time_ms: Optional[int] = None
    """ Time the server took to process the request, in milliseconds. """
    server_used: Optional[str] = None
    """ Host name of the server that processed the request. """
    user_data: Optional[object] = None
    """ An object with custom data.  You can store up to 32kB as custom data.  """
    query_id: Optional[str] = None
    """ Unique identifier for the query. This is used for [click analytics](https://www.algolia.com/doc/guides/analytics/click-analytics/). """
    automatic_insights: Optional[bool] = None
    """ Whether automatic events collection is enabled for the application. """
    page: int
    """ Page of search results to retrieve. """
    nb_hits: int
    """ Number of results (hits). """
    nb_pages: int
    """ Number of pages of results. """
    hits_per_page: int
    """ Number of hits per page. """
    hits: List[Hit]
    """ Search results (hits).  Hits are records from your index that match the search criteria, augmented with additional attributes, such as, for highlighting.  """
    query: str
    """ Search query. """
    params: str
    """ URL-encoded string of all search parameters. """
    compositions: Dict[str, ResultsCompositionInfoResponse]

    @field_validator("around_lat_lng")
    def around_lat_lng_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if value is None:
            return value

        if not match(r"^(-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)$", value):
            raise ValueError(
                r"must validate the regular expression /^(-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)$/"
            )
        return value

    model_config = ConfigDict(
        strict=False,
        use_enum_values=True,
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
        alias_generator=_alias_generator,
        extra="allow",
    )

    def to_json(self) -> str:
        return self.model_dump_json(by_alias=True, exclude_unset=True)

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of SearchResultsItem from a JSON string"""
        return cls.from_dict(loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias."""
        return self.model_dump(
            by_alias=True,
            exclude_none=True,
            exclude_unset=True,
        )

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of SearchResultsItem from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        obj["exhaustive"] = (
            Exhaustive.from_dict(obj["exhaustive"])
            if obj.get("exhaustive") is not None
            else None
        )
        obj["facets_stats"] = (
            dict(
                (_k, FacetStats.from_dict(_v)) for _k, _v in obj["facets_stats"].items()
            )
            if obj.get("facets_stats") is not None
            else None
        )
        obj["redirect"] = (
            Redirect.from_dict(obj["redirect"])
            if obj.get("redirect") is not None
            else None
        )
        obj["renderingContent"] = (
            RenderingContent.from_dict(obj["renderingContent"])
            if obj.get("renderingContent") is not None
            else None
        )
        obj["hits"] = (
            [Hit.from_dict(_item) for _item in obj["hits"]]
            if obj.get("hits") is not None
            else None
        )
        obj["compositions"] = (
            dict(
                (_k, ResultsCompositionInfoResponse.from_dict(_v))
                for _k, _v in obj["compositions"].items()
            )
            if obj.get("compositions") is not None
            else None
        )

        return cls.model_validate(obj)
