"""High-level orchestration service for configuring and querying LibreVNA."""

from __future__ import annotations

from dataclasses import dataclass, field

from python_app.hardware_full.librevna_backends import LibreVnaBackend, MockLibreVnaBackend, NativeLibreVnaBackend
from python_app.hardware_full.librevna_driver.models import SweepResult
from python_app.models.run_config_model import RadarSweepModel


@dataclass(slots=True)
class LibreVnaService:
    """Provide stable API for GUI/workflows while hiding backend details."""

    serial: str | None = None
    strict_protocol_version: int = 14
    backend_mode: str = "auto"
    _driver_available: bool = field(init=False, default=False, repr=False)
    _backend: LibreVnaBackend | None = field(init=False, default=None, repr=False)
    _using_mock_backend: bool = field(init=False, default=False, repr=False)

    def __post_init__(self) -> None:
        """Initialize selected backend and detect driver availability."""
        self._driver_available = False
        self._backend = None
        self._using_mock_backend = False

        mode = self.backend_mode.strip().lower()
        if mode not in {"auto", "native", "mock"}:
            raise ValueError(f"Unsupported LibreVnaService backend mode: {self.backend_mode}")

        if mode == "mock":
            self._backend = MockLibreVnaBackend()
            self._using_mock_backend = True
            return

        try:
            self._backend = NativeLibreVnaBackend(
                serial=self.serial,
                strict_protocol_version=self.strict_protocol_version,
            )
            self._driver_available = True
        except Exception:
            if mode == "native":
                raise
            self._backend = MockLibreVnaBackend()
            self._using_mock_backend = True

    @property
    def driver_available(self) -> bool:
        """Return `True` when native Python LibreVNA driver is available."""
        return self._driver_available

    def open(self) -> None:
        """Open backend resources."""
        if not self._driver_available and not self._using_mock_backend:
            return
        if self._backend is None:
            return
        self._backend.open()

    def close(self) -> None:
        """Close backend resources."""
        if self._backend is None:
            return
        self._backend.close()

    def configure(self, sweep: RadarSweepModel) -> None:
        """Apply sweep settings to active backend."""
        if self._backend is None:
            raise RuntimeError("LibreVNA backend is not initialized")
        self._backend.configure(sweep)

    def read_device_limits(self) -> dict[str, float | int]:
        """Read native device limits from connected LibreVNA."""
        if not self._driver_available:
            raise RuntimeError("LibreVNA Python driver is not available")
        if self._backend is None:
            raise RuntimeError("LibreVNA backend is not initialized")

        opened_here = not self._backend.is_open
        try:
            if opened_here:
                self.open()
            return self._backend.read_device_limits()
        finally:
            if opened_here:
                self.close()

    def acquire(self) -> SweepResult:
        """Acquire one sweep with all available traces from active backend."""
        if self._backend is None:
            raise RuntimeError("LibreVNA backend is not initialized")
        if self._using_mock_backend and not self._driver_available and self.backend_mode != "mock":
            raise RuntimeError("Device not found")
        return self._backend.acquire()
