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

from __future__ import annotations

from enum import Enum
from typing import Annotated

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

from ..core import account as account_1
from ..core import context as context_1
from ..core import error
from ..core import ext as ext_1
from ..core import format_id, pagination_response
from ..enums import creative_approval_status, media_buy_status


class CreativeApproval(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    approval_status: creative_approval_status.CreativeApprovalStatus
    creative_id: Annotated[str, Field(description='Creative identifier')]
    rejection_reason: Annotated[
        str | None,
        Field(
            description="Human-readable explanation of why the creative was rejected. Present only when approval_status is 'rejected'."
        ),
    ] = None


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


class Snapshot(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    as_of: Annotated[
        AwareDatetime,
        Field(description='ISO 8601 timestamp when this snapshot was captured by the platform'),
    ]
    clicks: Annotated[
        float | None, Field(description='Total clicks since package start (when available)', ge=0.0)
    ] = None
    currency: Annotated[
        str | None,
        Field(
            description='ISO 4217 currency code for spend in this snapshot. Optional when unchanged from package.currency or media_buy.currency.',
            pattern='^[A-Z]{3}$',
        ),
    ] = None
    delivery_status: Annotated[
        DeliveryStatus | None,
        Field(
            description="Operational delivery state of this package. 'not_delivering' means the package is within its scheduled flight but has delivered zero impressions for at least one full staleness cycle — the signal for automated price adjustments or buyer alerts. Implementers must not return 'not_delivering' until at least staleness_seconds have elapsed since package activation."
        ),
    ] = None
    ext: Annotated[
        ext_1.ExtensionObject | None,
        Field(description='Optional extension object for seller-specific snapshot fields.'),
    ] = None
    impressions: Annotated[
        float, Field(description='Total impressions delivered since package start', ge=0.0)
    ]
    pacing_index: Annotated[
        float | None,
        Field(
            description='Current delivery pace relative to expected (1.0 = on track, <1.0 = behind, >1.0 = ahead). Absent when pacing cannot be determined.',
            ge=0.0,
        ),
    ] = None
    spend: Annotated[
        float,
        Field(
            description='Total spend since package start, denominated in snapshot.currency when present, otherwise package.currency or media_buy.currency',
            ge=0.0,
        ),
    ]
    staleness_seconds: Annotated[
        int,
        Field(
            description='Maximum age of this data in seconds. For example, 900 means the data may be up to 15 minutes old. Use this to interpret zero delivery: a value of 900 means zero impressions is likely real; a value of 14400 means reporting may still be catching up.',
            ge=0,
        ),
    ]


class SnapshotUnavailableReason(Enum):
    SNAPSHOT_UNSUPPORTED = 'SNAPSHOT_UNSUPPORTED'
    SNAPSHOT_TEMPORARILY_UNAVAILABLE = 'SNAPSHOT_TEMPORARILY_UNAVAILABLE'
    SNAPSHOT_PERMISSION_DENIED = 'SNAPSHOT_PERMISSION_DENIED'


class Package(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    bid_price: Annotated[
        float | None,
        Field(
            description='Current bid price for auction-based packages. Denominated in package.currency when present, otherwise media_buy.currency. Relevant for automated price optimization loops.',
            ge=0.0,
        ),
    ] = None
    budget: Annotated[
        float | None,
        Field(
            description='Package budget amount, denominated in package.currency when present, otherwise media_buy.currency',
            ge=0.0,
        ),
    ] = None
    buyer_ref: Annotated[
        str | None, Field(description="Buyer's reference identifier for this package")
    ] = None
    creative_approvals: Annotated[
        list[CreativeApproval] | None,
        Field(
            description='Approval status for each creative assigned to this package. Absent when no creatives have been assigned.'
        ),
    ] = None
    currency: Annotated[
        str | None,
        Field(
            description='ISO 4217 currency code for monetary values at this package level (budget, bid_price, snapshot.spend). When absent, inherit media_buy.currency.',
            pattern='^[A-Z]{3}$',
        ),
    ] = None
    end_time: Annotated[
        AwareDatetime | None, Field(description='ISO 8601 flight end time for this package')
    ] = None
    ext: ext_1.ExtensionObject | None = None
    format_ids_pending: Annotated[
        list[format_id.FormatId] | None,
        Field(
            description='Format IDs from the original create_media_buy format_ids_to_provide that have not yet been uploaded via sync_creatives. When empty or absent, all required formats have been provided.'
        ),
    ] = None
    impressions: Annotated[
        float | None,
        Field(description='Goal impression count for impression-based packages', 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
    product_id: Annotated[
        str | None, Field(description='Product identifier this package is purchased from')
    ] = None
    snapshot: Annotated[
        Snapshot | None,
        Field(
            description='Near-real-time delivery snapshot for this package. Only present when include_snapshot was true in the request. Represents the latest available entity-level stats from the platform — not billing-grade data.'
        ),
    ] = None
    snapshot_unavailable_reason: Annotated[
        SnapshotUnavailableReason | None,
        Field(
            description='Machine-readable reason the snapshot is omitted. Present only when include_snapshot was true and snapshot is unavailable for this package.'
        ),
    ] = None
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 flight start time for this package. Use to determine whether the package is within its scheduled flight before interpreting delivery status.'
        ),
    ] = None


class MediaBuy(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_1.Account | None, Field(description='Account billed for this media buy')
    ] = None
    buyer_campaign_ref: Annotated[
        str | None,
        Field(
            description='Buyer campaign reference label sourced from create_media_buy.buyer_campaign_ref. Groups related operations under a single campaign; 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
    created_at: Annotated[AwareDatetime | None, Field(description='Creation timestamp')] = None
    creative_deadline: Annotated[
        AwareDatetime | None, Field(description='ISO 8601 timestamp for creative upload deadline')
    ] = None
    currency: Annotated[
        str,
        Field(
            description='ISO 4217 currency code (e.g., USD, EUR, GBP) for monetary values at this media buy level. total_budget is always denominated in this currency. Package-level fields may override with package.currency.',
            pattern='^[A-Z]{3}$',
        ),
    ]
    end_time: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 flight end time for this media buy (latest package end_time). Avoids requiring buyers to compute max(packages[].end_time).'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None
    media_buy_id: Annotated[
        str, Field(description="Publisher's unique identifier for the media buy")
    ]
    packages: Annotated[
        list[Package],
        Field(
            description='Packages within this media buy, augmented with creative approval status and optional delivery snapshots'
        ),
    ]
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 flight start time for this media buy (earliest package start_time). Avoids requiring buyers to compute min(packages[].start_time).'
        ),
    ] = None
    status: media_buy_status.MediaBuyStatus
    total_budget: Annotated[
        float,
        Field(
            description='Total budget amount across all packages, denominated in media_buy.currency',
            ge=0.0,
        ),
    ]
    updated_at: Annotated[AwareDatetime | None, Field(description='Last update timestamp')] = None


class GetMediaBuysResponse(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    context: context_1.ContextObject | None = None
    errors: Annotated[
        list[error.Error] | None,
        Field(description='Task-specific errors (e.g., media buy not found)'),
    ] = None
    ext: ext_1.ExtensionObject | None = None
    media_buys: Annotated[
        list[MediaBuy],
        Field(
            description='Array of media buys with status, creative approval state, and optional delivery snapshots'
        ),
    ]
    pagination: Annotated[
        pagination_response.PaginationResponse | None,
        Field(description='Pagination metadata for the media_buys array.'),
    ] = None
    sandbox: Annotated[
        bool | None,
        Field(description='When true, this response contains simulated data from sandbox mode.'),
    ] = None
