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

from __future__ import annotations

from enum import Enum
from typing import Annotated, Any, Literal

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

from ..core import account_ref, brand_ref
from ..core import catalog as catalog_1
from ..core import context as context_1
from ..core import ext as ext_1
from ..core import pagination_request, product_filters, property_list_ref


class BuyingMode(Enum):
    brief = 'brief'
    wholesale = 'wholesale'
    refine = 'refine'


class FieldModel(Enum):
    product_id = 'product_id'
    name = 'name'
    description = 'description'
    publisher_properties = 'publisher_properties'
    channels = 'channels'
    format_ids = 'format_ids'
    placements = 'placements'
    delivery_type = 'delivery_type'
    pricing_options = 'pricing_options'
    forecast = 'forecast'
    outcome_measurement = 'outcome_measurement'
    delivery_measurement = 'delivery_measurement'
    reporting_capabilities = 'reporting_capabilities'
    creative_policy = 'creative_policy'
    catalog_types = 'catalog_types'
    metric_optimization = 'metric_optimization'
    conversion_tracking = 'conversion_tracking'
    data_provider_signals = 'data_provider_signals'
    max_optimization_goals = 'max_optimization_goals'
    catalog_match = 'catalog_match'
    brief_relevance = 'brief_relevance'
    expires_at = 'expires_at'
    product_card = 'product_card'
    product_card_detailed = 'product_card_detailed'


class Refine(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    ask: Annotated[
        str,
        Field(
            description="What the buyer is asking for at the request level (e.g., 'more video options and less display', 'suggest how to combine these products').",
            min_length=1,
        ),
    ]
    scope: Annotated[
        Literal['request'],
        Field(
            description='Change scoped to the overall request — direction for the selection as a whole.'
        ),
    ]


class Action(Enum):
    include = 'include'
    omit = 'omit'
    more_like_this = 'more_like_this'


class Refine1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    action: Annotated[
        Action,
        Field(
            description="'include': return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned)."
        ),
    ]
    ask: Annotated[
        str | None,
        Field(
            description="What the buyer is asking for on this product. For 'include': specific changes to request (e.g., 'add 16:9 format'). For 'more_like_this': what 'similar' means (e.g., 'same audience but video format'). Ignored when action is 'omit'.",
            min_length=1,
        ),
    ] = None
    id: Annotated[
        str, Field(description='Product ID from a previous get_products response.', min_length=1)
    ]
    scope: Annotated[Literal['product'], Field(description='Change scoped to a specific product.')]


class Action2(Enum):
    include = 'include'
    omit = 'omit'


class Refine2(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    action: Annotated[
        Action2,
        Field(
            description="'include': return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response."
        ),
    ]
    ask: Annotated[
        str | None,
        Field(
            description="What the buyer is asking for on this proposal (e.g., 'shift more budget toward video', 'reduce total by 10%'). Ignored when action is 'omit'.",
            min_length=1,
        ),
    ] = None
    id: Annotated[
        str, Field(description='Proposal ID from a previous get_products response.', min_length=1)
    ]
    scope: Annotated[
        Literal['proposal'], Field(description='Change scoped to a specific proposal.')
    ]


class GetProductsRequest1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description="Account for product lookup. Returns products with pricing specific to this account's rate card."
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference for product discovery context. Resolved to full brand identity at execution time.'
        ),
    ] = None
    brief: Annotated[
        str,
        Field(
            description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'."
        ),
    ]
    buyer_campaign_ref: Annotated[
        str | None,
        Field(
            description="Buyer's campaign reference label. Groups related discovery and buy operations under a single campaign for CRM and ad server correlation (e.g., 'NovaDrink_Meals_Q2')."
        ),
    ] = None
    buying_mode: Annotated[
        Literal['brief'],
        Field(
            description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests."
        ),
    ]
    catalog: Annotated[
        catalog_1.Catalog | None,
        Field(
            description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None
    fields: Annotated[
        list[FieldModel] | None,
        Field(
            description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.',
            min_length=1,
        ),
    ] = None
    filters: product_filters.ProductFilters | None = None
    pagination: pagination_request.PaginationRequest | None = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.'
        ),
    ] = None
    refine: Any | None = None


class GetProductsRequest2(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description="Account for product lookup. Returns products with pricing specific to this account's rate card."
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference for product discovery context. Resolved to full brand identity at execution time.'
        ),
    ] = None
    brief: Any | None = None
    buyer_campaign_ref: Annotated[
        str | None,
        Field(
            description="Buyer's campaign reference label. Groups related discovery and buy operations under a single campaign for CRM and ad server correlation (e.g., 'NovaDrink_Meals_Q2')."
        ),
    ] = None
    buying_mode: Annotated[
        Literal['wholesale'],
        Field(
            description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests."
        ),
    ]
    catalog: Annotated[
        catalog_1.Catalog | None,
        Field(
            description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None
    fields: Annotated[
        list[FieldModel] | None,
        Field(
            description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.',
            min_length=1,
        ),
    ] = None
    filters: product_filters.ProductFilters | None = None
    pagination: pagination_request.PaginationRequest | None = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.'
        ),
    ] = None
    refine: Any | None = None


class GetProductsRequest3(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description="Account for product lookup. Returns products with pricing specific to this account's rate card."
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference for product discovery context. Resolved to full brand identity at execution time.'
        ),
    ] = None
    brief: Any | None = None
    buyer_campaign_ref: Annotated[
        str | None,
        Field(
            description="Buyer's campaign reference label. Groups related discovery and buy operations under a single campaign for CRM and ad server correlation (e.g., 'NovaDrink_Meals_Q2')."
        ),
    ] = None
    buying_mode: Annotated[
        Literal['refine'],
        Field(
            description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests."
        ),
    ]
    catalog: Annotated[
        catalog_1.Catalog | None,
        Field(
            description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None
    fields: Annotated[
        list[FieldModel] | None,
        Field(
            description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.',
            min_length=1,
        ),
    ] = None
    filters: product_filters.ProductFilters | None = None
    pagination: pagination_request.PaginationRequest | None = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.'
        ),
    ] = None
    refine: Annotated[
        list[Refine | Refine1 | Refine2],
        Field(
            description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.",
            min_length=1,
        ),
    ]


class GetProductsRequest(
    RootModel[GetProductsRequest1 | GetProductsRequest2 | GetProductsRequest3]
):
    root: Annotated[
        GetProductsRequest1 | GetProductsRequest2 | GetProductsRequest3,
        Field(
            description="Request parameters for discovering or refining advertising products. buying_mode declares the buyer's intent: 'brief' for curated discovery, 'wholesale' for raw catalog access, or 'refine' to iterate on known products and proposals.",
            title='Get Products Request',
        ),
    ]
