# generated by datamodel-codegen:
#   filename:  core/delivery_metrics.json
#   timestamp: 2026-02-27T02:10:10+00:00

from __future__ import annotations

from enum import Enum
from typing import Annotated

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

from ..enums import action_source as action_source_1
from ..enums import event_type as event_type_1


class ByActionSourceItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    action_source: Annotated[
        action_source_1.ActionSource, Field(description='Where the conversion occurred')
    ]
    count: Annotated[
        float, Field(description='Number of conversions from this action source', ge=0.0)
    ]
    event_source_id: Annotated[
        str | None,
        Field(
            description='Event source that produced these conversions (for disambiguation when multiple event sources are configured)'
        ),
    ] = None
    value: Annotated[
        float | None,
        Field(description='Total monetary value of conversions from this action source', ge=0.0),
    ] = None


class VenueBreakdownItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    impressions: Annotated[int, Field(description='Impressions delivered at this venue', ge=0)]
    loop_plays: Annotated[int | None, Field(description='Loop plays at this venue', ge=0)] = None
    screens_used: Annotated[
        int | None, Field(description='Number of screens used at this venue', ge=0)
    ] = None
    venue_id: Annotated[str, Field(description='Venue identifier')]
    venue_name: Annotated[str | None, Field(description='Human-readable venue name')] = None
    venue_type: Annotated[
        str | None,
        Field(description="Venue type (e.g., 'airport', 'transit', 'retail', 'billboard')"),
    ] = None


class DoohMetrics(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    calculation_notes: Annotated[
        str | None, Field(description='Explanation of how DOOH impressions were calculated')
    ] = None
    loop_plays: Annotated[
        int | None, Field(description='Number of times ad played in rotation', ge=0)
    ] = None
    screen_time_seconds: Annotated[
        int | None, Field(description='Total display time in seconds', ge=0)
    ] = None
    screens_used: Annotated[
        int | None, Field(description='Number of unique screens displaying the ad', ge=0)
    ] = None
    sov_achieved: Annotated[
        float | None,
        Field(description='Actual share of voice delivered (0.0 to 1.0)', ge=0.0, le=1.0),
    ] = None
    venue_breakdown: Annotated[
        list[VenueBreakdownItem] | None, Field(description='Per-venue performance breakdown')
    ] = None


class QuartileData(AdCPBaseModel):
    q1_views: Annotated[float | None, Field(description='25% completion views', ge=0.0)] = None
    q2_views: Annotated[float | None, Field(description='50% completion views', ge=0.0)] = None
    q3_views: Annotated[float | None, Field(description='75% completion views', ge=0.0)] = None
    q4_views: Annotated[float | None, Field(description='100% completion views', ge=0.0)] = None


class Standard(Enum):
    mrc = 'mrc'
    groupm = 'groupm'


class Viewability(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    measurable_impressions: Annotated[
        float | None,
        Field(
            description='Impressions where viewability could be measured. Excludes environments without measurement capability (e.g., non-Intersection Observer browsers, certain app environments).',
            ge=0.0,
        ),
    ] = None
    standard: Annotated[
        Standard | None,
        Field(
            description="Viewability measurement standard. 'mrc': 50% of pixels in view for 1 second (display) or 2 seconds (video), per MRC/IAB guidelines. 'groupm': 100% of pixels in view for the same durations. These are materially different thresholds and should not be compared across standards."
        ),
    ] = None
    viewable_impressions: Annotated[
        float | None,
        Field(
            description='Impressions that met the viewability threshold defined by the measurement standard.',
            ge=0.0,
        ),
    ] = None
    viewable_rate: Annotated[
        float | None,
        Field(
            description='Viewable impression rate (viewable_impressions / measurable_impressions). Range 0.0 to 1.0.',
            ge=0.0,
            le=1.0,
        ),
    ] = None


class ByEventTypeItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    count: Annotated[float, Field(description='Number of events of this type', ge=0.0)]
    event_source_id: Annotated[
        str | None,
        Field(
            description='Event source that produced these conversions (for disambiguation when multiple event sources are configured)'
        ),
    ] = None
    event_type: Annotated[event_type_1.EventType, Field(description='The event type')]
    value: Annotated[
        float | None, Field(description='Total monetary value of events of this type', ge=0.0)
    ] = None


class DeliveryMetrics(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    by_action_source: Annotated[
        list[ByActionSourceItem] | None,
        Field(
            description='Conversion metrics broken down by action source (website, app, in_store, etc.). Useful for omnichannel sellers where conversions occur across digital and physical channels.'
        ),
    ] = None
    by_event_type: Annotated[
        list[ByEventTypeItem] | None,
        Field(
            description='Conversion metrics broken down by event type. Spend-derived metrics (ROAS, CPA) are only available at the package/totals level since spend cannot be attributed to individual event types.'
        ),
    ] = None
    clicks: Annotated[float | None, Field(description='Total clicks', ge=0.0)] = None
    completed_views: Annotated[
        float | None,
        Field(
            description='Video/audio completions. When the package has a completed_views optimization goal with view_duration_seconds, completions are counted at that threshold rather than 100% completion.',
            ge=0.0,
        ),
    ] = None
    completion_rate: Annotated[
        float | None,
        Field(description='Completion rate (completed_views/impressions)', ge=0.0, le=1.0),
    ] = None
    conversion_value: Annotated[
        float | None,
        Field(
            description='Total monetary value of attributed conversions (in the reporting currency)',
            ge=0.0,
        ),
    ] = None
    conversions: Annotated[
        float | None,
        Field(
            description='Total conversions attributed to this delivery. When by_event_type is present, this equals the sum of all by_event_type[].count entries.',
            ge=0.0,
        ),
    ] = None
    cost_per_acquisition: Annotated[
        float | None, Field(description='Cost per conversion (spend / conversions)', ge=0.0)
    ] = None
    cost_per_click: Annotated[
        float | None, Field(description='Cost per click (spend / clicks)', ge=0.0)
    ] = None
    ctr: Annotated[
        float | None, Field(description='Click-through rate (clicks/impressions)', ge=0.0, le=1.0)
    ] = None
    dooh_metrics: Annotated[
        DoohMetrics | None,
        Field(description='DOOH-specific metrics (only included for DOOH campaigns)'),
    ] = None
    engagement_rate: Annotated[
        float | None,
        Field(
            description='Platform-specific engagement rate (0.0 to 1.0). Typically engagements/impressions, but definition varies by platform.',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    engagements: Annotated[
        float | None,
        Field(
            description="Total engagements — direct interactions with the ad beyond viewing. Includes social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio. Platform-specific; corresponds to the 'engagements' optimization metric.",
            ge=0.0,
        ),
    ] = None
    follows: Annotated[
        float | None,
        Field(
            description='New followers, page likes, artist/podcast/channel subscribes attributed to this delivery.',
            ge=0.0,
        ),
    ] = None
    frequency: Annotated[
        float | None,
        Field(
            description='Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)',
            ge=0.0,
        ),
    ] = None
    grps: Annotated[
        float | None, Field(description='Gross Rating Points delivered (for CPP)', ge=0.0)
    ] = None
    impressions: Annotated[float | None, Field(description='Impressions delivered', ge=0.0)] = None
    leads: Annotated[
        float | None,
        Field(
            description="Leads generated (convenience alias for by_event_type where event_type='lead')",
            ge=0.0,
        ),
    ] = None
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Fraction of conversions from first-time brand buyers (0 = none, 1 = all)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    profile_visits: Annotated[
        float | None,
        Field(
            description="Visits to the brand's in-platform page (profile, artist page, channel, or storefront) attributed to this delivery. Does not include external website clicks.",
            ge=0.0,
        ),
    ] = None
    quartile_data: Annotated[
        QuartileData | None, Field(description='Video quartile completion data')
    ] = None
    reach: Annotated[
        float | None,
        Field(
            description='Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.',
            ge=0.0,
        ),
    ] = None
    roas: Annotated[
        float | None, Field(description='Return on ad spend (conversion_value / spend)', ge=0.0)
    ] = None
    saves: Annotated[
        float | None,
        Field(
            description='Saves, bookmarks, playlist adds, pins attributed to this delivery.', ge=0.0
        ),
    ] = None
    spend: Annotated[float | None, Field(description='Amount spent', ge=0.0)] = None
    viewability: Annotated[
        Viewability | None,
        Field(
            description='Viewability metrics. Viewable rate should be calculated as viewable_impressions / measurable_impressions (not total impressions), since some environments cannot measure viewability.'
        ),
    ] = None
    views: Annotated[float | None, Field(description='Views at threshold (for CPV)', ge=0.0)] = None
