# generated by datamodel-codegen:
#   filename:  config-schema.yaml
#   timestamp: 2025-12-12T07:57:50+00:00

from __future__ import annotations

from enum import Enum
from typing import Literal

from pydantic import BaseModel, ConfigDict, Field, RootModel


class Region(Enum):
    """
    Platform region selection (cn=ModelScope, other=HuggingFace)
    """

    cn = "cn"
    other = "other"


class Metadata(BaseModel):
    version: str = Field(
        ..., examples=["1.0.0", "2.1.3"], pattern="^\\d+\\.\\d+\\.\\d+$"
    )
    """
    Configuration version (semantic versioning)
    """
    region: Region
    """
    Platform region selection (cn=ModelScope, other=HuggingFace)
    """
    cache_dir: str = Field(..., examples=["~/.lumen/models", "/opt/lumen/models"])
    """
    Model cache directory path (supports ~ expansion)
    """


class Mode(Enum):
    """
    Deployment mode
    """

    single = "single"
    hub = "hub"


class Service(RootModel[str]):
    root: str = Field(..., pattern="^[a-z][a-z0-9_]*$")


class Deployment(BaseModel):
    mode: Literal["single"]
    """
    Deployment mode
    """
    service: str = Field(..., pattern="^[a-z][a-z0-9_]*$")
    """
    Service name for single mode (required if mode=single)
    """
    services: list[Service] | None = Field(None, min_length=1)
    """
    Service names for hub mode (required if mode=hub)
    """


class Deployment1(BaseModel):
    mode: Literal["hub"]
    """
    Deployment mode
    """
    service: str | None = Field(None, pattern="^[a-z][a-z0-9_]*$")
    """
    Service name for single mode (required if mode=single)
    """
    services: list[Service] = Field(..., min_length=1)
    """
    Service names for hub mode (required if mode=hub)
    """


class Mdns(BaseModel):
    enabled: bool | None = False
    """
    Enable mDNS service discovery
    """
    service_name: str | None = Field(
        None, examples=["lumen-clip", "lumen-hub"], pattern="^[a-z][a-z0-9-]*$"
    )
    """
    mDNS service name (required if enabled=true)
    """


class Server(BaseModel):
    port: int = Field(..., ge=1024, le=65535)
    """
    gRPC server port
    """
    host: str | None = Field("0.0.0.0", examples=["0.0.0.0", "127.0.0.1", "[::]"])
    """
    Server bind address
    """
    mdns: Mdns | None = None


class Import(BaseModel):
    registry_class: str = Field(
        ...,
        examples=[
            "lumen_clip.service_registry.ClipService",
            "lumen_face.service_registry.FaceService",
        ],
        pattern="^[a-z_][a-z0-9_.]*\\.[A-Z][a-zA-Z0-9]*$",
    )
    """
    Full dotted path to service registry class
    """
    add_to_server: str = Field(
        ...,
        examples=[
            "lumen_clip.proto.ml_service_pb2_grpc.add_InferenceServicer_to_server",
            "lumen_face.proto.ml_service_pb2_grpc.add_FaceServicer_to_server",
        ],
        pattern="^[a-z_][a-z0-9_.]*\\.add_[A-Za-z0-9_]+_to_server$",
    )
    """
    Full dotted path to gRPC add_to_server function
    """


class BackendSettings(BaseModel):
    """
    Optional settings for inference backend configuration.
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    device: str | None = None
    """
    Preferred device ('cuda', 'mps', 'cpu'). If null, auto-detects best available.
    """
    batch_size: int | None = Field(8, ge=1)
    """
    Maximum batch size for inference.
    """
    onnx_providers: list[str] | None = None
    """
    List of ONNX execution providers. If null, uses ONNX Runtime defaults.
    """
    prefer_fp16: bool | None = True
    """
    Whether to prefer FP16 model files over FP32 when available.
    Improves performance on supported hardware.
    """


class Runtime(Enum):
    """
    Model runtime type
    """

    torch = "torch"
    onnx = "onnx"
    rknn = "rknn"


class ModelConfig(BaseModel):
    model: str = Field(..., examples=["ViT-B-32", "CN-CLIP-ViT-B-16", "MobileCLIP-S2"])
    """
    Model repository name
    """
    runtime: Runtime
    """
    Model runtime type
    """
    rknn_device: str | None = Field(
        None, examples=["rk3566", "rk3588"], pattern="^rk\\d+$"
    )
    """
    RKNN device identifier (required if runtime=rknn)
    """
    dataset: str | None = Field(None, examples=["ImageNet_1k", "TreeOfLife-10M"])
    """
    Dataset name for zero-shot classification (optional)
    """


class Services(BaseModel):
    enabled: bool
    """
    Whether to load this service
    """
    package: str = Field(
        ..., examples=["lumen_clip", "lumen_face"], pattern="^[a-z][a-z0-9_]*$"
    )
    """
    Python package name
    """
    import_: Import = Field(..., alias="import")
    backend_settings: BackendSettings | None = None
    models: dict[str, ModelConfig]
    """
    Model configurations (alias → config)
    """


class LumenConfig(BaseModel):
    """
    Unified configuration schema for all Lumen ML services
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    metadata: Metadata
    deployment: Deployment | Deployment1
    server: Server
    services: dict[str, Services]
    """
    Service definitions
    """
