# generated by datamodel-codegen:
#   filename:  pricing-option.json
#   timestamp: 2025-11-15T17:41:03+00:00

from __future__ import annotations

from typing import Literal

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


class CpmFixedOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_guaranteed')",
    )
    pricing_model: Literal["cpm"] = Field(..., description="Cost per 1,000 impressions")
    rate: float = Field(..., description="Fixed CPM rate (cost per 1,000 impressions)", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class PriceGuidance(AdCPBaseModel):
    floor: float = Field(
        ..., description="Minimum bid price - publisher will reject bids under this value", ge=0.0
    )
    p25: float | None = Field(None, description="25th percentile winning price", ge=0.0)
    p50: float | None = Field(None, description="Median winning price", ge=0.0)
    p75: float | None = Field(None, description="75th percentile winning price", ge=0.0)
    p90: float | None = Field(None, description="90th percentile winning price", ge=0.0)


class CpmAuctionOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_auction')",
    )
    pricing_model: Literal["cpm"] = Field(..., description="Cost per 1,000 impressions")
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    price_guidance: PriceGuidance = Field(
        ..., description="Pricing guidance for auction-based CPM bidding"
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class VcpmFixedOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_guaranteed')",
    )
    pricing_model: Literal["vcpm"] = Field(
        ..., description="Cost per 1,000 viewable impressions (MRC standard)"
    )
    rate: float = Field(
        ..., description="Fixed vCPM rate (cost per 1,000 viewable impressions)", ge=0.0
    )
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class PriceGuidance1(AdCPBaseModel):
    floor: float = Field(..., description="Minimum acceptable bid price", ge=0.0)
    p25: float | None = Field(None, description="25th percentile of recent winning bids", ge=0.0)
    p50: float | None = Field(None, description="Median of recent winning bids", ge=0.0)
    p75: float | None = Field(None, description="75th percentile of recent winning bids", ge=0.0)
    p90: float | None = Field(None, description="90th percentile of recent winning bids", ge=0.0)


class VcpmAuctionOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_auction')",
    )
    pricing_model: Literal["vcpm"] = Field(
        ..., description="Cost per 1,000 viewable impressions (MRC standard)"
    )
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    price_guidance: PriceGuidance1 = Field(
        ..., description="Statistical guidance for auction pricing"
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class CpcOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpc_usd_fixed')",
    )
    pricing_model: Literal["cpc"] = Field(..., description="Cost per click")
    rate: float = Field(..., description="Fixed CPC rate (cost per click)", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class CpcvOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpcv_usd_guaranteed')",
    )
    pricing_model: Literal["cpcv"] = Field(
        ..., description="Cost per completed view (100% completion)"
    )
    rate: float = Field(..., description="Fixed CPCV rate (cost per 100% completion)", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class ViewThreshold(RootModel[float]):
    root: float = Field(
        ...,
        description="Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)",
        ge=0.0,
        le=1.0,
    )


class ViewThreshold1(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    duration_seconds: int = Field(
        ...,
        description="Seconds of viewing required (e.g., 30 for YouTube-style '30 seconds = view')",
        ge=1,
    )


class Parameters(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    view_threshold: ViewThreshold | ViewThreshold1


class CpvOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpv_usd_50pct')",
    )
    pricing_model: Literal["cpv"] = Field(..., description="Cost per view at threshold")
    rate: float = Field(..., description="Fixed CPV rate (cost per view)", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    parameters: Parameters = Field(
        ..., description="CPV-specific parameters defining the view threshold"
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class Parameters1(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    demographic: str = Field(
        ...,
        description="Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)",
        pattern="^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$",
    )
    min_points: float | None = Field(
        None, description="Minimum GRPs/TRPs required for this pricing option", ge=0.0
    )


class CppOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'cpp_usd_p18-49')",
    )
    pricing_model: Literal["cpp"] = Field(..., description="Cost per Gross Rating Point")
    rate: float = Field(..., description="Fixed CPP rate (cost per rating point)", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    parameters: Parameters1 = Field(
        ..., description="CPP-specific parameters for demographic targeting and GRP requirements"
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class Parameters2(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    duration_hours: float | None = Field(
        None, description="Duration in hours for time-based flat rate pricing (DOOH)", ge=0.0
    )
    sov_percentage: float | None = Field(
        None, description="Guaranteed share of voice as percentage (DOOH, 0-100)", ge=0.0, le=100.0
    )
    loop_duration_seconds: int | None = Field(
        None, description="Duration of ad loop rotation in seconds (DOOH)", ge=1
    )
    min_plays_per_hour: int | None = Field(
        None,
        description="Minimum number of times ad plays per hour (DOOH frequency guarantee)",
        ge=0,
    )
    venue_package: str | None = Field(
        None,
        description="Named venue package identifier for DOOH (e.g., 'times_square_network', 'airport_terminals')",
    )
    estimated_impressions: int | None = Field(
        None,
        description="Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)",
        ge=0,
    )
    daypart: str | None = Field(
        None,
        description="Specific daypart for time-based pricing (e.g., 'morning_commute', 'evening_prime', 'overnight')",
    )


class FlatRateOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    pricing_option_id: str = Field(
        ...,
        description="Unique identifier for this pricing option within the product (e.g., 'flat_rate_usd_24h_takeover')",
    )
    pricing_model: Literal["flat_rate"] = Field(
        ..., description="Fixed cost regardless of delivery volume"
    )
    rate: float = Field(..., description="Flat rate cost", ge=0.0)
    currency: str = Field(
        ...,
        description="ISO 4217 currency code",
        examples=["USD", "EUR", "GBP", "JPY"],
        pattern="^[A-Z]{3}$",
    )
    is_fixed: Literal[True] = Field(
        ..., description="Whether this is a fixed rate (true) or auction-based (false)"
    )
    parameters: Parameters2 | None = Field(
        None, description="Flat rate parameters for DOOH and time-based campaigns"
    )
    min_spend_per_package: float | None = Field(
        None,
        description="Minimum spend requirement per package using this pricing option, in the specified currency",
        ge=0.0,
    )


class PricingOption(
    RootModel[
        CpmFixedOption
        | CpmAuctionOption
        | VcpmFixedOption
        | VcpmAuctionOption
        | CpcOption
        | CpcvOption
        | CpvOption
        | CppOption
        | FlatRateOption
    ]
):
    root: (
        CpmFixedOption
        | CpmAuctionOption
        | VcpmFixedOption
        | VcpmAuctionOption
        | CpcOption
        | CpcvOption
        | CpvOption
        | CppOption
        | FlatRateOption
    ) = Field(
        ...,
        description="A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.",
        title="Pricing Option",
    )
