# generated by datamodel-codegen:
#   filename:  product.json
#   timestamp: 2025-11-15T22:03:55+00:00

from __future__ import annotations

from typing import Annotated, Any, Literal

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

from . import cpc_option, cpcv_option, cpm_auction_option, cpm_fixed_option, cpp_option, cpv_option
from . import creative_policy as creative_policy_1
from . import delivery_type as delivery_type_1
from . import flat_rate_option
from . import format_id as format_id_1
from . import measurement as measurement_1
from . import placement
from . import reporting_capabilities as reporting_capabilities_1
from . import vcpm_auction_option, vcpm_fixed_option


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 ProductCard(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    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="forbid",
    )
    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 PropertyId(RootModel[str]):
    root: Annotated[str, Field(pattern="^[a-z0-9_]+$")]


class PublisherProperties(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    property_ids: Annotated[
        list[PropertyId],
        Field(description="Specific property IDs from the publisher's adagents.json", min_length=1),
    ]
    publisher_domain: Annotated[
        str,
        Field(
            description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')",
            pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$",
        ),
    ]
    selection_type: Annotated[
        Literal["by_id"],
        Field(description="Discriminator indicating selection by specific property IDs"),
    ]


class PropertyTag(PropertyId):
    pass


class PublisherProperties3(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    property_tags: Annotated[
        list[PropertyTag],
        Field(
            description="Property tags from the publisher's adagents.json. Product covers all properties with these tags",
            min_length=1,
        ),
    ]
    publisher_domain: Annotated[
        str,
        Field(
            description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')",
            pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$",
        ),
    ]
    selection_type: Annotated[
        Literal["by_tag"], Field(description="Discriminator indicating selection by property tags")
    ]


class Product(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    brief_relevance: Annotated[
        str | None,
        Field(
            description="Explanation of why this product matches the brief (only included when brief is provided)"
        ),
    ] = None
    creative_policy: creative_policy_1.CreativePolicy | None = 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")
    ]
    estimated_exposures: Annotated[
        int | None,
        Field(description="Estimated exposures/impressions for guaranteed products", ge=0),
    ] = None
    expires_at: Annotated[
        AwareDatetime | None, Field(description="Expiration timestamp for custom products")
    ] = 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
    measurement: measurement_1.Measurement | None = None
    name: Annotated[str, Field(description="Human-readable product name")]
    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[
            cpm_fixed_option.CpmFixedRatePricingOption
            | cpm_auction_option.CpmAuctionPricingOption
            | vcpm_fixed_option.VcpmFixedRatePricingOption
            | vcpm_auction_option.VcpmAuctionPricingOption
            | cpc_option.CpcPricingOption
            | cpcv_option.CpcvPricingOption
            | cpv_option.CpvPricingOption
            | cpp_option.CppPricingOption
            | flat_rate_option.FlatRatePricingOption
        ],
        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")]
    publisher_properties: Annotated[
        list[PublisherProperties | PublisherProperties3],
        Field(
            description="Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization.",
            min_length=1,
        ),
    ]
    reporting_capabilities: reporting_capabilities_1.ReportingCapabilities | None = None

    @model_validator(mode="after")
    def validate_publisher_properties_items(self) -> "Product":
        """Validate all publisher_properties items."""
        from adcp.validation import validate_product

        data = self.model_dump()
        validate_product(data)
        return self
