from enum import Enum
from typing import Optional, Union

from pydantic import Field, field_validator

from ..base import FrigateBaseModel
from ..env import EnvString
from .objects import DEFAULT_TRACKED_OBJECTS

__all__ = ["OnvifConfig", "PtzAutotrackConfig", "ZoomingModeEnum"]


class ZoomingModeEnum(str, Enum):
    disabled = "disabled"
    absolute = "absolute"
    relative = "relative"


class PtzAutotrackConfig(FrigateBaseModel):
    enabled: bool = Field(
        default=False,
        title="Enable Autotracking",
        description="Enable or disable automatic PTZ camera tracking of detected objects.",
    )
    calibrate_on_startup: bool = Field(
        default=False,
        title="Calibrate on start",
        description="Measure PTZ motor speeds on startup to improve tracking accuracy. Frigate will update config with movement_weights after calibration.",
    )
    zooming: ZoomingModeEnum = Field(
        default=ZoomingModeEnum.disabled,
        title="Zoom mode",
        description="Control zoom behavior: disabled (pan/tilt only), absolute (most compatible), or relative (concurrent pan/tilt/zoom).",
    )
    zoom_factor: float = Field(
        default=0.3,
        title="Zoom factor",
        description="Control zoom level on tracked objects. Lower values keep more scene in view; higher values zoom in closer but may lose tracking. Values between 0.1 and 0.75.",
        ge=0.1,
        le=0.75,
    )
    track: list[str] = Field(
        default=DEFAULT_TRACKED_OBJECTS,
        title="Tracked objects",
        description="List of object types that should trigger autotracking.",
    )
    required_zones: list[str] = Field(
        default_factory=list,
        title="Required zones",
        description="Objects must enter one of these zones before autotracking begins.",
    )
    return_preset: str = Field(
        default="home",
        title="Return preset",
        description="ONVIF preset name configured in camera firmware to return to after tracking ends.",
    )
    timeout: int = Field(
        default=10,
        title="Return timeout",
        description="Wait this many seconds after losing tracking before returning camera to preset position.",
    )
    movement_weights: Optional[Union[str, list[str]]] = Field(
        default_factory=list,
        title="Movement weights",
        description="Calibration values automatically generated by camera calibration. Do not modify manually.",
    )
    enabled_in_config: Optional[bool] = Field(
        default=None,
        title="Original autotrack state",
        description="Internal field to track whether autotracking was enabled in configuration.",
    )

    @field_validator("movement_weights", mode="before")
    @classmethod
    def validate_weights(cls, v):
        if v is None:
            return None

        if isinstance(v, str):
            weights = list(map(str, map(float, v.split(","))))
        elif isinstance(v, list):
            weights = [str(float(val)) for val in v]
        else:
            raise ValueError("Invalid type for movement_weights")

        if len(weights) != 6:
            raise ValueError(
                "movement_weights must have exactly 6 floats, remove this line from your config and run autotracking calibration"
            )

        return weights


class OnvifConfig(FrigateBaseModel):
    host: EnvString = Field(
        default="",
        title="ONVIF host",
        description="Host (and optional scheme) for the ONVIF service for this camera.",
    )
    port: int = Field(
        default=8000,
        title="ONVIF port",
        description="Port number for the ONVIF service.",
    )
    user: Optional[EnvString] = Field(
        default=None,
        title="ONVIF username",
        description="Username for ONVIF authentication; some devices require admin user for ONVIF.",
    )
    password: Optional[EnvString] = Field(
        default=None,
        title="ONVIF password",
        description="Password for ONVIF authentication.",
    )
    tls_insecure: bool = Field(
        default=False,
        title="Disable TLS verify",
        description="Skip TLS verification and disable digest auth for ONVIF (unsafe; use in safe networks only).",
    )
    profile: Optional[str] = Field(
        default=None,
        title="ONVIF profile",
        description="Specific ONVIF media profile to use for PTZ control, matched by token or name. If not set, the first profile with valid PTZ configuration is selected automatically.",
    )
    autotracking: PtzAutotrackConfig = Field(
        default_factory=PtzAutotrackConfig,
        title="Autotracking",
        description="Automatically track moving objects and keep them centered in the frame using PTZ camera movements.",
    )
    ignore_time_mismatch: bool = Field(
        default=False,
        title="Ignore time mismatch",
        description="Ignore time synchronization differences between camera and Frigate server for ONVIF communication.",
    )
