"""Factory for matrix-mode (multi-port) radar acquisition services.

Matrix radars acquire the full virtual switch matrix per call via
``acquire_collection`` instead of one combo per ``acquire`` like single-radar
services. The supported models are LibreVNA in synchronized multi-device mode
and the PLANAR SN9000 multi-port analyzer.

Service implementations are imported lazily so a config that targets one
model does not pull in transport dependencies (libusb, pyvisa, etc.) needed
only by the other model.
"""

from __future__ import annotations

from typing import Protocol

from python_app.models.dataset_model import SweepCollection
from python_app.models.run_config_model import RadarSweepModel, RunConfigModel


class MatrixRadarService(Protocol):
    """Common API for radars that emit a full combo matrix per acquisition."""

    def open(self) -> None:
        """Open hardware connections."""

    def close(self) -> None:
        """Close hardware connections."""

    def configure(self, sweep: RadarSweepModel) -> None:
        """Apply sweep settings to the radar."""

    def acquire_collection(self, collection_id: int = 1) -> SweepCollection:
        """Acquire one complete virtual switch matrix in canonical combo order."""

    def recover(self) -> None:
        """Reconnect to the radar after a transient acquisition failure."""


def create_matrix_radar_service(config: RunConfigModel) -> MatrixRadarService:
    """Create the matrix radar service implementation for the active config."""
    if not config.is_matrix_radar:
        raise RuntimeError("matrix radar service factory requires a matrix-mode radar.model")

    model = config.radar.model
    if model == RunConfigModel.LIBREVNA_MULTI_MODEL:
        from python_app.hardware_full.multi_device_service import MultiDeviceLibreVnaService

        return MultiDeviceLibreVnaService(
            master_serial=config.radar.serial,
            slave_serials=list(config.radar.multi_device.slave_serials),
            force_external_reference=config.radar.multi_device.force_external_reference,
            recovery_attempts=config.radar.multi_device.recovery_attempts,
            backend_mode=config.radar.driver_mode,
        )

    if model == RunConfigModel.SN9000_MODEL:
        if config.radar.driver_mode != "native":
            raise RuntimeError("SN9000 requires radar.driver_mode='native'")
        from python_app.hardware_full.sn9000_service import Sn9000Service

        return Sn9000Service(
            host=config.radar.remote_host,
            port=config.radar.remote_port,
        )

    raise RuntimeError(f"Unsupported matrix radar model: {model}")
