# generated by datamodel-codegen:
#   filename:  core/product.json
#   timestamp: 2026-02-28T17:39:50+00:00

from __future__ import annotations

from enum import Enum
from typing import Annotated, Any

from adcp.types.base import AdCPBaseModel
from pydantic import AwareDatetime, ConfigDict, Field, RootModel

from ..enums import action_source, catalog_type
from ..enums import channels as channels_1
from ..enums import delivery_type as delivery_type_1
from ..enums import reach_unit
from . import creative_policy as creative_policy_1
from . import data_provider_signal_selector, delivery_forecast
from . import ext as ext_1
from . import format_id as format_id_1
from . import outcome_measurement as outcome_measurement_1
from . import placement, pricing_option, publisher_property_selector
from . import reporting_capabilities as reporting_capabilities_1


class MatchedGtin(RootModel[str]):
    root: Annotated[str, Field(pattern='^[0-9]{8,14}$')]


class CatalogMatch(AdCPBaseModel):
    matched_count: Annotated[
        int | None,
        Field(description="Number of catalog items that matched this product's inventory.", ge=0),
    ] = None
    matched_gtins: Annotated[
        list[MatchedGtin] | None,
        Field(
            description="GTINs from the buyer's catalog that are eligible on this product's inventory. Standard GTIN formats (GTIN-8 through GTIN-14). Only present for product-type catalogs with GTIN matching."
        ),
    ] = None
    matched_ids: Annotated[
        list[str] | None,
        Field(
            description="Item IDs from the buyer's catalog that matched this product's inventory. The ID type depends on the catalog type and content_id_type (e.g., SKUs for product catalogs, job_ids for job catalogs, offering_ids for offering catalogs)."
        ),
    ] = None
    submitted_count: Annotated[
        int, Field(description="Total catalog items evaluated from the buyer's catalog.", ge=0)
    ]


class SupportedTarget(Enum):
    cost_per = 'cost_per'
    per_ad_spend = 'per_ad_spend'
    maximize_value = 'maximize_value'


class ConversionTracking(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    action_sources: Annotated[
        list[action_source.ActionSource] | None,
        Field(
            description="Action sources relevant to this product (e.g. a retail media product might have 'in_store' and 'website', while a display product might only have 'website')",
            min_length=1,
        ),
    ] = None
    platform_managed: Annotated[
        bool | None,
        Field(
            description="Whether the seller provides its own always-on measurement (e.g. Amazon sales attribution for Amazon advertisers). When true, sync_event_sources response will include seller-managed event sources with managed_by='seller'."
        ),
    ] = None
    supported_targets: Annotated[
        list[SupportedTarget] | None,
        Field(
            description='Target kinds available for event goals on this product. Values match target.kind on the optimization goal. cost_per: target cost per conversion event. per_ad_spend: target return on ad spend (requires value_field on event sources). maximize_value: maximize total conversion value without a specific ratio target (requires value_field). Only these target kinds are accepted — goals with unlisted target kinds will be rejected. A goal without a target implicitly maximizes conversion count within budget — no declaration needed for that mode. When omitted, buyers can still set target-less event goals.',
            min_length=1,
        ),
    ] = None


class DeliveryMeasurement(AdCPBaseModel):
    notes: Annotated[
        str | None,
        Field(
            description="Additional details about measurement methodology in plain language (e.g., 'MRC-accredited viewability. 50% in-view for 1s display / 2s video', 'Panel-based demographic measurement updated monthly')"
        ),
    ] = None
    provider: Annotated[
        str,
        Field(
            description="Measurement provider(s) used for this product (e.g., 'Google Ad Manager with IAS viewability', 'Nielsen DAR', 'Geopath for DOOH impressions')"
        ),
    ]


class SupportedMetric(Enum):
    clicks = 'clicks'
    views = 'views'
    completed_views = 'completed_views'
    viewed_seconds = 'viewed_seconds'
    attention_seconds = 'attention_seconds'
    attention_score = 'attention_score'
    engagements = 'engagements'
    follows = 'follows'
    saves = 'saves'
    profile_visits = 'profile_visits'
    reach = 'reach'


class SupportedTarget1(Enum):
    cost_per = 'cost_per'
    threshold_rate = 'threshold_rate'


class SupportedViewDuration(RootModel[float]):
    root: Annotated[float, Field(gt=0.0)]


class ProductCard(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    format_id: Annotated[
        format_id_1.FormatId,
        Field(
            description='Creative format defining the card layout (typically product_card_standard)'
        ),
    ]
    manifest: Annotated[
        dict[str, Any],
        Field(description='Asset manifest for rendering the card, structure defined by the format'),
    ]


class ProductCardDetailed(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    format_id: Annotated[
        format_id_1.FormatId,
        Field(
            description='Creative format defining the detailed card layout (typically product_card_detailed)'
        ),
    ]
    manifest: Annotated[
        dict[str, Any],
        Field(
            description='Asset manifest for rendering the detailed card, structure defined by the format'
        ),
    ]


class MetricOptimization(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    supported_metrics: Annotated[
        list[SupportedMetric],
        Field(
            description='Metric kinds this product can optimize for. Buyers should only request metric goals for kinds listed here.',
            min_length=1,
        ),
    ]
    supported_reach_units: Annotated[
        list[reach_unit.ReachUnit] | None,
        Field(
            description="Reach units this product can optimize for. Required when supported_metrics includes 'reach'. Buyers must set reach_unit to a value in this list on reach optimization goals — sellers reject unsupported values.",
            min_length=1,
        ),
    ] = None
    supported_targets: Annotated[
        list[SupportedTarget1] | None,
        Field(
            description='Target kinds available for metric goals on this product. Values match target.kind on the optimization goal. Only these target kinds are accepted — goals with unlisted target kinds will be rejected. When omitted, buyers can set target-less metric goals (maximize volume within budget) but cannot set specific targets.'
        ),
    ] = None
    supported_view_durations: Annotated[
        list[SupportedViewDuration] | None,
        Field(
            description="Video view duration thresholds (in seconds) this product supports for completed_views goals. Only relevant when supported_metrics includes 'completed_views'. When absent, the seller uses their platform default. Buyers must set view_duration_seconds to a value in this list — sellers reject unsupported values."
        ),
    ] = None


class Product(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    brief_relevance: Annotated[
        str | None,
        Field(
            description='Explanation of why this product matches the brief (only included when brief is provided)'
        ),
    ] = None
    catalog_match: Annotated[
        CatalogMatch | None,
        Field(
            description='When the buyer provides a catalog on get_products, indicates which catalog items are eligible for this product. Only present for products where catalog matching is relevant (e.g., sponsored product listings, job boards, hotel ads).'
        ),
    ] = None
    catalog_types: Annotated[
        list[catalog_type.CatalogType] | None,
        Field(
            description='Catalog types this product supports for catalog-driven campaigns. A sponsored product listing declares ["product"], a job board declares ["job", "offering"]. Buyers match synced catalogs to products via this field.',
            min_length=1,
        ),
    ] = None
    channels: Annotated[
        list[channels_1.MediaChannel] | None,
        Field(
            description="Advertising channels this product is sold as. Products inherit from their properties' supported_channels but may narrow the scope. For example, a product covering YouTube properties might be sold as ['ctv'] even though those properties support ['olv', 'social', 'ctv']."
        ),
    ] = None
    conversion_tracking: Annotated[
        ConversionTracking | None,
        Field(
            description="Conversion event tracking for this product. Presence indicates the product supports optimization_goals with kind: 'event'. Seller-level capabilities (supported event types, UID types, attribution windows) are declared in get_adcp_capabilities."
        ),
    ] = None
    creative_policy: creative_policy_1.CreativePolicy | None = None
    data_provider_signals: Annotated[
        list[data_provider_signal_selector.DataProviderSignalSelector] | None,
        Field(
            description="Data provider signals available for this product. Buyers fetch signal definitions from each data provider's adagents.json and can verify agent authorization."
        ),
    ] = None
    delivery_measurement: Annotated[
        DeliveryMeasurement,
        Field(
            description='Measurement provider and methodology for delivery metrics. The buyer accepts the declared provider as the source of truth for the buy. REQUIRED for all products.'
        ),
    ]
    delivery_type: delivery_type_1.DeliveryType
    description: Annotated[
        str, Field(description='Detailed description of the product and its inventory')
    ]
    expires_at: Annotated[
        AwareDatetime | None, Field(description='Expiration timestamp for custom products')
    ] = None
    ext: ext_1.ExtensionObject | None = None
    forecast: Annotated[
        delivery_forecast.DeliveryForecast | None,
        Field(
            description='Forecasted delivery metrics for this product. Gives buyers an estimate of expected performance before requesting a proposal.'
        ),
    ] = None
    format_ids: Annotated[
        list[format_id_1.FormatId],
        Field(
            description='Array of supported creative format IDs - structured format_id objects with agent_url and id'
        ),
    ]
    is_custom: Annotated[bool | None, Field(description='Whether this is a custom product')] = None
    max_optimization_goals: Annotated[
        int | None,
        Field(
            description='Maximum number of optimization_goals this product accepts on a package. When absent, no limit is declared. Most social platforms accept only 1 goal — buyers sending arrays longer than this value should expect the seller to use only the highest-priority (lowest priority number) goal.',
            ge=1,
        ),
    ] = None
    metric_optimization: Annotated[
        MetricOptimization | None,
        Field(
            description="Metric optimization capabilities for this product. Presence indicates the product supports optimization_goals with kind: 'metric'. No event source or conversion tracking setup required — the seller tracks these metrics natively."
        ),
    ] = None
    name: Annotated[str, Field(description='Human-readable product name')]
    outcome_measurement: outcome_measurement_1.OutcomeMeasurement | None = None
    placements: Annotated[
        list[placement.Placement] | None,
        Field(
            description='Optional array of specific placements within this product. When provided, buyers can target specific placements when assigning creatives.',
            min_length=1,
        ),
    ] = None
    pricing_options: Annotated[
        list[pricing_option.PricingOption],
        Field(description='Available pricing models for this product', min_length=1),
    ]
    product_card: Annotated[
        ProductCard | None,
        Field(
            description='Optional standard visual card (300x400px) for displaying this product in user interfaces. Can be rendered via preview_creative or pre-generated.'
        ),
    ] = None
    product_card_detailed: Annotated[
        ProductCardDetailed | None,
        Field(
            description='Optional detailed card with carousel and full specifications. Provides rich product presentation similar to media kit pages.'
        ),
    ] = None
    product_id: Annotated[str, Field(description='Unique identifier for the product')]
    property_targeting_allowed: Annotated[
        bool | None,
        Field(
            description="Whether buyers can filter this product to a subset of its publisher_properties. When false (default), the product is 'all or nothing' - buyers must accept all properties or the product is excluded from property_list filtering results."
        ),
    ] = False
    publisher_properties: Annotated[
        list[publisher_property_selector.PublisherPropertySelector],
        Field(
            description="Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization. Selection patterns mirror the authorization patterns in adagents.json for consistency.",
            min_length=1,
        ),
    ]
    reporting_capabilities: reporting_capabilities_1.ReportingCapabilities | None = None
    signal_targeting_allowed: Annotated[
        bool | None,
        Field(
            description='Whether buyers can filter this product to a subset of its data_provider_signals. When false (default), the product includes all listed signals as a bundle. When true, buyers can target specific signals.'
        ),
    ] = False
