"""MQTT LED client — publishes pixel data to an MQTT topic."""

import json
from typing import List, Tuple, Union

import numpy as np

from wled_controller.core.devices.led_client import DeviceHealth, LEDClient
from wled_controller.utils import get_logger

logger = get_logger(__name__)

# Singleton reference — injected from main.py at startup
_mqtt_service = None


def set_mqtt_service(service) -> None:
    global _mqtt_service
    _mqtt_service = service


def get_mqtt_service():
    return _mqtt_service


def parse_mqtt_url(url: str) -> str:
    """Extract topic from an mqtt:// URL.

    Format: mqtt://topic/path  (broker connection is global via config)
    """
    if url.startswith("mqtt://"):
        return url[7:]
    return url


class MQTTLEDClient(LEDClient):
    """Publishes JSON pixel data to an MQTT topic via the shared service."""

    def __init__(self, url: str, led_count: int = 0, **kwargs):
        self._topic = parse_mqtt_url(url)
        self._led_count = led_count
        self._connected = False

    async def connect(self) -> bool:
        svc = _mqtt_service
        if svc is None or not svc.is_enabled:
            raise ConnectionError("MQTT service not available")
        if not svc.is_connected:
            raise ConnectionError("MQTT service not connected to broker")
        self._connected = True
        return True

    async def close(self) -> None:
        self._connected = False

    @property
    def is_connected(self) -> bool:
        return self._connected and _mqtt_service is not None and _mqtt_service.is_connected

    async def send_pixels(
        self,
        pixels: Union[List[Tuple[int, int, int]], np.ndarray],
        brightness: int = 255,
    ) -> bool:
        svc = _mqtt_service
        if svc is None or not svc.is_connected:
            return False

        if isinstance(pixels, np.ndarray):
            pixel_list = pixels.tolist()
        else:
            pixel_list = list(pixels)

        payload = json.dumps({
            "pixels": pixel_list,
            "brightness": brightness,
            "led_count": len(pixel_list),
        })

        await svc.publish(self._topic, payload, retain=False, qos=0)
        return True

    @classmethod
    async def check_health(
        cls,
        url: str,
        http_client,
        prev_health=None,
    ) -> DeviceHealth:
        from datetime import datetime, timezone
        svc = _mqtt_service
        if svc is None or not svc.is_enabled:
            return DeviceHealth(online=False, error="MQTT disabled", last_checked=datetime.now(timezone.utc))
        return DeviceHealth(
            online=svc.is_connected,
            last_checked=datetime.now(timezone.utc),
            error=None if svc.is_connected else "MQTT broker disconnected",
        )
