# generated by datamodel-codegen:
#   filename:  protocol/get_adcp_capabilities_response.json
#   timestamp: 2026-02-12T02:11:19+00:00

from __future__ import annotations

from enum import Enum
from typing import Annotated

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

from ..core import context as context_1
from ..core import error
from ..core import ext as ext_1
from ..core import media_buy_features
from ..enums import action_source, age_verification_method, channels
from ..enums import event_type as event_type_1
from ..enums import uid_type
from ..sponsored_intelligence import si_capabilities


class DefaultBilling(Enum):
    brand = 'brand'
    operator = 'operator'
    agent = 'agent'


class Account(AdCPBaseModel):
    authorization_endpoint: Annotated[
        AnyUrl | None,
        Field(
            description='OAuth authorization endpoint for obtaining operator-level credentials. Present when the seller supports OAuth for operator authentication. The agent directs the operator to this URL to authenticate and obtain a bearer token. If absent and require_operator_auth is true, operators obtain credentials out-of-band (e.g., seller portal, API key).'
        ),
    ] = None
    default_billing: Annotated[
        DefaultBilling | None,
        Field(
            description='The billing model applied when the agent omits billing from a sync_accounts request. Must be one of the values in supported_billing.'
        ),
    ] = None
    require_operator_auth: Annotated[
        bool | None,
        Field(
            description="Whether the seller requires operator-level credentials. When false (default), the seller trusts the agent's identity claims — the agent authenticates once and declares brands/operators via sync_accounts. When true, each operator must authenticate independently with the seller, and the agent opens a per-operator session using the operator's credential."
        ),
    ] = False
    required_for_products: Annotated[
        bool | None,
        Field(
            description='Whether an active account is required to call get_products. When true, the agent must establish an account via sync_accounts before browsing products. When false, get_products works without an account (account_id is optional for rate-card-specific pricing).'
        ),
    ] = False
    supported_billing: Annotated[
        list[DefaultBilling],
        Field(
            description='Billing models this seller supports. brand: seller invoices the brand directly. operator: seller invoices the operator (agency). agent: agent consolidates billing.',
            min_length=1,
        ),
    ]


class MajorVersion(RootModel[int]):
    root: Annotated[int, Field(ge=1)]


class Adcp(AdCPBaseModel):
    major_versions: Annotated[
        list[MajorVersion],
        Field(
            description='AdCP major versions supported by this seller. Major versions indicate breaking changes.',
            min_length=1,
        ),
    ]


class ExtensionsSupportedItem(RootModel[str]):
    root: Annotated[
        str,
        Field(
            description="Extension namespace (lowercase alphanumeric with underscores, e.g., 'scope3', 'garm', 'iab_tcf')",
            pattern='^[a-z][a-z0-9_]*$',
        ),
    ]


class Range(AdCPBaseModel):
    max: Annotated[float, Field(description='Maximum value')]
    min: Annotated[float, Field(description='Minimum value')]


class Type(Enum):
    binary = 'binary'
    quantitative = 'quantitative'
    categorical = 'categorical'


class PropertyFeature(AdCPBaseModel):
    categories: Annotated[
        list[str] | None, Field(description='For categorical features, the valid values')
    ] = None
    description: Annotated[
        str | None, Field(description='Human-readable description of what this feature measures')
    ] = None
    feature_id: Annotated[
        str,
        Field(
            description="Unique identifier for this feature (e.g., 'consent_quality', 'coppa_certified', 'carbon_score')"
        ),
    ]
    methodology_url: Annotated[
        AnyUrl | None,
        Field(
            description='URL to documentation explaining how this feature is calculated or measured. Helps buyers understand and compare methodologies across vendors.'
        ),
    ] = None
    range: Annotated[
        Range | None, Field(description='For quantitative features, the valid range')
    ] = None
    type: Annotated[
        Type,
        Field(
            description="Data type: 'binary' for yes/no, 'quantitative' for numeric scores, 'categorical' for enum values"
        ),
    ]


class Governance(AdCPBaseModel):
    property_features: Annotated[
        list[PropertyFeature] | None,
        Field(
            description='Property features this governance agent can evaluate. Each feature describes a score, rating, or certification the agent can provide for properties.'
        ),
    ] = None


class AttributionWindow(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    click_through: Annotated[
        list[str],
        Field(
            description='Available click-through attribution windows (e.g. ["7d"], ["7d", "14d", "30d"])',
            min_length=1,
        ),
    ]
    event_type: Annotated[
        event_type_1.EventType | None,
        Field(description='Event type this window applies to, or omit for default window'),
    ] = None
    view_through: Annotated[
        list[str] | None,
        Field(
            description='Available view-through attribution windows (e.g. ["1d"], ["1d", "7d", "14d"])',
            min_length=1,
        ),
    ] = None


class SupportedHashedIdentifier(Enum):
    hashed_email = 'hashed_email'
    hashed_phone = 'hashed_phone'


class MraidVersion(RootModel[str]):
    root: Annotated[str, Field(pattern='^[0-9]+\\.[0-9]+$')]


class VastVersion(MraidVersion):
    pass


class CreativeSpecs(AdCPBaseModel):
    mraid_versions: Annotated[
        list[MraidVersion] | None,
        Field(description='MRAID versions supported for rich media mobile creatives'),
    ] = None
    simid: Annotated[bool | None, Field(description='SIMID support for interactive video ads')] = (
        None
    )
    vast_versions: Annotated[
        list[VastVersion] | None, Field(description='VAST versions supported for video creatives')
    ] = None
    vpaid: Annotated[bool | None, Field(description='VPAID support for interactive video ads')] = (
        None
    )


class AgeRestriction(AdCPBaseModel):
    supported: Annotated[
        bool | None, Field(description='Whether seller supports age restrictions')
    ] = None
    verification_methods: Annotated[
        list[age_verification_method.AgeVerificationMethod] | None,
        Field(description='Age verification methods this seller supports'),
    ] = None


class GeoMetros(AdCPBaseModel):
    eurostat_nuts2: Annotated[
        bool | None, Field(description='Supports Eurostat NUTS Level 2 regions (EU)')
    ] = None
    nielsen_dma: Annotated[
        bool | None,
        Field(description="Supports Nielsen DMA codes (US market, e.g., '501' for NYC)"),
    ] = None
    uk_itl1: Annotated[bool | None, Field(description='Supports UK ITL Level 1 regions')] = None
    uk_itl2: Annotated[bool | None, Field(description='Supports UK ITL Level 2 regions')] = None


class GeoPostalAreas(AdCPBaseModel):
    au_postcode: Annotated[
        bool | None, Field(description="Australian postcode, 4 digits (e.g., '2000')")
    ] = None
    ca_fsa: Annotated[
        bool | None, Field(description="Canadian Forward Sortation Area (e.g., 'K1A')")
    ] = None
    ca_full: Annotated[
        bool | None, Field(description="Canadian full postal code (e.g., 'K1A 0B1')")
    ] = None
    de_plz: Annotated[
        bool | None, Field(description="German Postleitzahl, 5 digits (e.g., '10115')")
    ] = None
    fr_code_postal: Annotated[
        bool | None, Field(description="French code postal, 5 digits (e.g., '75001')")
    ] = None
    gb_full: Annotated[bool | None, Field(description="UK full postcode (e.g., 'SW1A 1AA')")] = None
    gb_outward: Annotated[
        bool | None, Field(description="UK postcode district / outward code (e.g., 'SW1', 'EC1')")
    ] = None
    us_zip: Annotated[bool | None, Field(description="US 5-digit ZIP codes (e.g., '10001')")] = None
    us_zip_plus_four: Annotated[
        bool | None, Field(description="US 9-digit ZIP+4 codes (e.g., '10001-1234')")
    ] = None


class Targeting(AdCPBaseModel):
    age_restriction: Annotated[
        AgeRestriction | None,
        Field(description='Age restriction capabilities for compliance (alcohol, gambling)'),
    ] = None
    device_platform: Annotated[
        bool | None,
        Field(
            description='Whether seller supports device platform targeting (Sec-CH-UA-Platform values)'
        ),
    ] = None
    geo_countries: Annotated[
        bool | None,
        Field(
            description="Supports country-level geo targeting using ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE')"
        ),
    ] = None
    geo_metros: Annotated[
        GeoMetros | None,
        Field(
            description='Metro area targeting support. Specifies which classification systems are supported.'
        ),
    ] = None
    geo_postal_areas: Annotated[
        GeoPostalAreas | None,
        Field(
            description='Postal area targeting support. Specifies which postal code systems are supported. System names encode country and precision.'
        ),
    ] = None
    geo_regions: Annotated[
        bool | None,
        Field(
            description="Supports region/state-level geo targeting using ISO 3166-2 subdivision codes (e.g., 'US-NY', 'GB-SCT', 'DE-BY')"
        ),
    ] = None
    language: Annotated[
        bool | None,
        Field(description='Whether seller supports language targeting (ISO 639-1 codes)'),
    ] = None


class Execution(AdCPBaseModel):
    axe_integrations: Annotated[
        list[AnyUrl] | None,
        Field(
            description='Agentic ad exchange (AXE) integrations supported. URLs are canonical identifiers for exchanges this seller can execute through.'
        ),
    ] = None
    creative_specs: Annotated[
        CreativeSpecs | None, Field(description='Creative specification support')
    ] = None
    targeting: Annotated[
        Targeting | None,
        Field(
            description='Targeting capabilities. If declared true/supported, buyer can use these targeting parameters and seller MUST honor them.'
        ),
    ] = None


class PrimaryCountry(RootModel[str]):
    root: Annotated[str, Field(pattern='^[A-Z]{2}$')]


class PublisherDomain(RootModel[str]):
    root: Annotated[
        str, Field(pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$')
    ]


class Portfolio(AdCPBaseModel):
    advertising_policies: Annotated[
        str | None,
        Field(
            description='Advertising content policies, restrictions, and guidelines',
            max_length=10000,
        ),
    ] = None
    description: Annotated[
        str | None,
        Field(
            description='Markdown-formatted description of the inventory portfolio', max_length=5000
        ),
    ] = None
    primary_channels: Annotated[
        list[channels.MediaChannel] | None,
        Field(description='Primary advertising channels in this portfolio'),
    ] = None
    primary_countries: Annotated[
        list[PrimaryCountry] | None,
        Field(description='Primary countries (ISO 3166-1 alpha-2) where inventory is concentrated'),
    ] = None
    publisher_domains: Annotated[
        list[PublisherDomain],
        Field(
            description="Publisher domains this seller is authorized to represent. Buyers should fetch each publisher's adagents.json for property definitions.",
            min_length=1,
        ),
    ]


class DataProviderDomain(PublisherDomain):
    pass


class Features(AdCPBaseModel):
    catalog_signals: Annotated[
        bool | None,
        Field(
            description='Supports signals from data provider catalogs with structured signal_id references'
        ),
    ] = None


class Signals(AdCPBaseModel):
    data_provider_domains: Annotated[
        list[DataProviderDomain] | None,
        Field(
            description="Data provider domains this signals agent is authorized to resell. Buyers should fetch each data provider's adagents.json for signal catalog definitions and to verify authorization.",
            min_length=1,
        ),
    ] = None
    features: Annotated[
        Features | None, Field(description='Optional signals features supported')
    ] = None


class Preferred(Enum):
    mcp = 'mcp'
    a2a = 'a2a'


class Transport(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    type: Annotated[Preferred, Field(description='Protocol transport type')]
    url: Annotated[AnyUrl, Field(description='Agent endpoint URL for this transport')]


class Endpoint(AdCPBaseModel):
    preferred: Annotated[
        Preferred | None, Field(description='Preferred transport when host supports multiple')
    ] = None
    transports: Annotated[
        list[Transport],
        Field(
            description='Available protocol transports. Hosts select based on their capabilities.',
            min_length=1,
        ),
    ]


class SupportedProtocol(Enum):
    media_buy = 'media_buy'
    signals = 'signals'
    governance = 'governance'
    sponsored_intelligence = 'sponsored_intelligence'
    creative = 'creative'


class ConversionTracking(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    attribution_windows: Annotated[
        list[AttributionWindow] | None,
        Field(
            description='Attribution windows available from this seller. Single-element arrays indicate fixed windows; multi-element arrays indicate configurable options the buyer can choose from via optimization_goal.attribution_window on packages.'
        ),
    ] = None
    supported_action_sources: Annotated[
        list[action_source.ActionSource] | None,
        Field(description='Action sources this seller accepts events from', min_length=1),
    ] = None
    supported_event_types: Annotated[
        list[event_type_1.EventType] | None,
        Field(
            description='Event types this seller can track and attribute. If omitted, all standard event types are supported.',
            min_length=1,
        ),
    ] = None
    supported_hashed_identifiers: Annotated[
        list[SupportedHashedIdentifier] | None,
        Field(
            description='Hashed PII types accepted for user matching. Buyers must hash before sending (SHA-256, normalized).',
            min_length=1,
        ),
    ] = None
    supported_uid_types: Annotated[
        list[uid_type.UidType] | None,
        Field(description='Universal ID types accepted for user matching', min_length=1),
    ] = None


class MediaBuy(AdCPBaseModel):
    conversion_tracking: Annotated[
        ConversionTracking | None,
        Field(
            description='Seller-level conversion tracking capabilities. Only present when features.conversion_tracking is true.'
        ),
    ] = None
    execution: Annotated[
        Execution | None, Field(description='Technical execution capabilities for media buying')
    ] = None
    features: media_buy_features.MediaBuyFeatures | None = None
    portfolio: Annotated[
        Portfolio | None,
        Field(description="Information about the seller's media inventory portfolio"),
    ] = None


class SponsoredIntelligence(AdCPBaseModel):
    brand_manifest_url: Annotated[
        AnyUrl | None, Field(description='URL to brand manifest with colors, fonts, logos, tone')
    ] = None
    capabilities: Annotated[
        si_capabilities.SiCapabilities,
        Field(description='Modalities, components, and commerce capabilities'),
    ]
    endpoint: Annotated[Endpoint, Field(description='SI agent endpoint configuration')]


class GetAdcpCapabilitiesResponse(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        Account | None,
        Field(
            description='Account management capabilities. Describes how accounts are established, what billing models are supported, and whether an account is required before browsing products.'
        ),
    ] = None
    adcp: Annotated[Adcp, Field(description='Core AdCP protocol information')]
    context: context_1.ContextObject | None = None
    errors: Annotated[
        list[error.Error] | None, Field(description='Task-specific errors and warnings')
    ] = None
    ext: ext_1.ExtensionObject | None = None
    extensions_supported: Annotated[
        list[ExtensionsSupportedItem] | None,
        Field(
            description='Extension namespaces this agent supports. Buyers can expect meaningful data in ext.{namespace} fields on responses from this agent. Extension schemas are published in the AdCP extension registry.'
        ),
    ] = None
    governance: Annotated[
        Governance | None,
        Field(
            description='Governance protocol capabilities. Only present if governance is in supported_protocols. Governance agents provide property data like compliance scores, brand safety ratings, and sustainability metrics.'
        ),
    ] = None
    last_updated: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 timestamp of when capabilities were last updated. Buyers can use this for cache invalidation.'
        ),
    ] = None
    media_buy: Annotated[
        MediaBuy | None,
        Field(
            description='Media-buy protocol capabilities. Only present if media_buy is in supported_protocols.'
        ),
    ] = None
    signals: Annotated[
        Signals | None,
        Field(
            description='Signals protocol capabilities. Only present if signals is in supported_protocols.'
        ),
    ] = None
    sponsored_intelligence: Annotated[
        SponsoredIntelligence | None,
        Field(
            description='Sponsored Intelligence protocol capabilities. Only present if sponsored_intelligence is in supported_protocols. SI agents handle conversational brand experiences.'
        ),
    ] = None
    supported_protocols: Annotated[
        list[SupportedProtocol],
        Field(description='Which AdCP domain protocols this seller supports', min_length=1),
    ]
