"""
Agent manifest execution models.

Defines execution configuration, inspired by Prefect, Dagster, and Temporal patterns.
"""

from enum import Enum

from pydantic import BaseModel, Field

from typing import Literal, Optional


class ExecutionMode(str, Enum):
    """Execution mode for agent."""

    SYNC = "sync"
    ASYNC = "async"
    STREAMING = "streaming"


class RetryPolicy(BaseModel):
    """
    Retry policy configuration (Temporal-inspired).

    Defines how failed executions should be retried.
    """

    max_attempts: int = Field(3, ge=1, description="Maximum retry attempts")
    initial_interval: str = Field("1s", description="Initial retry interval")
    max_interval: str = Field("30s", description="Maximum retry interval")
    backoff_coefficient: float = Field(2.0, ge=1.0, description="Backoff multiplier")
    retryable_errors: list[str] = Field(
        default_factory=list,
        description="Error types that should be retried",
    )
    non_retryable_errors: list[str] = Field(
        default_factory=list,
        description="Error types that should not be retried",
    )


class ConcurrencyConfig(BaseModel):
    """Concurrency control configuration."""

    max_concurrent: int = Field(10, ge=1, description="Maximum parallel executions")
    queue_behavior: Literal["wait", "reject", "drop_oldest"] = Field(
        "wait",
        description="Behavior when concurrency limit is reached",
    )


class ErrorHandlingStrategy(str, Enum):
    """Error handling strategy."""

    FAIL = "fail"
    RETRY = "retry"
    DEFAULT_VALUE = "default-value"
    FAIL_BRANCH = "fail-branch"


class FallbackConfig(BaseModel):
    """Fallback configuration for error handling."""

    type: Literal["default-value", "agent", "function"] = Field(
        ...,
        description="Fallback type",
    )
    value: Optional[str] = Field(None, description="Default value (for default-value type)")
    agent: Optional[str] = Field(None, description="Fallback agent reference (for agent type)")
    function: Optional[str] = Field(None, description="Fallback function (for function type)")


class ErrorHandlingConfig(BaseModel):
    """
    Error handling configuration (Dify-inspired).

    Defines how errors should be handled during execution.
    """

    strategy: ErrorHandlingStrategy = Field(
        ErrorHandlingStrategy.FAIL,
        description="Error handling strategy",
    )
    fallback: Optional[FallbackConfig] = Field(None, description="Fallback configuration")


class Hook(BaseModel):
    """
    Lifecycle hook definition.

    Hooks are called at specific points during agent execution.
    """

    name: str = Field(..., description="Hook name")
    handler: str = Field(
        ...,
        description="Handler reference (e.g., ./hooks/validate.py:validate_input)",
    )
    config: dict[str, object] = Field(
        default_factory=dict,
        description="Hook configuration",
    )


class HooksConfig(BaseModel):
    """Lifecycle hooks configuration."""

    before_execution: list[Hook] = Field(
        default_factory=list,
        description="Hooks called before execution",
    )
    after_execution: list[Hook] = Field(
        default_factory=list,
        description="Hooks called after successful execution",
    )
    on_error: list[Hook] = Field(
        default_factory=list,
        description="Hooks called on error",
    )


class ExecutionConfig(BaseModel):
    """
    Execution configuration block.

    Defines how the agent should be executed, including timeouts,
    retries, concurrency, and error handling.
    """

    # Execution mode
    mode: ExecutionMode = Field(ExecutionMode.SYNC, description="Execution mode")

    # Timeout
    timeout: Optional[str] = Field(None, description="Maximum execution time (e.g., 5m, 30s)")

    # Retry policy
    retries: Optional[RetryPolicy] = Field(None, description="Retry policy")

    # Concurrency control
    concurrency: Optional[ConcurrencyConfig] = Field(None, description="Concurrency configuration")

    # Error handling
    error_handling: Optional[ErrorHandlingConfig] = Field(
        None,
        description="Error handling configuration",
    )

    # Lifecycle hooks
    hooks: Optional[HooksConfig] = Field(None, description="Lifecycle hooks")
