"""Heartbeats for Broadlink devices."""

import datetime as dt
import logging

import broadlink as blk

from homeassistant.const import CONF_HOST
from homeassistant.core import CALLBACK_TYPE, HomeAssistant
from homeassistant.helpers import event

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)


class BroadlinkHeartbeat:
    """Manages heartbeats in the Broadlink integration.

    Some devices reboot when they cannot reach the cloud. This mechanism
    feeds their watchdog timers so they can be used offline.
    """

    HEARTBEAT_INTERVAL = dt.timedelta(minutes=2)

    def __init__(self, hass: HomeAssistant) -> None:
        """Initialize the heartbeat."""
        self._hass = hass
        self._unsubscribe: CALLBACK_TYPE | None = None

    async def async_setup(self) -> None:
        """Set up the heartbeat."""
        if self._unsubscribe is None:
            await self.async_heartbeat(dt.datetime.now())
            self._unsubscribe = event.async_track_time_interval(
                self._hass, self.async_heartbeat, self.HEARTBEAT_INTERVAL
            )

    async def async_unload(self) -> None:
        """Unload the heartbeat."""
        if self._unsubscribe is not None:
            self._unsubscribe()
            self._unsubscribe = None

    async def async_heartbeat(self, _: dt.datetime) -> None:
        """Send packets to feed watchdog timers."""
        hass = self._hass
        config_entries = hass.config_entries.async_entries(DOMAIN)
        hosts: set[str] = {entry.data[CONF_HOST] for entry in config_entries}
        await hass.async_add_executor_job(self.heartbeat, hosts)

    @staticmethod
    def heartbeat(hosts: set[str]) -> None:
        """Send packets to feed watchdog timers."""
        for host in hosts:
            try:
                blk.ping(host)
            except OSError as err:
                _LOGGER.debug("Failed to send heartbeat to %s: %s", host, err)
            else:
                _LOGGER.debug("Heartbeat sent to %s", host)
