"""
AIS-catcher process manager.
Detects RTL-SDR hardware and manages AIS-catcher.exe.
"""
from __future__ import annotations

import json
import os
import subprocess
import sys
from pathlib import Path

_HERE = Path(__file__).parent
TOOLS_DIR = _HERE.parent.parent / "tools" / "ais-catcher"
EXE_PATH  = TOOLS_DIR / "AIS-catcher.exe"

_process: subprocess.Popen | None = None


def exe_exists() -> bool:
    return EXE_PATH.exists()


def detect_sdr() -> list[dict]:
    """Return list of RTL-SDR devices detected via PowerShell PnP (VID_0BDA)."""
    found = []
    try:
        ps = (
            "Get-PnpDevice -Status OK | "
            "Where-Object { ($_.HardwareID | Out-String) -match 'VID_0BDA' } | "
            "Select-Object "
            "@{N='desc';E={$_.FriendlyName}},"
            "@{N='hw';E={($_.HardwareID | Select-Object -First 1)}} | "
            "ConvertTo-Json -Compress"
        )
        out = subprocess.check_output(
            ["powershell", "-NoProfile", "-NonInteractive", "-Command", ps],
            text=True, timeout=6, stderr=subprocess.DEVNULL,
        ).strip()
        if not out:
            return found
        data = json.loads(out)
        if isinstance(data, dict):
            data = [data]
        for d in (data or []):
            found.append({
                "description": d.get("desc") or "RTL-SDR dongle",
                "hardware_id": d.get("hw") or "",
                "type": "rtl_sdr",
            })
    except Exception as e:
        print(f"[ais-catcher] SDR detect error: {e}")
    return found


def _kill_existing():
    """Kill any stray AIS-catcher processes already running."""
    try:
        subprocess.run(
            ["taskkill", "/F", "/IM", "AIS-catcher.exe"],
            capture_output=True, timeout=5
        )
    except Exception:
        pass


def is_running() -> bool:
    global _process
    if _process is not None and _process.poll() is None:
        return True
    # Also check system-wide (could have been launched externally)
    try:
        out = subprocess.check_output(
            ["tasklist", "/FI", "IMAGENAME eq AIS-catcher.exe", "/NH"],
            text=True, timeout=3, stderr=subprocess.DEVNULL,
        )
        return "AIS-catcher.exe" in out
    except Exception:
        return False


def launch(udp_port: int = 10110, web_port: int = 8100) -> dict:
    """
    Launch AIS-catcher.exe if not already running.
    Returns {"ok": bool, "already_running": bool, "pid": int|None, "error": str|None}
    """
    global _process

    if not exe_exists():
        return {"ok": False, "error": f"AIS-catcher.exe not found at {EXE_PATH}"}

    if is_running():
        return {"ok": True, "already_running": True, "pid": _process.pid if _process else None}

    sdrs = detect_sdr()
    if not sdrs:
        return {"ok": False, "error": "No RTL-SDR device detected"}

    try:
        _kill_existing()
        cmd = [
            str(EXE_PATH),
            "-v", "10",
            "-X",
            "-u", f"127.0.0.1", str(udp_port),
            "-N", str(web_port),
            "PLUGIN_DIR", str(TOOLS_DIR / "plugins"),
        ]
        _process = subprocess.Popen(
            cmd,
            cwd=str(TOOLS_DIR),
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
        )
        return {"ok": True, "already_running": False, "pid": _process.pid}
    except Exception as e:
        return {"ok": False, "error": str(e)}


def stop() -> dict:
    """Stop the managed AIS-catcher process."""
    global _process
    if _process and _process.poll() is None:
        _process.terminate()
        try:
            _process.wait(timeout=4)
        except subprocess.TimeoutExpired:
            _process.kill()
        _process = None
    _kill_existing()
    return {"ok": True}


def status() -> dict:
    sdrs   = detect_sdr()
    running = is_running()
    pid    = _process.pid if (_process and _process.poll() is None) else None
    return {
        "exe_found":  exe_exists(),
        "sdr_devices": sdrs,
        "running":    running,
        "pid":        pid,
    }
