# generated by datamodel-codegen:
#   filename:  media_buy/get_media_buy_delivery_response.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

from ..core import attribution_window as attribution_window_1
from ..core import context as context_1
from ..core import error
from ..core import ext as ext_1
from ..core.delivery_metrics import DeliveryMetrics
from ..enums import audience_source as audience_source_1
from ..enums import content_id_type as content_id_type_1
from ..enums import device_platform as device_platform_1
from ..enums import device_type as device_type_1
from ..enums import geo_level as geo_level_1
from ..enums import pricing_model as pricing_model_1


class AggregatedTotals(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    clicks: Annotated[
        float | None,
        Field(description='Total clicks across all media buys (if applicable)', ge=0.0),
    ] = None
    conversion_value: Annotated[
        float | None,
        Field(description='Total conversion value across all media buys (if applicable)', ge=0.0),
    ] = None
    conversions: Annotated[
        float | None,
        Field(description='Total conversions across all media buys (if applicable)', ge=0.0),
    ] = None
    cost_per_acquisition: Annotated[
        float | None,
        Field(
            description='Aggregate cost per conversion across all media buys (total spend / total conversions)',
            ge=0.0,
        ),
    ] = None
    impressions: Annotated[
        float, Field(description='Total impressions delivered across all media buys', ge=0.0)
    ]
    media_buy_count: Annotated[
        int, Field(description='Number of media buys included in the response', ge=0)
    ]
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Fraction of total conversions across all media buys from first-time brand buyers (weighted by conversion volume, not a simple average of per-buy rates)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    roas: Annotated[
        float | None,
        Field(
            description='Aggregate return on ad spend across all media buys (total conversion_value / total spend)',
            ge=0.0,
        ),
    ] = None
    spend: Annotated[float, Field(description='Total amount spent across all media buys', ge=0.0)]
    video_completions: Annotated[
        float | None,
        Field(description='Total video completions across all media buys (if applicable)', ge=0.0),
    ] = None


class MatchType(Enum):
    broad = 'broad'
    phrase = 'phrase'
    exact = 'exact'


class DailyBreakdownItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    conversion_value: Annotated[
        float | None, Field(description='Daily conversion value for this package', ge=0.0)
    ] = None
    conversions: Annotated[
        float | None, Field(description='Daily conversions for this package', ge=0.0)
    ] = None
    date: Annotated[str, Field(description='Date (YYYY-MM-DD)', pattern='^\\d{4}-\\d{2}-\\d{2}$')]
    impressions: Annotated[float, Field(description='Daily impressions for this package', ge=0.0)]
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Daily fraction of conversions from first-time brand buyers (0 = none, 1 = all)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    roas: Annotated[
        float | None,
        Field(description='Daily return on ad spend (conversion_value / spend)', ge=0.0),
    ] = None
    spend: Annotated[float, Field(description='Daily spend for this package', ge=0.0)]


class DeliveryStatus(Enum):
    delivering = 'delivering'
    completed = 'completed'
    budget_exhausted = 'budget_exhausted'
    flight_ended = 'flight_ended'
    goal_met = 'goal_met'


class DailyBreakdownItem1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    conversion_value: Annotated[
        float | None, Field(description='Daily conversion value', ge=0.0)
    ] = None
    conversions: Annotated[float | None, Field(description='Daily conversions', ge=0.0)] = None
    date: Annotated[str, Field(description='Date (YYYY-MM-DD)', pattern='^\\d{4}-\\d{2}-\\d{2}$')]
    impressions: Annotated[float, Field(description='Daily impressions', ge=0.0)]
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Daily fraction of conversions from first-time brand buyers (0 = none, 1 = all)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    roas: Annotated[
        float | None,
        Field(description='Daily return on ad spend (conversion_value / spend)', ge=0.0),
    ] = None
    spend: Annotated[float, Field(description='Daily spend', ge=0.0)]


class Status(Enum):
    pending_activation = 'pending_activation'
    pending = 'pending'
    active = 'active'
    paused = 'paused'
    completed = 'completed'
    rejected = 'rejected'
    canceled = 'canceled'
    failed = 'failed'
    reporting_delayed = 'reporting_delayed'


class NotificationType(Enum):
    scheduled = 'scheduled'
    final = 'final'
    delayed = 'delayed'
    adjusted = 'adjusted'


class ReportingPeriod(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    end: Annotated[
        AwareDatetime,
        Field(description='ISO 8601 end timestamp in UTC (e.g., 2024-02-05T23:59:59Z)'),
    ]
    start: Annotated[
        AwareDatetime,
        Field(description='ISO 8601 start timestamp in UTC (e.g., 2024-02-05T00:00:00Z)'),
    ]


class ByAudienceItem(DeliveryMetrics):
    audience_id: Annotated[
        str,
        Field(
            description="Audience segment identifier. For 'synced' source, matches audience_id from sync_audiences. For other sources, seller-defined."
        ),
    ]
    audience_name: Annotated[
        str | None, Field(description='Human-readable audience segment name')
    ] = None
    audience_source: Annotated[
        audience_source_1.AudienceSource,
        Field(
            description='Origin of the audience segment (synced, platform, third_party, lookalike, retargeting, unknown)'
        ),
    ]
    impressions: Any
    spend: Any


class ByCatalogItemItem(DeliveryMetrics):
    content_id: Annotated[
        str, Field(description='Catalog item identifier (e.g., SKU, GTIN, job_id, offering_id)')
    ]
    content_id_type: Annotated[
        content_id_type_1.ContentIdType | None,
        Field(description='Identifier type for this content_id'),
    ] = None
    impressions: Any
    spend: Any


class ByCreativeItem(DeliveryMetrics):
    creative_id: Annotated[
        str, Field(description='Creative identifier matching the creative assignment')
    ]
    weight: Annotated[
        float | None,
        Field(
            description='Observed delivery share for this creative within the package during the reporting period, expressed as a percentage (0-100). Reflects actual delivery distribution, not a configured setting.',
            ge=0.0,
            le=100.0,
        ),
    ] = None
    impressions: Any
    spend: Any


class ByDevicePlatformItem(DeliveryMetrics):
    device_platform: Annotated[
        device_platform_1.DevicePlatform, Field(description='Operating system platform')
    ]
    impressions: Any
    spend: Any


class ByDeviceTypeItem(DeliveryMetrics):
    device_type: Annotated[
        device_type_1.DeviceType,
        Field(description='Device form factor (desktop, mobile, tablet, ctv, dooh, unknown)'),
    ]
    impressions: Any
    spend: Any


class ByGeoItem(DeliveryMetrics):
    geo_code: Annotated[
        str,
        Field(
            description="Geographic code within the level and system. Country: ISO 3166-1 alpha-2 ('US'). Region: ISO 3166-2 with country prefix ('US-CA'). Metro/postal: system-specific code ('501', '10001')."
        ),
    ]
    geo_level: Annotated[
        geo_level_1.GeographicTargetingLevel,
        Field(description='Geographic level of this entry (country, region, metro, postal_area)'),
    ]
    geo_name: Annotated[
        str | None,
        Field(
            description="Human-readable geographic name (e.g., 'United States', 'California', 'New York DMA')"
        ),
    ] = None
    system: Annotated[
        str | None,
        Field(
            description="Classification system for metro or postal_area levels (e.g., 'nielsen_dma', 'us_zip'). Present when geo_level is 'metro' or 'postal_area'."
        ),
    ] = None
    impressions: Any
    spend: Any


class ByKeywordItem(DeliveryMetrics):
    keyword: Annotated[str, Field(description='The targeted keyword')]
    match_type: Annotated[MatchType, Field(description='Match type for this keyword')]
    impressions: Any
    spend: Any


class ByPlacementItem(DeliveryMetrics):
    placement_id: Annotated[
        str, Field(description="Placement identifier from the product's placements array")
    ]
    placement_name: Annotated[str | None, Field(description='Human-readable placement name')] = None
    impressions: Any
    spend: Any


class ByPackageItem(DeliveryMetrics):
    buyer_ref: Annotated[
        str | None, Field(description="Buyer's reference identifier for this package")
    ] = None
    by_audience: Annotated[
        list[ByAudienceItem] | None,
        Field(
            description="Delivery by audience segment within this package. Available when the buyer requests audience breakdown via reporting_dimensions and the seller supports it. Only 'synced' audiences are directly targetable via the targeting overlay; other sources are informational."
        ),
    ] = None
    by_audience_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_audience was truncated. Sellers MUST return this flag whenever by_audience is present (false means the list is complete).'
        ),
    ] = None
    by_catalog_item: Annotated[
        list[ByCatalogItemItem] | None,
        Field(
            description='Delivery by catalog item within this package. Available for catalog-driven packages when the seller supports item-level reporting.'
        ),
    ] = None
    by_creative: Annotated[
        list[ByCreativeItem] | None,
        Field(
            description='Metrics broken down by creative within this package. Available when the seller supports creative-level reporting.'
        ),
    ] = None
    by_device_platform: Annotated[
        list[ByDevicePlatformItem] | None,
        Field(
            description='Delivery by operating system within this package. Available when the buyer requests device_platform breakdown via reporting_dimensions and the seller supports it. Useful for CTV campaigns where tvOS vs Roku OS vs Fire OS matters.'
        ),
    ] = None
    by_device_platform_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_device_platform was truncated. Sellers MUST return this flag whenever by_device_platform is present (false means the list is complete).'
        ),
    ] = None
    by_device_type: Annotated[
        list[ByDeviceTypeItem] | None,
        Field(
            description='Delivery by device form factor within this package. Available when the buyer requests device_type breakdown via reporting_dimensions and the seller supports it.'
        ),
    ] = None
    by_device_type_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_device_type was truncated. Sellers MUST return this flag whenever by_device_type is present (false means the list is complete).'
        ),
    ] = None
    by_geo: Annotated[
        list[ByGeoItem] | None,
        Field(
            description="Delivery by geographic area within this package. Available when the buyer requests geo breakdown via reporting_dimensions and the seller supports it. Each dimension's rows are independent slices that should sum to the package total."
        ),
    ] = None
    by_geo_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_geo was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_geo is present (false means the list is complete).'
        ),
    ] = None
    by_keyword: Annotated[
        list[ByKeywordItem] | None,
        Field(
            description='Metrics broken down by keyword within this package. One row per (keyword, match_type) pair — the same keyword with different match types appears as separate rows. Keyword-grain only: rows reflect aggregate performance of each targeted keyword, not individual search queries. Rows may not sum to package totals when a single impression is attributed to the triggering keyword only. Available for search and retail media packages when the seller supports keyword-level reporting.'
        ),
    ] = None
    by_placement: Annotated[
        list[ByPlacementItem] | None,
        Field(
            description="Delivery by placement within this package. Available when the buyer requests placement breakdown via reporting_dimensions and the seller supports it. Placement IDs reference the product's placements array."
        ),
    ] = None
    by_placement_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_placement was truncated. Sellers MUST return this flag whenever by_placement is present (false means the list is complete).'
        ),
    ] = None
    currency: Annotated[
        str,
        Field(
            description="ISO 4217 currency code (e.g., USD, EUR, GBP) for this package's pricing. Indicates the currency in which the rate and spend values are denominated. Different packages can use different currencies when supported by the publisher.",
            pattern='^[A-Z]{3}$',
        ),
    ]
    daily_breakdown: Annotated[
        list[DailyBreakdownItem] | None,
        Field(
            description='Day-by-day delivery for this package. Only present when include_package_daily_breakdown is true in the request. Enables per-package pacing analysis and line-item monitoring.'
        ),
    ] = None
    delivery_status: Annotated[
        DeliveryStatus | None,
        Field(
            description='System-reported operational state of this package. Reflects actual delivery state independent of buyer pause control.'
        ),
    ] = None
    pacing_index: Annotated[
        float | None,
        Field(description='Delivery pace (1.0 = on track, <1.0 = behind, >1.0 = ahead)', ge=0.0),
    ] = None
    package_id: Annotated[str, Field(description="Publisher's package identifier")]
    paused: Annotated[
        bool | None, Field(description='Whether this package is currently paused by the buyer')
    ] = None
    pricing_model: Annotated[
        pricing_model_1.PricingModel,
        Field(
            description='The pricing model used for this package (e.g., cpm, cpcv, cpp). Indicates how the package is billed and which metrics are most relevant for optimization.'
        ),
    ]
    rate: Annotated[
        float,
        Field(
            description='The pricing rate for this package in the specified currency. For fixed-rate pricing, this is the agreed rate (e.g., CPM rate of 12.50 means $12.50 per 1,000 impressions). For auction-based pricing, this represents the effective rate based on actual delivery.',
            ge=0.0,
        ),
    ]
    spend: Any


class Totals(DeliveryMetrics):
    effective_rate: Annotated[
        float | None,
        Field(
            description="Effective rate paid per unit based on pricing_model (e.g., actual CPM for 'cpm', actual cost per completed view for 'cpcv', actual cost per point for 'cpp')",
            ge=0.0,
        ),
    ] = None
    spend: Any


class MediaBuyDelivery(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    buyer_campaign_ref: Annotated[
        str | None,
        Field(
            description="Buyer's campaign reference label from create_media_buy.buyer_campaign_ref. Groups related operations under a single campaign for CRM and ad server correlation; may be absent when not provided at creation time."
        ),
    ] = None
    buyer_ref: Annotated[
        str | None, Field(description="Buyer's reference identifier for this media buy")
    ] = None
    by_package: Annotated[list[ByPackageItem], Field(description='Metrics broken down by package')]
    daily_breakdown: Annotated[
        list[DailyBreakdownItem1] | None, Field(description='Day-by-day delivery')
    ] = None
    expected_availability: Annotated[
        AwareDatetime | None,
        Field(
            description='When delayed data is expected to be available (only present when status is reporting_delayed)'
        ),
    ] = None
    is_adjusted: Annotated[
        bool | None,
        Field(
            description='Indicates this delivery contains updated data for a previously reported period. Buyer should replace previous period data with these totals.'
        ),
    ] = None
    media_buy_id: Annotated[str, Field(description="Publisher's media buy identifier")]
    pricing_model: Annotated[
        pricing_model_1.PricingModel | None,
        Field(description='Pricing model used for this media buy'),
    ] = None
    status: Annotated[
        Status,
        Field(
            description='Current media buy status. Lifecycle states use the same taxonomy as media-buy-status (`pending_activation`, `active`, `paused`, `completed`, `rejected`, `canceled`). In webhook context, reporting_delayed indicates data temporarily unavailable. `pending` is accepted as a legacy alias for pending_activation.'
        ),
    ]
    totals: Totals


class GetMediaBuyDeliveryResponse(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    aggregated_totals: Annotated[
        AggregatedTotals | None,
        Field(
            description='Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.'
        ),
    ] = None
    attribution_window: Annotated[
        attribution_window_1.AttributionWindow | None,
        Field(
            description='Attribution methodology and lookback windows used for conversion metrics in this response. All media buys from a single seller share the same attribution methodology. Enables cross-platform comparison (e.g., Amazon 14-day click vs. Criteo 30-day click).'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')]
    errors: Annotated[
        list[error.Error] | None,
        Field(
            description='Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None
    media_buy_deliveries: Annotated[
        list[MediaBuyDelivery],
        Field(
            description='Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.'
        ),
    ]
    next_expected_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp for next expected notification (only present in webhook deliveries when notification_type is not 'final')"
        ),
    ] = None
    notification_type: Annotated[
        NotificationType | None,
        Field(
            description='Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with updated data'
        ),
    ] = None
    partial_data: Annotated[
        bool | None,
        Field(
            description='Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)'
        ),
    ] = None
    reporting_period: Annotated[
        ReportingPeriod,
        Field(description='Date range for the report. All periods use UTC timezone.'),
    ]
    sandbox: Annotated[
        bool | None,
        Field(description='When true, this response contains simulated data from sandbox mode.'),
    ] = None
    sequence_number: Annotated[
        int | None,
        Field(
            description='Sequential notification number (only present in webhook deliveries, starts at 1)',
            ge=1,
        ),
    ] = None
    unavailable_count: Annotated[
        int | None,
        Field(
            description='Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)',
            ge=0,
        ),
    ] = None
