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

from __future__ import annotations

from enum import Enum
from typing import Annotated, Any, Literal

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

from ..enums import available_metric, format_category, format_id_parameter, universal_macro
from ..enums import wcag_level as wcag_level_1
from . import format_id as format_id_1
from .requirements import (
    audio_asset_requirements,
    css_asset_requirements,
    daast_asset_requirements,
    html_asset_requirements,
    image_asset_requirements,
    javascript_asset_requirements,
    markdown_asset_requirements,
    promoted_offerings_asset_requirements,
    text_asset_requirements,
    url_asset_requirements,
    vast_asset_requirements,
    video_asset_requirements,
    webhook_asset_requirements,
)


class SelectionMode(Enum):
    sequential = 'sequential'
    optimize = 'optimize'


class Responsive(AdCPBaseModel):
    height: bool
    width: bool


class Dimensions(AdCPBaseModel):
    aspect_ratio: Annotated[
        str | None,
        Field(
            description="Fixed aspect ratio constraint (e.g., '16:9', '4:3', '1:1')",
            pattern='^\\d+:\\d+$',
        ),
    ] = None
    height: Annotated[int | None, Field(description='Fixed height in pixels', ge=1)] = None
    max_height: Annotated[
        int | None, Field(description='Maximum height in pixels for responsive renders', ge=1)
    ] = None
    max_width: Annotated[
        int | None, Field(description='Maximum width in pixels for responsive renders', ge=1)
    ] = None
    min_height: Annotated[
        int | None, Field(description='Minimum height in pixels for responsive renders', ge=1)
    ] = None
    min_width: Annotated[
        int | None, Field(description='Minimum width in pixels for responsive renders', ge=1)
    ] = None
    responsive: Annotated[
        Responsive | None, Field(description='Indicates which dimensions are responsive/fluid')
    ] = None
    width: Annotated[int | None, Field(description='Fixed width in pixels', ge=1)] = None


class Renders(AdCPBaseModel):
    dimensions: Annotated[
        Dimensions, Field(description='Dimensions for this rendered piece (in pixels)')
    ]
    parameters_from_format_id: Annotated[
        bool | None,
        Field(
            description='When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly.'
        ),
    ] = None
    role: Annotated[
        str,
        Field(
            description="Semantic role of this rendered piece (e.g., 'primary', 'companion', 'mobile_variant')"
        ),
    ]


class Dimensions1(Dimensions):
    pass


class Renders1(AdCPBaseModel):
    dimensions: Annotated[
        Dimensions1 | None, Field(description='Dimensions for this rendered piece (in pixels)')
    ] = None
    parameters_from_format_id: Annotated[
        Literal[True],
        Field(
            description='When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly.'
        ),
    ]
    role: Annotated[
        str,
        Field(
            description="Semantic role of this rendered piece (e.g., 'primary', 'companion', 'mobile_variant')"
        ),
    ]


class BaseGroupAsset(AdCPBaseModel):
    asset_id: Annotated[str, Field(description='Identifier for this asset within the group')]
    asset_role: Annotated[
        str | None,
        Field(
            description="Optional descriptive label for this asset's purpose. Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only."
        ),
    ] = None
    required: Annotated[
        bool,
        Field(description='Whether this asset is required within each repetition of the group'),
    ]


class BaseIndividualAsset(AdCPBaseModel):
    asset_id: Annotated[
        str,
        Field(
            description='Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object.'
        ),
    ]
    asset_role: Annotated[
        str | None,
        Field(
            description="Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo', 'third_party_tracking'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only."
        ),
    ] = None
    item_type: Annotated[
        Literal['individual'],
        Field(description='Discriminator indicating this is an individual asset'),
    ]
    required: Annotated[
        bool,
        Field(
            description='Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.'
        ),
    ]


class Accessibility(AdCPBaseModel):
    requires_accessible_assets: Annotated[
        bool | None,
        Field(
            description='When true, all assets with x-accessibility fields must include those fields. For inspectable assets (image, video, audio), this means providing accessibility metadata like alt_text or captions. For opaque assets (HTML, JavaScript), this means providing self-declared accessibility properties.'
        ),
    ] = None
    wcag_level: Annotated[
        wcag_level_1.WcagLevel,
        Field(
            description='WCAG conformance level that this format achieves. For format-rendered creatives, the format guarantees this level. For opaque creatives, the format requires assets that self-certify to this level.'
        ),
    ]


class Assets(BaseIndividualAsset):
    asset_type: Literal['image'] = 'image'
    item_type: Literal['individual'] = 'individual'
    requirements: image_asset_requirements.ImageAssetRequirements | None = None


class Assets5(BaseIndividualAsset):
    asset_type: Literal['video'] = 'video'
    item_type: Literal['individual'] = 'individual'
    requirements: video_asset_requirements.VideoAssetRequirements | None = None


class Assets6(BaseIndividualAsset):
    asset_type: Literal['audio'] = 'audio'
    item_type: Literal['individual'] = 'individual'
    requirements: audio_asset_requirements.AudioAssetRequirements | None = None


class Assets7(BaseIndividualAsset):
    asset_type: Literal['text'] = 'text'
    item_type: Literal['individual'] = 'individual'
    requirements: text_asset_requirements.TextAssetRequirements | None = None


class Assets8(BaseIndividualAsset):
    asset_type: Literal['markdown'] = 'markdown'
    item_type: Literal['individual'] = 'individual'
    requirements: markdown_asset_requirements.MarkdownAssetRequirements | None = None


class Assets9(BaseIndividualAsset):
    asset_type: Literal['html'] = 'html'
    item_type: Literal['individual'] = 'individual'
    requirements: html_asset_requirements.HtmlAssetRequirements | None = None


class Assets10(BaseIndividualAsset):
    asset_type: Literal['css'] = 'css'
    item_type: Literal['individual'] = 'individual'
    requirements: css_asset_requirements.CssAssetRequirements | None = None


class Assets11(BaseIndividualAsset):
    asset_type: Literal['javascript'] = 'javascript'
    item_type: Literal['individual'] = 'individual'
    requirements: javascript_asset_requirements.JavascriptAssetRequirements | None = None


class Assets12(BaseIndividualAsset):
    asset_type: Literal['vast'] = 'vast'
    item_type: Literal['individual'] = 'individual'
    requirements: vast_asset_requirements.VastAssetRequirements | None = None


class Assets13(BaseIndividualAsset):
    asset_type: Literal['daast'] = 'daast'
    item_type: Literal['individual'] = 'individual'
    requirements: daast_asset_requirements.DaastAssetRequirements | None = None


class Assets14(BaseIndividualAsset):
    asset_type: Literal['promoted_offerings'] = 'promoted_offerings'
    item_type: Literal['individual'] = 'individual'
    requirements: (
        promoted_offerings_asset_requirements.PromotedOfferingsAssetRequirements | None
    ) = None


class Assets15(BaseIndividualAsset):
    asset_type: Literal['url'] = 'url'
    item_type: Literal['individual'] = 'individual'
    requirements: url_asset_requirements.UrlAssetRequirements | None = None


class Assets16(BaseIndividualAsset):
    asset_type: Literal['webhook'] = 'webhook'
    item_type: Literal['individual'] = 'individual'
    requirements: webhook_asset_requirements.WebhookAssetRequirements | None = None


class Assets18(BaseGroupAsset):
    asset_type: Literal['image'] = 'image'
    requirements: image_asset_requirements.ImageAssetRequirements | None = None


class Assets19(BaseGroupAsset):
    asset_type: Literal['video'] = 'video'
    requirements: video_asset_requirements.VideoAssetRequirements | None = None


class Assets20(BaseGroupAsset):
    asset_type: Literal['audio'] = 'audio'
    requirements: audio_asset_requirements.AudioAssetRequirements | None = None


class Assets21(BaseGroupAsset):
    asset_type: Literal['text'] = 'text'
    requirements: text_asset_requirements.TextAssetRequirements | None = None


class Assets22(BaseGroupAsset):
    asset_type: Literal['markdown'] = 'markdown'
    requirements: markdown_asset_requirements.MarkdownAssetRequirements | None = None


class Assets23(BaseGroupAsset):
    asset_type: Literal['html'] = 'html'
    requirements: html_asset_requirements.HtmlAssetRequirements | None = None


class Assets24(BaseGroupAsset):
    asset_type: Literal['css'] = 'css'
    requirements: css_asset_requirements.CssAssetRequirements | None = None


class Assets25(BaseGroupAsset):
    asset_type: Literal['javascript'] = 'javascript'
    requirements: javascript_asset_requirements.JavascriptAssetRequirements | None = None


class Assets26(BaseGroupAsset):
    asset_type: Literal['vast'] = 'vast'
    requirements: vast_asset_requirements.VastAssetRequirements | None = None


class Assets27(BaseGroupAsset):
    asset_type: Literal['daast'] = 'daast'
    requirements: daast_asset_requirements.DaastAssetRequirements | None = None


class Assets28(BaseGroupAsset):
    asset_type: Literal['promoted_offerings'] = 'promoted_offerings'
    requirements: (
        promoted_offerings_asset_requirements.PromotedOfferingsAssetRequirements | None
    ) = None


class Assets29(BaseGroupAsset):
    asset_type: Literal['url'] = 'url'
    requirements: url_asset_requirements.UrlAssetRequirements | None = None


class Assets30(BaseGroupAsset):
    asset_type: Literal['webhook'] = 'webhook'
    requirements: webhook_asset_requirements.WebhookAssetRequirements | None = None


class Assets17(AdCPBaseModel):
    asset_group_id: Annotated[
        str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')")
    ]
    assets: Annotated[
        list[
            Assets18
            | Assets19
            | Assets20
            | Assets21
            | Assets22
            | Assets23
            | Assets24
            | Assets25
            | Assets26
            | Assets27
            | Assets28
            | Assets29
            | Assets30
        ],
        Field(description='Assets within each repetition of this group'),
    ]
    item_type: Annotated[
        Literal['repeatable_group'],
        Field(description='Discriminator indicating this is a repeatable asset group'),
    ]
    max_count: Annotated[int, Field(description='Maximum number of repetitions allowed', ge=1)]
    min_count: Annotated[
        int,
        Field(
            description='Minimum number of repetitions required (if group is required) or allowed (if optional)',
            ge=0,
        ),
    ]
    required: Annotated[
        bool,
        Field(
            description='Whether this asset group is required. If true, at least min_count repetitions must be provided.'
        ),
    ]
    selection_mode: Annotated[
        SelectionMode | None,
        Field(
            description="How the platform uses repetitions of this group. 'sequential' means all items display in order (carousels, playlists). 'optimize' means the platform selects the best-performing combination from alternatives (asset group optimization like Meta Advantage+ or Google Pmax)."
        ),
    ] = SelectionMode.sequential


class FormatCard(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    format_id: Annotated[
        format_id_1.FormatId,
        Field(
            description='Creative format defining the card layout (typically format_card_standard)'
        ),
    ]
    manifest: Annotated[
        dict[str, Any],
        Field(description='Asset manifest for rendering the card, structure defined by the format'),
    ]


class FormatCardDetailed(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    format_id: Annotated[
        format_id_1.FormatId,
        Field(
            description='Creative format defining the detailed card layout (typically format_card_detailed)'
        ),
    ]
    manifest: Annotated[
        dict[str, Any],
        Field(
            description='Asset manifest for rendering the detailed card, structure defined by the format'
        ),
    ]


class Format(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    accepts_parameters: Annotated[
        list[format_id_parameter.FormatIdParameter] | None,
        Field(
            description='List of parameters this format accepts in format_id. Template formats define which parameters (dimensions, duration, etc.) can be specified when instantiating the format. Empty or omitted means this is a concrete format with fixed parameters.'
        ),
    ] = None
    accessibility: Annotated[
        Accessibility | None,
        Field(
            description='Accessibility posture of this format. Declares the WCAG conformance level that creatives produced by this format will meet.'
        ),
    ] = None
    assets: Annotated[
        list[
            Assets
            | Assets5
            | Assets6
            | Assets7
            | Assets8
            | Assets9
            | Assets10
            | Assets11
            | Assets12
            | Assets13
            | Assets14
            | Assets15
            | Assets16
            | Assets17
        ]
        | None,
        Field(
            description="Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory."
        ),
    ] = None
    delivery: Annotated[
        dict[str, Any] | None,
        Field(description='Delivery method specifications (e.g., hosted, VAST, third-party tags)'),
    ] = None
    description: Annotated[
        str | None,
        Field(
            description='Plain text explanation of what this format does and what assets it requires'
        ),
    ] = None
    example_url: Annotated[
        AnyUrl | None,
        Field(
            description='Optional URL to showcase page with examples and interactive demos of this format'
        ),
    ] = None
    format_card: Annotated[
        FormatCard | None,
        Field(
            description='Optional standard visual card (300x400px) for displaying this format in user interfaces. Can be rendered via preview_creative or pre-generated.'
        ),
    ] = None
    format_card_detailed: Annotated[
        FormatCardDetailed | None,
        Field(
            description='Optional detailed card with carousel and full specifications. Provides rich format documentation similar to ad spec pages.'
        ),
    ] = None
    format_id: Annotated[
        format_id_1.FormatId,
        Field(description='Structured format identifier with agent URL and format name'),
    ]
    name: Annotated[str, Field(description='Human-readable format name')]
    output_format_ids: Annotated[
        list[format_id_1.FormatId] | None,
        Field(
            description='For generative formats: array of format IDs that this format can generate. When a format accepts inputs like brand_manifest and message, this specifies what concrete output formats can be produced (e.g., a generative banner format might output standard image banner formats).'
        ),
    ] = None
    renders: Annotated[
        list[Renders | Renders1] | None,
        Field(
            description='Specification of rendered pieces for this format. Most formats produce a single render. Companion ad formats (video + banner), adaptive formats, and multi-placement formats produce multiple renders. Each render specifies its role and dimensions.',
            min_length=1,
        ),
    ] = None
    reported_metrics: Annotated[
        list[available_metric.AvailableMetric] | None,
        Field(
            description='Metrics this format can produce in delivery reporting. Buyers receive the intersection of format reported_metrics and product available_metrics. If omitted, the format defers entirely to product-level metric declarations.',
            min_length=1,
        ),
    ] = None
    supported_macros: Annotated[
        list[universal_macro.UniversalMacro | str] | None,
        Field(
            description='List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID). Used for validation and developer tooling. See docs/creative/universal-macros.mdx for full documentation.'
        ),
    ] = None
    type: Annotated[
        format_category.FormatCategory | None,
        Field(
            description='DEPRECATED: High-level category for this format. Use the assets array to understand creative requirements instead - it provides precise information about what asset types are needed.'
        ),
    ] = None
