"""ESP-NOW device provider — ultra-low-latency LED control via ESP32 gateway."""

from typing import List

from wled_controller.core.devices.led_client import (
    DeviceHealth,
    DiscoveredDevice,
    LEDClient,
    LEDDeviceProvider,
)
from wled_controller.core.devices.espnow_client import ESPNowClient
from wled_controller.utils import get_logger

logger = get_logger(__name__)


class ESPNowDeviceProvider(LEDDeviceProvider):
    """Provider for ESP-NOW LED devices via serial ESP32 gateway.

    URL = serial port of the gateway ESP32 (e.g. COM3, /dev/ttyUSB0).
    Each device represents one remote ESP32 peer identified by MAC address.
    Multiple devices can share the same gateway (serial port).
    """

    @property
    def device_type(self) -> str:
        return "espnow"

    @property
    def capabilities(self) -> set:
        return {"manual_led_count", "health_check"}

    def create_client(self, url: str, **kwargs) -> LEDClient:
        return ESPNowClient(
            url,
            led_count=kwargs.get("led_count", 0),
            baud_rate=kwargs.get("baud_rate", 921600),
            espnow_peer_mac=kwargs.get("espnow_peer_mac", "FF:FF:FF:FF:FF:FF"),
            espnow_channel=kwargs.get("espnow_channel", 1),
        )

    async def check_health(self, url: str, http_client, prev_health=None) -> DeviceHealth:
        return await ESPNowClient.check_health(url, http_client, prev_health)

    async def validate_device(self, url: str) -> dict:
        """Validate serial port is accessible. LED count is manual."""
        try:
            import serial as pyserial

            s = pyserial.Serial(url, timeout=0.5)
            s.close()
        except ImportError:
            raise ValueError("pyserial is required for ESP-NOW devices: pip install pyserial")
        except Exception as e:
            raise ValueError(f"Cannot open serial port {url}: {e}")
        return {}

    async def discover(self, timeout: float = 3.0) -> List[DiscoveredDevice]:
        """Discover available serial ports that could be ESP32 gateways."""
        try:
            import serial.tools.list_ports

            ports = serial.tools.list_ports.comports()
            results = []
            for port in ports:
                # Look for ESP32 USB descriptors
                desc = (port.description or "").lower()
                vid = port.vid or 0
                # Common ESP32 USB VIDs: Espressif (0x303A), Silicon Labs CP210x (0x10C4),
                # FTDI (0x0403), WCH CH340 (0x1A86)
                esp_vids = {0x303A, 0x10C4, 0x0403, 0x1A86}
                if vid in esp_vids or "cp210" in desc or "ch340" in desc or "esp" in desc:
                    results.append(
                        DiscoveredDevice(
                            name=f"ESP-NOW Gateway ({port.description})",
                            url=port.device,
                            device_type="espnow",
                            ip="",
                            mac="",
                            led_count=None,
                            version=None,
                        )
                    )
            return results
        except ImportError:
            return []
