"""CLI for Synapse sensor emulators."""

from __future__ import annotations

import argparse
import logging
import signal
import threading
import time

from sensor_emulator.lidar_collector import main as lidar_collector_main
from sensor_emulator.mavlink import MavlinkEmulator, MavlinkTelemetryConfig
from sensor_emulator.radar import RadarEmulator, RadarEmulatorConfig


def _configure_logging(verbose: bool) -> None:
    logging.basicConfig(
        level=logging.DEBUG if verbose else logging.INFO,
        format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
    )


def _build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Run Synapse-compatible sensor emulators")
    parser.add_argument("--verbose", action="store_true", help="Enable debug logging")

    subparsers = parser.add_subparsers(dest="command", required=True)

    radar_parser = subparsers.add_parser("radar", help="Run radar emulator")
    radar_parser.add_argument("--host", default="127.0.0.1")
    radar_parser.add_argument("--ctrl-port", type=int, default=8100)
    radar_parser.add_argument("--data-port", type=int, default=8101)
    radar_parser.add_argument("--n-samples", type=int, default=511)
    radar_parser.add_argument("--frame-interval", type=float, default=0.02)

    mavlink_parser = subparsers.add_parser("mavlink", help="Run MAVLink emulator")
    mavlink_parser.add_argument("--host", default="127.0.0.1")
    mavlink_parser.add_argument("--port", type=int, default=14550)
    mavlink_parser.add_argument("--stream-hz", type=float, default=10.0)

    all_parser = subparsers.add_parser("all", help="Run radar + MAVLink emulators")
    all_parser.add_argument("--host", default="127.0.0.1")
    all_parser.add_argument("--ctrl-port", type=int, default=8100)
    all_parser.add_argument("--data-port", type=int, default=8101)
    all_parser.add_argument("--radar-n-samples", type=int, default=511)
    all_parser.add_argument("--radar-frame-interval", type=float, default=0.02)
    all_parser.add_argument("--mavlink-port", type=int, default=14550)
    all_parser.add_argument("--mavlink-stream-hz", type=float, default=10.0)

    lidar_parser = subparsers.add_parser(
        "lidar-collector",
        help="Run LiDAR collector emulator binary interface",
    )
    lidar_parser.add_argument("config_path", nargs="?")
    lidar_parser.add_argument("--rate-hz", type=float, default=20.0)
    lidar_parser.add_argument("--samples-per-cycle", type=int, default=32)

    return parser


def _wait_until_interrupted(stop: threading.Event) -> None:
    while not stop.is_set():
        time.sleep(0.2)


def main(argv: list[str] | None = None) -> int:
    parser = _build_parser()
    args = parser.parse_args(argv)

    _configure_logging(args.verbose)

    if args.command == "lidar-collector":
        collector_args: list[str] = []
        if args.config_path:
            collector_args.append(args.config_path)
        collector_args.extend([
            "--rate-hz",
            str(args.rate_hz),
            "--samples-per-cycle",
            str(args.samples_per_cycle),
        ])
        return lidar_collector_main(collector_args)

    stop_event = threading.Event()

    def _on_signal(signum, frame):  # type: ignore[no-untyped-def]
        del frame
        logging.getLogger(__name__).info("Received signal %s, stopping", signum)
        stop_event.set()

    signal.signal(signal.SIGINT, _on_signal)
    signal.signal(signal.SIGTERM, _on_signal)

    radar_emulator = None
    mavlink_emulator = None

    try:
        if args.command in {"radar", "all"}:
            radar_emulator = RadarEmulator(
                RadarEmulatorConfig(
                    host=args.host,
                    ctrl_port=args.ctrl_port,
                    data_port=args.data_port,
                    n_samples=getattr(args, "n_samples", getattr(args, "radar_n_samples", 511)),
                    frame_interval_s=getattr(
                        args,
                        "frame_interval",
                        getattr(args, "radar_frame_interval", 0.02),
                    ),
                )
            )
            radar_emulator.start()

        if args.command in {"mavlink", "all"}:
            mavlink_emulator = MavlinkEmulator(
                MavlinkTelemetryConfig(
                    host=args.host,
                    port=getattr(args, "port", getattr(args, "mavlink_port", 14550)),
                    stream_hz=getattr(
                        args,
                        "stream_hz",
                        getattr(args, "mavlink_stream_hz", 10.0),
                    ),
                )
            )
            mavlink_emulator.start()

        _wait_until_interrupted(stop_event)
    finally:
        if mavlink_emulator is not None:
            mavlink_emulator.stop()
        if radar_emulator is not None:
            radar_emulator.stop()

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
