# coding: utf-8

"""
    Perigon API

    The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key.

    The version of the OpenAPI document: 1.0.0
    Contact: data@perigon.io
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations

import json
import pprint
import re  # noqa: F401
from typing import Any, ClassVar, Dict, List, Optional, Set

from perigon_sdk.models.coordinate_filter import CoordinateFilter
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing_extensions import Self


class ArticleSearchFilter(BaseModel):
    """
    A versatile filter object to refine search results based on articles, clusters, sources, languages, categories, locations, companies, and people. Supports logical operators (AND, OR, NOT) for complex queries. Accepts single values or arrays, with arrays applied as OR operations.
    """  # noqa: E501

    article_id: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by specific article(s). Array of article IDs. For convenience, a single string ID is also accepted.",
        alias="articleId",
    )
    cluster_id: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by specific cluster(s). Accepts either a single string or an array of strings.",
        alias="clusterId",
    )
    source: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by specific source(s). Accepts either a single string or an array of strings.",
    )
    exclude_source: Optional[List[StrictStr]] = Field(
        default=None,
        description="The domain of the website, which should be excluded from the search. Multiple parameters could be provided. Wildcards (* and ?) are suported (e.g. *.cnn.com).",
        alias="excludeSource",
    )
    source_group: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by specific source group, for example: 'top100'. Accepts either a single string or an array of strings.",
        alias="sourceGroup",
    )
    language: Optional[List[StrictStr]] = Field(
        default=None,
        description="Language code to filter by language. If an array parameters are passed, they will be applied as OR operations. For example: ['en', 'es']. Language ISO codes must be provided.",
    )
    exclude_language: Optional[List[StrictStr]] = Field(
        default=None,
        description=" A list of languages to be excluded. Any article published in one of the languages provided in this filter will not be returned. This is useful when you are interested only in news published in specific languages.",
        alias="excludeLanguage",
    )
    label: Optional[List[StrictStr]] = Field(
        default=None,
        description="Labels to filter by, could be 'Opinion', 'Paid-news', 'Non-news', etc. If multiple parameters are passed, they will be applied as OR operations. ",
    )
    exclude_label: Optional[List[StrictStr]] = Field(
        default=None,
        description="Exclude results that include specific labels (Opinion, Non-news, Paid News, etc.). You can filter multiple by repeating the parameter.",
        alias="excludeLabel",
    )
    taxonomy: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filters by Google Content Categories. This field will accept 1 or more categories, must pass the full name of the category. Example: taxonomy=/Finance/Banking/Other, /Finance/Investing/Funds",
    )
    category: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by categories. Categories are general themes that the article is about. Examples of categories: Tech, Politics, etc. If multiple parameters are passed, they will be applied as OR operations. Use 'none' to search uncategorized articles.",
    )
    topic: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by topics. Each topic is some kind of entity that the article is about. Examples of topics: Markets, Joe Biden, Green Energy, Climate Change, Cryptocurrency, etc. If multiple parameters are passed, they will be applied as OR operations.",
    )
    exclude_topic: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filter by excluding topics. Each topic is some kind of entity that the article is about. Examples of topics: Markets, Joe Biden, Green Energy, Climate Change, Cryptocurrency, etc. If multiple parameters are passed, they will be applied as OR operations.",
        alias="excludeTopic",
    )
    country: Optional[List[StrictStr]] = Field(
        default=None,
        description="Country code to filter by country. If multiple parameters are passed, they will be applied as OR operations. Only accepts country ISO codes.",
    )
    exclude_country: Optional[List[StrictStr]] = Field(
        default=None,
        description="Excludes articles from specific countries in the vector search results. Accepts a list of country codes (e.g., 'US', 'UK', 'CA'). Use this parameter to filter out articles published in countries you don't want to include in your search results. See the Country and Language Support section in the documentation for a full list of supported country codes.",
        alias="excludeCountry",
    )
    locations_country: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filters articles where a specified country plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the country in question. If multiple parameters are passed, they will be applied as OR operations. Only accepts country ISO codes.",
        alias="locationsCountry",
    )
    exclude_locations_country: Optional[List[StrictStr]] = Field(
        default=None,
        description="Excludes articles where a specified country plays a central role in the content, ensuring results are not deeply relevant to the country in question. If multiple parameters are passed, they will be applied as AND operations, excluding articles relevant to any of the specified countries.",
        alias="excludeLocationsCountry",
    )
    state: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations. Only accepts state ISO codes.",
    )
    exclude_state: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of states to exclude. Articles that include, or are associated with, any of the states provided here will be filtered out. This is especially useful if you want to ignore news tied to certain geographical areas (e.g., US states).",
        alias="excludeState",
    )
    county: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations.",
    )
    exclude_county: Optional[List[StrictStr]] = Field(
        default=None,
        description="Excludes articles from specific counties or administrative divisions in the vector search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter",
        alias="excludeCounty",
    )
    city: Optional[List[StrictStr]] = Field(
        default=None,
        description="Filters articles where a specified city plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the urban area in question. If multiple parameters are passed, they will be applied as OR operations.",
    )
    exclude_city: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of cities to exclude from the results. Articles that are associated with any of the specified cities will be filtered out.",
        alias="excludeCity",
    )
    source_country: Optional[List[StrictStr]] = Field(
        default=None,
        description="Find articles published by sources that are located within a given country. Must be 2 character country code (i.e. us, gb, etc).",
        alias="sourceCountry",
    )
    source_state: Optional[List[StrictStr]] = Field(
        default=None,
        description="Find articles published by sources that are located within a given state.",
        alias="sourceState",
    )
    source_county: Optional[List[StrictStr]] = Field(
        default=None,
        description="Find articles published by sources that are located within a given county.",
        alias="sourceCounty",
    )
    source_city: Optional[List[StrictStr]] = Field(
        default=None,
        description="Find articles published by sources that are located within a given city.",
        alias="sourceCity",
    )
    coordinates: Optional[CoordinateFilter] = None
    source_coordinates: Optional[CoordinateFilter] = Field(
        default=None, alias="sourceCoordinates"
    )
    company_id: Optional[List[StrictStr]] = Field(
        default=None, description="List of company IDs to filter by.", alias="companyId"
    )
    exclude_company_id: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of company identifiers. Articles associated with companies that have any of these unique IDs will be filtered out from the returned results, ensuring that certain companies or corporate entities are not included.",
        alias="excludeCompanyId",
    )
    company_domain: Optional[List[StrictStr]] = Field(
        default=None,
        description="Search by company domains for filtering. E.g. companyDomain=apple.com.",
        alias="companyDomain",
    )
    exclude_company_domain: Optional[List[StrictStr]] = Field(
        default=None,
        description='A list of company domains to exclude. If an article is related to a company that uses one of the specified domains (for instance, "example.com"), it will not be returned in the results.',
        alias="excludeCompanyDomain",
    )
    company_symbol: Optional[List[StrictStr]] = Field(
        default=None, description="Search by company symbols.", alias="companySymbol"
    )
    exclude_company_symbol: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of stock symbols (ticker symbols) that identify companies to be excluded. Articles related to companies using any of these symbols will be omitted, which is useful for targeting or avoiding specific public companies.",
        alias="excludeCompanySymbol",
    )
    company_name: Optional[List[StrictStr]] = Field(
        default=None, description="Search by company name.", alias="companyName"
    )
    person_wikidata_id: Optional[List[StrictStr]] = Field(
        default=None,
        description="List of person Wikidata IDs for filtering.",
        alias="personWikidataId",
    )
    exclude_person_wikidata_id: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of Wikidata identifiers for individuals. Articles mentioning persons with any of these Wikidata IDs will be filtered out. This is particularly helpful when using a unique identifier to prevent ambiguity in names.",
        alias="excludePersonWikidataId",
    )
    person_name: Optional[List[StrictStr]] = Field(
        default=None,
        description="List of person names for exact matches. Boolean and complex logic is not supported on this filter.",
        alias="personName",
    )
    exclude_person_name: Optional[List[StrictStr]] = Field(
        default=None,
        description="A list of person names that, when associated with the content, cause the article to be excluded. This filter removes articles related to any individuals whose names match those on the list.",
        alias="excludePersonName",
    )
    var_and: Optional[List[ArticleSearchFilter]] = Field(
        default=None,
        description="Adds additional AND filter objects. These objects must be of the same type as the original filter object and will be combined with the existing filter using the AND logical operator.",
        alias="AND",
    )
    var_or: Optional[List[ArticleSearchFilter]] = Field(
        default=None,
        description="Adds additional OR filter objects. These objects must be of the same type as the original filter object and will be combined with the existing filter using the OR logical operator.",
        alias="OR",
    )
    var_not: Optional[List[ArticleSearchFilter]] = Field(
        default=None,
        description="A filter object for logical NOT operations",
        alias="NOT",
    )
    __properties: ClassVar[List[str]] = [
        "articleId",
        "clusterId",
        "source",
        "excludeSource",
        "sourceGroup",
        "language",
        "excludeLanguage",
        "label",
        "excludeLabel",
        "taxonomy",
        "category",
        "topic",
        "excludeTopic",
        "country",
        "excludeCountry",
        "locationsCountry",
        "excludeLocationsCountry",
        "state",
        "excludeState",
        "county",
        "excludeCounty",
        "city",
        "excludeCity",
        "sourceCountry",
        "sourceState",
        "sourceCounty",
        "sourceCity",
        "coordinates",
        "sourceCoordinates",
        "companyId",
        "excludeCompanyId",
        "companyDomain",
        "excludeCompanyDomain",
        "companySymbol",
        "excludeCompanySymbol",
        "companyName",
        "personWikidataId",
        "excludePersonWikidataId",
        "personName",
        "excludePersonName",
        "AND",
        "OR",
        "NOT",
    ]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )

    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

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

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of coordinates
        if self.coordinates:
            _dict["coordinates"] = self.coordinates.to_dict()
        # override the default output from pydantic by calling `to_dict()` of source_coordinates
        if self.source_coordinates:
            _dict["sourceCoordinates"] = self.source_coordinates.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in var_and (list)
        _items = []
        if self.var_and:
            for _item_var_and in self.var_and:
                if _item_var_and:
                    _items.append(_item_var_and.to_dict())
            _dict["AND"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in var_or (list)
        _items = []
        if self.var_or:
            for _item_var_or in self.var_or:
                if _item_var_or:
                    _items.append(_item_var_or.to_dict())
            _dict["OR"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in var_not (list)
        _items = []
        if self.var_not:
            for _item_var_not in self.var_not:
                if _item_var_not:
                    _items.append(_item_var_not.to_dict())
            _dict["NOT"] = _items
        return _dict

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

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

        _obj = cls.model_validate(
            {
                "articleId": obj.get("articleId"),
                "clusterId": obj.get("clusterId"),
                "source": obj.get("source"),
                "excludeSource": obj.get("excludeSource"),
                "sourceGroup": obj.get("sourceGroup"),
                "language": obj.get("language"),
                "excludeLanguage": obj.get("excludeLanguage"),
                "label": obj.get("label"),
                "excludeLabel": obj.get("excludeLabel"),
                "taxonomy": obj.get("taxonomy"),
                "category": obj.get("category"),
                "topic": obj.get("topic"),
                "excludeTopic": obj.get("excludeTopic"),
                "country": obj.get("country"),
                "excludeCountry": obj.get("excludeCountry"),
                "locationsCountry": obj.get("locationsCountry"),
                "excludeLocationsCountry": obj.get("excludeLocationsCountry"),
                "state": obj.get("state"),
                "excludeState": obj.get("excludeState"),
                "county": obj.get("county"),
                "excludeCounty": obj.get("excludeCounty"),
                "city": obj.get("city"),
                "excludeCity": obj.get("excludeCity"),
                "sourceCountry": obj.get("sourceCountry"),
                "sourceState": obj.get("sourceState"),
                "sourceCounty": obj.get("sourceCounty"),
                "sourceCity": obj.get("sourceCity"),
                "coordinates": CoordinateFilter.from_dict(obj["coordinates"])
                if obj.get("coordinates") is not None
                else None,
                "sourceCoordinates": CoordinateFilter.from_dict(
                    obj["sourceCoordinates"]
                )
                if obj.get("sourceCoordinates") is not None
                else None,
                "companyId": obj.get("companyId"),
                "excludeCompanyId": obj.get("excludeCompanyId"),
                "companyDomain": obj.get("companyDomain"),
                "excludeCompanyDomain": obj.get("excludeCompanyDomain"),
                "companySymbol": obj.get("companySymbol"),
                "excludeCompanySymbol": obj.get("excludeCompanySymbol"),
                "companyName": obj.get("companyName"),
                "personWikidataId": obj.get("personWikidataId"),
                "excludePersonWikidataId": obj.get("excludePersonWikidataId"),
                "personName": obj.get("personName"),
                "excludePersonName": obj.get("excludePersonName"),
                "AND": [ArticleSearchFilter.from_dict(_item) for _item in obj["AND"]]
                if obj.get("AND") is not None
                else None,
                "OR": [ArticleSearchFilter.from_dict(_item) for _item in obj["OR"]]
                if obj.get("OR") is not None
                else None,
                "NOT": [ArticleSearchFilter.from_dict(_item) for _item in obj["NOT"]]
                if obj.get("NOT") is not None
                else None,
            }
        )
        return _obj


# TODO: Rewrite to not use raise_errors
ArticleSearchFilter.model_rebuild(raise_errors=False)
