# generated by datamodel-codegen:
#   filename:  Component.json

from __future__ import annotations

from enum import Enum
from typing import Any, Literal, Optional, Union

from pydantic import BaseModel, ConfigDict, Field, RootModel, conint, constr


class Status(Enum):
    pending = 'pending'
    in_progress = 'in-progress'
    done = 'done'
    blocked = 'blocked'


class TodoItem(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    description: str
    status: Status
    owner: Optional[str] = None
    tags: Optional[list[str]] = None
    link: Optional[str] = None


class Metadata(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    intent: Optional[str] = None
    version: Optional[str] = None
    tags: Optional[list[str]] = None
    todo: Optional[list[TodoItem]] = None


class Platform(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    minimum: Optional[str] = None
    maximum: Optional[str] = None


class Requires(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    features: Optional[list[str]] = None
    capabilities: Optional[list[str]] = None
    platform: Optional[Platform] = None


class Capabilities(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    required: Optional[list[str]] = None
    optional: Optional[list[str]] = None


class Secret(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    mount_path: str
    provider: Optional[str] = None


class Network(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    egress: Optional[list[dict[str, Any]]] = None
    ingress: Optional[list[dict[str, Any]]] = None


class Resources(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    memory: Optional[str] = None
    cpu: Optional[str] = None
    timeout: Optional[str] = None


class Permissions(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    capabilities: Optional[Capabilities] = None
    secrets: Optional[list[Secret]] = None
    network: Optional[Network] = None
    resources: Optional[Resources] = None


class Type(Enum):
    counter = 'counter'
    histogram = 'histogram'
    gauge = 'gauge'
    summary = 'summary'


class Metric(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    type: Type
    intent: Optional[str] = None
    labels: Optional[list[str]] = None
    buckets: Optional[list[float]] = None
    quantiles: Optional[list[float]] = None


class Alert(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    metric: str
    condition: str
    severity: Optional[str] = None
    notify: Optional[list[str]] = None


class Telemetry(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    metrics: Optional[list[Metric]] = None
    alerts: Optional[list[Alert]] = None


class Load(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    duration: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = None
    concurrency: Optional[conint(ge=1)] = None
    requests_per_second: Optional[float] = None
    ramp_up: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = None


class ExpectItem(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    metric: str
    threshold: str
    critical: Optional[bool] = None
    warning: Optional[str] = None


class Benchmark(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    scenario: str
    description: Optional[str] = None
    load: Load
    expect: list[ExpectItem]


class Tests(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    scenario: str
    run: Optional[str] = None
    with_: Optional[dict[str, Any]] = Field(None, alias='with')
    expect: Optional[list[str]] = None
    timeout_seconds: Optional[conint(ge=1)] = Field(
        None, description='Optional per-scenario timeout in seconds'
    )
    services: Optional[list[str]] = Field(
        None, description="Logical services this test exercises (e.g. ['users','orders'])"
    )


class TestCase(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: str
    inputs: Optional[dict[str, Any]] = None
    expected_outputs: Optional[dict[str, Any]] = None
    assertions: Optional[list[dict[str, Any]]] = None


class ComponentTestScenario(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: str
    description: Optional[str] = None
    test_type: Optional[str] = None
    tags: Optional[list[str]] = None
    test_cases: list[TestCase]


class Event1(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    description: Optional[str] = None
    version: Optional[str] = None
    schema_: str = Field(..., alias='schema')
    schema_ref: Optional[str] = None


class Event2(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    description: Optional[str] = None
    version: Optional[str] = None
    schema_: Optional[str] = Field(None, alias='schema')
    schema_ref: str


class Event(RootModel[Union[Event1, Event2]]):
    root: Union[Event1, Event2]


class BackoffStrategy(Enum):
    fixed = 'fixed'
    linear = 'linear'
    exponential = 'exponential'
    fibonacci = 'fibonacci'


class Reliability(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    retries: Optional[conint(ge=0)] = None
    backoff_strategy: Optional[BackoffStrategy] = None
    base_delay_ms: Optional[conint(ge=0)] = None
    max_delay_ms: Optional[conint(ge=0)] = None
    dead_letter_queue: Optional[bool] = None


class Type1(Enum):
    webhook = 'webhook'
    event = 'event'
    schedule = 'schedule'
    mqtt = 'mqtt'
    internal = 'internal'


class Trigger(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    type: Type1
    path: Optional[str] = None
    method: Optional[str] = None
    cron: Optional[str] = None
    topic: Optional[str] = None
    event: Optional[str] = None
    produces_event: Optional[str] = None
    schema_: Optional[str] = Field(None, alias='schema')
    authentication: Optional[dict[str, Any]] = None
    reliability: Optional[Reliability] = None
    description: Optional[str] = None
    provider: Optional[str] = None


class Type2(Enum):
    http = 'http'
    grpc = 'grpc'


class InterfaceEndpoint(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    type: Type2
    path: str
    method: Optional[str] = None
    description: Optional[str] = None
    authentication: Optional[dict[str, Any]] = None


class Binding1(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: Optional[str] = None
    trigger: str
    process: str
    inputs: Optional[dict[str, Any]] = None
    reliability: Optional[Reliability] = None


class Binding(RootModel[Binding1]):
    root: Binding1


class Runner(Enum):
    python = 'python'
    wasm_polyglot = 'wasm-polyglot'
    docker = 'docker'
    docker_job = 'docker-job'
    browser = 'browser'


class Build(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    context: Optional[str] = Field(
        None,
        description="Docker build context path. Resolved component-first: if it resolves under 'components/...', the orchestration builder uses that as the build root; otherwise process-rooted behaviour is used for backward compatibility.",
    )
    dockerfile: Optional[str] = Field(
        None, description='Relative path to Dockerfile within the build context.'
    )
    target: Optional[str] = Field(None, description='Optional Docker build target stage.')


class Run(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    build: Optional[Build] = Field(
        None, description='Docker build configuration when runner=docker.'
    )
    handler: Optional[str] = Field(
        None, description="Handler or module entrypoint (e.g., 'main.py', 'src/app.py')."
    )
    command: Optional[Union[str, list[str]]] = Field(
        None, description='Override container command used at runtime.'
    )


class Dependencies(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    file: Optional[str] = None


class RunItem(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: str
    uses: str
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class OnFailure(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    retry: Optional[Reliability] = None
    run: Optional[list[RunItem]] = None


class OnSucces(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: str
    uses: str
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class Test(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    scenario: str
    run: Optional[str] = None
    with_: Optional[dict[str, Any]] = Field(None, alias='with')
    expect: Optional[list[str]] = None
    timeout_seconds: Optional[conint(ge=1)] = Field(
        None, description='Optional per-scenario timeout in seconds'
    )
    services: Optional[list[str]] = Field(
        None, description="Logical services this test exercises (e.g. ['users','orders'])"
    )


class Entrypoint(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    name: str
    runner: Runner
    run: Optional[Union[str, Run]] = Field(
        None,
        description='Execution configuration. Either a simple handler string or an object with build/command/etc.',
    )
    description: Optional[str] = None
    dependencies: Optional[Dependencies] = None
    environment: Optional[dict[str, Any]] = None
    inputs: Optional[dict[str, Any]] = None
    outputs: Optional[dict[str, Any]] = None
    reliability: Optional[Reliability] = None
    on_failure: Optional[OnFailure] = None
    on_success: Optional[list[OnSucces]] = None
    tests: Optional[list[Test]] = None
    telemetry: Optional[dict[str, Any]] = None
    resources: Optional[dict[str, Any]] = None


class Interface(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    triggers: list[Trigger]
    endpoints: Optional[list[InterfaceEndpoint]] = None
    inputs: Optional[dict[str, Any]] = None
    outputs: Optional[dict[str, Any]] = None
    resources: Optional[dict[str, Any]] = None


class Interface1(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    triggers: Optional[list[Trigger]] = None
    endpoints: list[InterfaceEndpoint]
    inputs: Optional[dict[str, Any]] = None
    outputs: Optional[dict[str, Any]] = None
    resources: Optional[dict[str, Any]] = None


class Component(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    kind: Literal['Component']
    schema_version: str
    metadata: Metadata
    requires: Optional[Requires] = None
    events: Optional[list[Event]] = Field(
        None, description='Catalog of events this component can produce'
    )
    interface: Optional[Union[Interface, Interface1]] = Field(
        None, description='Public entrypoints (triggers/endpoints) that can invoke the component'
    )
    bindings: Optional[list[Binding]] = Field(
        None, description='Wiring between interface triggers and internal processes'
    )
    entrypoint: Optional[Entrypoint] = Field(
        None, description='Single entrypoint shorthand; normalized to entrypoints[0]'
    )
    entrypoints: Optional[list[Entrypoint]] = Field(
        None, description='Component execution entrypoints', min_length=1
    )
    permissions: Optional[Permissions] = None
    telemetry: Optional[Telemetry] = None
    benchmarks: Optional[list[Benchmark]] = None
    tests: Optional[list[Union[Tests, ComponentTestScenario]]] = Field(
        None,
        description='Component-level tests. Supports both simple testCase (scenario/run/with/expect) and richer v2 scenarios (name/test_type/test_cases).',
    )
    compute: Optional[Union[str, dict[str, Any]]] = None
    documentation: Optional[dict[str, Any]] = None
