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

from __future__ import annotations

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

from pydantic import BaseModel, ConfigDict, Field, 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 = Field(
        ..., description="Process identifier (e.g., 'web', 'api', 'transcode-worker')"
    )
    intent: Optional[str] = Field(None, description='Human-readable description of process purpose')
    tags: Optional[list[str]] = Field(
        None, description="Categorization tags (e.g., ['worker', 'video'])"
    )
    todo: Optional[list[TodoItem]] = None


class Contract(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    produces: Optional[list] = Field(
        None,
        description="Events this process publishes (e.g., ['video.transcoded', 'thumbnail.generated'])",
    )


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 BackoffStrategy(Enum):
    fixed = 'fixed'
    linear = 'linear'
    exponential = 'exponential'
    fibonacci = 'fibonacci'


class Retry(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    max_attempts: Optional[conint(ge=0, le=100)] = Field(
        None, description='Maximum retry attempts (0 = no retries)'
    )
    delay: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = Field(
        None, description="Initial delay between retries (e.g., '5s', '1m')"
    )
    backoff_strategy: Optional[BackoffStrategy] = Field(None, description='Delay increase strategy')
    max_delay: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = Field(
        None, description='Maximum delay between retries'
    )
    jitter: Optional[bool] = Field(None, description='Add random jitter to prevent thundering herd')
    conditions: Optional[list[str]] = Field(
        None, description="Conditions for retrying (e.g., ['status_code == 500'])"
    )


class RunItem(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class OnFailure(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    retry: Optional[Retry] = Field(
        None, description='Automatic retry configuration for transient failures'
    )
    run: Optional[list[RunItem]] = Field(
        None, description='Actions to run when all retries are exhausted'
    )


class OnSucces(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class Action(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


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 Transition(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    target: str = Field(..., description='Target state name')
    guard: Optional[str] = Field(
        None,
        description="Condition expression that must be true for transition (e.g., 'status == 200')",
    )
    actions: Optional[list[Action]] = Field(
        None, description='Actions to execute during transition'
    )
    inputs: Optional[dict[str, Any]] = Field(
        None, description='Mapping that derives process inputs from the event payload or context.'
    )
    environment: Optional[dict[str, str]] = Field(
        None, description='Environment overrides applied when this transition fires.'
    )
    reliability: Optional[Reliability] = None
    schema_: Optional[str] = Field(
        None,
        alias='schema',
        description='Relative path to the Event schema manifest associated with this transition.',
    )
    schema_ref: Optional[str] = Field(None, description='External reference to the Event schema.')
    produces_event: Optional[str] = Field(
        None, description='Optional event emitted when the transition executes.'
    )


class Type(Enum):
    final = 'final'
    parallel = 'parallel'


class Invoke(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class InvokeItem(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class OnEntryItem(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class OnExitItem(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    name: Optional[str] = None
    uses: Union[
        constr(pattern=r'^(component://|workflow://|process://|library://|knot0/).+'),
        constr(pattern=r'^\.{1,2}/.+$'),
    ]
    with_: Optional[dict[str, Any]] = Field(None, alias='with')


class Retry1(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    max_attempts: Optional[conint(ge=0, le=100)] = None
    delay: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = None
    backoff_strategy: Optional[BackoffStrategy] = None
    max_delay: Optional[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$')] = None
    jitter: Optional[bool] = None
    conditions: Optional[list[str]] = None


class OnFailure1(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    retry: Optional[Retry1] = None
    run: Optional[list[RunItem]] = Field(None, min_length=1)


class State(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    states: Optional[dict[str, State]] = Field(
        None, description='Nested child states (for hierarchical state machines)'
    )
    initial: Optional[str] = Field(
        None, description='Initial child state name (for hierarchical states)'
    )
    type: Optional[Type] = Field(
        None,
        description="State type: 'final' = terminal state, 'parallel' = concurrent child states",
    )
    on: Optional[
        dict[constr(pattern=r'^[A-Za-z0-9_.:-]+$'), Union[Transition, list[Transition]]]
    ] = Field(None, description='Event handlers - map event names to transitions')
    after: Optional[dict[constr(pattern=r'^(?:[0-9]+(?:\.[0-9]+)?)(ms|s|m|h|d)$'), Transition]] = (
        Field(None, description='Delayed transitions - automatically transition after timeout')
    )
    invoke: Optional[Union[Invoke, list[InvokeItem]]] = Field(
        None,
        description="Component or service to invoke while in this state (REQUIRED for persistent services in 'Running' state)",
    )
    on_entry: Optional[list[OnEntryItem]] = Field(
        None, description='Actions to execute when entering this state', min_length=1
    )
    on_exit: Optional[list[OnExitItem]] = Field(
        None, description='Actions to execute when exiting this state', min_length=1
    )
    on_failure: Optional[OnFailure1] = Field(
        None, description='State-level failure handling (overrides process-level on_failure)'
    )


class Trigger(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    event: constr(pattern=r'^[a-z0-9]+(?:\.[a-z0-9]+)*$') = Field(
        ...,
        description="Canonical event name that triggers this process (lowercase dot-notation: 'video.uploaded', 'user.created').",
    )
    target_state: Optional[str] = Field(
        None, description='State name to transition to when the event is received.'
    )
    schema_: Optional[str] = Field(
        None,
        alias='schema',
        description="Relative path to the Event schema manifest (e.g., './events/video-uploaded').",
    )
    schema_ref: Optional[str] = Field(
        None, description='External reference to the Event schema (e.g., registry URL).'
    )
    inputs: Optional[dict[str, Any]] = Field(
        None,
        description='Mapping that derives process inputs from the event payload using JSON Pointer or expression syntax.',
    )
    environment: Optional[dict[str, str]] = Field(
        None,
        description='Environment overrides injected when this trigger fires (e.g., narrow `KNOT0_ALLOWED_*`).',
    )
    reliability: Optional[Reliability] = None
    filters: Optional[list[str]] = Field(
        None,
        description="Optional filters to match specific event payloads (e.g., ['payload.size > 1000000']).",
    )


class Statechart(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    initial: str = Field(
        ...,
        description="Initial state name (e.g., 'Running' for services, 'AwaitingEvent' for workers)",
    )
    context: Optional[dict[str, Any]] = Field(
        None, description='Global state machine context available to all states'
    )
    triggers: Optional[list[Trigger]] = Field(
        None,
        description='Optional explicit trigger declarations. Acts as default wiring when the process is deployed standalone; Component bindings override these settings when both are present.',
    )
    states: dict[str, State] = Field(
        ...,
        description="State machine states. Event names declared in each state's 'on' map are treated as subscriptions when the trigger map is built.",
    )


class Body(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    statechart: Statechart = Field(
        ..., description='State machine definition - controls process lifecycle and behavior'
    )
    view: Optional[dict[str, Any]] = Field(
        None, description='UI rendering configuration (deprecated, rarely used)'
    )


class Process(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    kind: Literal['Process']
    schema_version: str
    metadata: Metadata
    contract: Optional[Contract] = None
    tests: Optional[list[Test]] = Field(
        None, description='Unit and integration tests for this process'
    )
    body: Body
    on_failure: Optional[OnFailure] = Field(
        None, description='Process-level failure handling and retry configuration'
    )
    on_success: Optional[list[OnSucces]] = Field(
        None,
        description='Actions to run after successful process completion (e.g., publish completion event)',
    )


State.model_rebuild()
