# coding: utf-8

"""
    Pinterest REST API

    Pinterest's REST API

    The version of the OpenAPI document: 5.23.0
    Contact: blah+oapicf@cliffano.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

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


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from pinterestsdk.models.ad_group_summary_status import AdGroupSummaryStatus
from pinterestsdk.models.ads_analytics_create_async_request_all_of_custom_conversion_event_metrics import AdsAnalyticsCreateAsyncRequestAllOfCustomConversionEventMetrics
from pinterestsdk.models.ads_analytics_metrics_filter import AdsAnalyticsMetricsFilter
from pinterestsdk.models.campaign_summary_status import CampaignSummaryStatus
from pinterestsdk.models.conversion_attribution_window_days import ConversionAttributionWindowDays
from pinterestsdk.models.conversion_report_attribution_type import ConversionReportAttributionType
from pinterestsdk.models.conversion_report_time_type import ConversionReportTimeType
from pinterestsdk.models.data_output_format import DataOutputFormat
from pinterestsdk.models.granularity import Granularity
from pinterestsdk.models.metrics_reporting_level import MetricsReportingLevel
from pinterestsdk.models.objective_type import ObjectiveType
from pinterestsdk.models.pin_promotion_summary_status import PinPromotionSummaryStatus
from pinterestsdk.models.product_group_summary_status import ProductGroupSummaryStatus
from pinterestsdk.models.reporting_column_async import ReportingColumnAsync
from pinterestsdk.models.reporting_time_zone import ReportingTimeZone
from typing import Optional, Set
from typing_extensions import Self

class AdsAnalyticsCreateAsyncRequest(BaseModel):
    """
    AdsAnalyticsCreateAsyncRequest
    """ # noqa: E501
    attribution_types: Optional[List[ConversionReportAttributionType]] = Field(default=None, description="List of types of attribution for the conversion report")
    click_window_days: Optional[ConversionAttributionWindowDays] = Field(default=ConversionAttributionWindowDays.NUMBER_30, description="Number of days to use as the conversion attribution window for a pin click action. Applies to Pinterest Tag conversion metrics. Prior conversion tags use their defined attribution windows. If not specified, defaults to `30` days.")
    conversion_report_time: Optional[ConversionReportTimeType] = Field(default='TIME_OF_AD_ACTION', description="The date by which the conversion metrics returned from this endpoint will be reported. There are two dates associated with a conversion event: the date that the user interacted with the ad, and the date that the user completed a conversion event.")
    end_date: Annotated[str, Field(strict=True)] = Field(description="Metric report end date (UTC). Format: YYYY-MM-DD")
    engagement_window_days: Optional[ConversionAttributionWindowDays] = Field(default=ConversionAttributionWindowDays.NUMBER_30, description="Number of days to use as the conversion attribution window for an engagement action. Engagements include saves, closeups, link clicks, and carousel card swipes. Applies to Pinterest Tag conversion metrics. Prior conversion tags use their defined attribution windows. If not specified, defaults to `30` days.")
    granularity: Granularity = Field(description="TOTAL - metrics are aggregated over the specified date range.<br> DAY - metrics are broken down daily.<br> HOUR - metrics are broken down hourly.<br>WEEKLY - metrics are broken down weekly.<br>MONTHLY - metrics are broken down monthly")
    start_date: Annotated[str, Field(strict=True)] = Field(description="Metric report start date (UTC). Format: YYYY-MM-DD")
    view_window_days: Optional[ConversionAttributionWindowDays] = Field(default=ConversionAttributionWindowDays.NUMBER_1, description="Number of days to use as the conversion attribution window for a view action. Applies to Pinterest Tag conversion metrics. Prior conversion tags use their defined attribution windows. If not specified, defaults to `1` day.")
    campaign_ids: Optional[Annotated[List[Annotated[str, Field(strict=True)]], Field(min_length=1, max_length=500)]] = Field(default=None, description="List of campaign ids")
    campaign_statuses: Optional[Annotated[List[CampaignSummaryStatus], Field(min_length=1, max_length=6)]] = Field(default=None, description="List of status values for filtering")
    campaign_objective_types: Optional[Annotated[List[ObjectiveType], Field(min_length=1, max_length=7)]] = Field(default=None, description="List of values for filtering. [\"WEB_SESSIONS\"] in BETA.")
    campaign_brand_label: Optional[StrictStr] = Field(default=None, description="Campaign brand label for filtering.")
    ad_group_ids: Optional[Annotated[List[Annotated[str, Field(strict=True)]], Field(min_length=1, max_length=500)]] = Field(default=None, description="List of ad group ids")
    ad_group_statuses: Optional[Annotated[List[AdGroupSummaryStatus], Field(min_length=1, max_length=6)]] = Field(default=None, description="List of values for filtering")
    ad_ids: Optional[Annotated[List[Annotated[str, Field(strict=True)]], Field(min_length=1, max_length=500)]] = Field(default=None, description="List of ad ids [This parameter is no supported for Product Item Level Reports]")
    ad_statuses: Optional[Annotated[List[PinPromotionSummaryStatus], Field(min_length=1, max_length=6)]] = Field(default=None, description="List of values for filtering [This parameter is not supported for Product Item Level Reports]")
    product_group_ids: Optional[Annotated[List[Annotated[str, Field(strict=True)]], Field(min_length=1, max_length=500)]] = Field(default=None, description="List of product group ids")
    product_group_statuses: Optional[Annotated[List[ProductGroupSummaryStatus], Field(min_length=1, max_length=6)]] = Field(default=None, description="List of values for filtering")
    product_item_ids: Optional[Annotated[List[Annotated[str, Field(strict=True)]], Field(min_length=1, max_length=500)]] = Field(default=None, description="List of product item ids")
    targeting_types: Optional[Annotated[List[StrictStr], Field(min_length=1, max_length=5)]] = Field(default=None, description="List of targeting types. Requires `level` to be a value ending in `_TARGETING`. [\"AUDIENCE_MULTIPLIER\"] is only available in CAMPAIGN_TARGETING level. [\"MEDIA_TYPE\"] is only available in PRODUCT_ITEM_TARGETING level. [\"AGE_BUCKET_AND_GENDER\"] is in BETA and not yet available to all users.")
    metrics_filters: Optional[Annotated[List[AdsAnalyticsMetricsFilter], Field(min_length=1)]] = Field(default=None, description="List of metrics filters")
    columns: List[ReportingColumnAsync] = Field(description="Metric and entity columns. Pin promotion and ad related columns are not supported for the Product Item level reports.")
    combine_targeting_types: Optional[StrictBool] = Field(default=False, description="Determines if the targeting types included in the request should be consolidated into a single breakdown. For example, when combine_targeting_types is set to true, if GENDER and COUNTRY are targeting types in the request, the response will have a targeting type of GENDER_AND_COUNTRY and targeting values such as female&US. This feature is currently in BETA and is not available to all users.")
    custom_conversion_event_metrics: Optional[List[AdsAnalyticsCreateAsyncRequestAllOfCustomConversionEventMetrics]] = Field(default=None, description="List of advertiser-defined custom conversion event metrics to include in the report")
    end_hour: Optional[Annotated[int, Field(le=23, strict=True, ge=0)]] = Field(default=None, description="Which hour of the end date to stop the report (inclusive). For example, with an end_date of '2020-01-01' and end_hour of '15', the report will contain metrics up to '2020-01-01 14:59:59'. The entire day will be included if no end hour is provided. Only allowed for hourly reports.")
    level: MetricsReportingLevel = Field(description="Level of the report")
    primary_sort: Optional[StrictStr] = Field(default=None, description="Whether to first sort the report by date or by entity ID of the reporting entity level. Date will be used as the first level key for JSON reports that use BY_DATE. BY_DATE is recommended for large requests.")
    report_format: Optional[DataOutputFormat] = Field(default='JSON', description="Specification for formatting the report data. Reports in JSON will not zero-fill metrics, whereas reports in CSV will. Both report formats will omit rows where all the columns are equal to 0.")
    reporting_timezone: Optional[ReportingTimeZone] = Field(default=None, description="Specify the timezone to be applied for the reporting. This feature is currently in BETA and is not available to all users.")
    start_hour: Optional[Annotated[int, Field(le=23, strict=True, ge=0)]] = Field(default=None, description="Which hour of the start date to begin the report. The entire day will be included if no start hour is provided. Only allowed for hourly reports.")
    __properties: ClassVar[List[str]] = ["attribution_types", "click_window_days", "conversion_report_time", "end_date", "engagement_window_days", "granularity", "start_date", "view_window_days", "campaign_ids", "campaign_statuses", "campaign_objective_types", "campaign_brand_label", "ad_group_ids", "ad_group_statuses", "ad_ids", "ad_statuses", "product_group_ids", "product_group_statuses", "product_item_ids", "targeting_types", "metrics_filters", "columns", "combine_targeting_types", "custom_conversion_event_metrics", "end_hour", "level", "primary_sort", "report_format", "reporting_timezone", "start_hour"]

    @field_validator('end_date')
    def end_date_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if not re.match(r"^(\d{4})-(\d{2})-(\d{2})$", value):
            raise ValueError(r"must validate the regular expression /^(\d{4})-(\d{2})-(\d{2})$/")
        return value

    @field_validator('start_date')
    def start_date_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if not re.match(r"^(\d{4})-(\d{2})-(\d{2})$", value):
            raise ValueError(r"must validate the regular expression /^(\d{4})-(\d{2})-(\d{2})$/")
        return value

    @field_validator('targeting_types')
    def targeting_types_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        for i in value:
            if i not in set(['KEYWORD', 'APPTYPE', 'GENDER', 'LOCATION', 'PLACEMENT', 'COUNTRY', 'TARGETED_INTEREST', 'PINNER_INTEREST', 'AUDIENCE_INCLUDE', 'GEO', 'AGE_BUCKET', 'REGION', 'MEDIA_TYPE', 'AGE_BUCKET_AND_GENDER', 'AUDIENCE_MULTIPLIER', 'CREATIVE_ENHANCEMENTS', 'LOCAL_ADS_STORE_CODE']):
                raise ValueError("each list item must be one of ('KEYWORD', 'APPTYPE', 'GENDER', 'LOCATION', 'PLACEMENT', 'COUNTRY', 'TARGETED_INTEREST', 'PINNER_INTEREST', 'AUDIENCE_INCLUDE', 'GEO', 'AGE_BUCKET', 'REGION', 'MEDIA_TYPE', 'AGE_BUCKET_AND_GENDER', 'AUDIENCE_MULTIPLIER', 'CREATIVE_ENHANCEMENTS', 'LOCAL_ADS_STORE_CODE')")
        return value

    @field_validator('primary_sort')
    def primary_sort_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['BY_ID', 'BY_DATE']):
            raise ValueError("must be one of enum values ('BY_ID', 'BY_DATE')")
        return value

    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 AdsAnalyticsCreateAsyncRequest 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 each item in metrics_filters (list)
        _items = []
        if self.metrics_filters:
            for _item_metrics_filters in self.metrics_filters:
                if _item_metrics_filters:
                    _items.append(_item_metrics_filters.to_dict())
            _dict['metrics_filters'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in custom_conversion_event_metrics (list)
        _items = []
        if self.custom_conversion_event_metrics:
            for _item_custom_conversion_event_metrics in self.custom_conversion_event_metrics:
                if _item_custom_conversion_event_metrics:
                    _items.append(_item_custom_conversion_event_metrics.to_dict())
            _dict['custom_conversion_event_metrics'] = _items
        return _dict

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

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

        _obj = cls.model_validate({
            "attribution_types": obj.get("attribution_types"),
            "click_window_days": obj.get("click_window_days") if obj.get("click_window_days") is not None else ConversionAttributionWindowDays.NUMBER_30,
            "conversion_report_time": obj.get("conversion_report_time") if obj.get("conversion_report_time") is not None else 'TIME_OF_AD_ACTION',
            "end_date": obj.get("end_date"),
            "engagement_window_days": obj.get("engagement_window_days") if obj.get("engagement_window_days") is not None else ConversionAttributionWindowDays.NUMBER_30,
            "granularity": obj.get("granularity"),
            "start_date": obj.get("start_date"),
            "view_window_days": obj.get("view_window_days") if obj.get("view_window_days") is not None else ConversionAttributionWindowDays.NUMBER_1,
            "campaign_ids": obj.get("campaign_ids"),
            "campaign_statuses": obj.get("campaign_statuses"),
            "campaign_objective_types": obj.get("campaign_objective_types"),
            "campaign_brand_label": obj.get("campaign_brand_label"),
            "ad_group_ids": obj.get("ad_group_ids"),
            "ad_group_statuses": obj.get("ad_group_statuses"),
            "ad_ids": obj.get("ad_ids"),
            "ad_statuses": obj.get("ad_statuses"),
            "product_group_ids": obj.get("product_group_ids"),
            "product_group_statuses": obj.get("product_group_statuses"),
            "product_item_ids": obj.get("product_item_ids"),
            "targeting_types": obj.get("targeting_types"),
            "metrics_filters": [AdsAnalyticsMetricsFilter.from_dict(_item) for _item in obj["metrics_filters"]] if obj.get("metrics_filters") is not None else None,
            "columns": obj.get("columns"),
            "combine_targeting_types": obj.get("combine_targeting_types") if obj.get("combine_targeting_types") is not None else False,
            "custom_conversion_event_metrics": [AdsAnalyticsCreateAsyncRequestAllOfCustomConversionEventMetrics.from_dict(_item) for _item in obj["custom_conversion_event_metrics"]] if obj.get("custom_conversion_event_metrics") is not None else None,
            "end_hour": obj.get("end_hour"),
            "level": obj.get("level"),
            "primary_sort": obj.get("primary_sort"),
            "report_format": obj.get("report_format") if obj.get("report_format") is not None else 'JSON',
            "reporting_timezone": obj.get("reporting_timezone"),
            "start_hour": obj.get("start_hour")
        })
        return _obj


