"""Represent the Netgear router and its devices."""

from abc import abstractmethod
from typing import Any, override

from homeassistant.core import callback
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .coordinator import NetgearDataCoordinator, NetgearTrackerCoordinator
from .router import NetgearRouter


class NetgearDeviceEntity(CoordinatorEntity[NetgearTrackerCoordinator]):
    """Base class for a device connected to a Netgear router."""

    _attr_has_entity_name = True

    def __init__(
        self,
        coordinator: NetgearTrackerCoordinator,
        device: dict,
    ) -> None:
        """Initialize a Netgear device."""
        super().__init__(coordinator)
        self._router = coordinator.router
        self._device = device
        self._mac = device["mac"]
        self._device_name = self.get_device_name()
        self._active = device["active"]
        self._attr_unique_id = self._mac
        self._attr_device_info = DeviceInfo(
            connections={(dr.CONNECTION_NETWORK_MAC, self._mac)},
            default_name=self._device_name,
            default_model=device["device_model"],
            via_device_id=dr.async_get_device_id_by_identifier(
                coordinator.hass,
                (DOMAIN, coordinator.router.unique_id),
                config_entry_id=coordinator.config_entry.entry_id,
            ),
        )

    def get_device_name(self):
        """Return the name of the given device or the MAC if we don't know."""
        name = self._device["name"]
        if not name or name == "--":
            name = self._mac

        return name

    @abstractmethod
    @callback
    def async_update_device(self) -> None:
        """Update the Netgear device."""

    @callback
    @override
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        self.async_update_device()
        super()._handle_coordinator_update()


class NetgearRouterEntity(Entity):
    """Base class for a Netgear router entity without coordinator."""

    _attr_has_entity_name = True

    def __init__(self, router: NetgearRouter) -> None:
        """Initialize a Netgear device."""
        self._router = router
        self._attr_unique_id = router.serial_number
        self._attr_device_info = router.device_info


class NetgearRouterCoordinatorEntity[T: NetgearDataCoordinator[Any]](
    NetgearRouterEntity, CoordinatorEntity[T]
):
    """Base class for a Netgear router entity."""

    def __init__(self, coordinator: T) -> None:
        """Initialize a Netgear device."""
        CoordinatorEntity.__init__(self, coordinator)
        NetgearRouterEntity.__init__(self, coordinator.router)

    @abstractmethod
    @callback
    def async_update_device(self) -> None:
        """Update the Netgear device."""

    @callback
    @override
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        self.async_update_device()
        super()._handle_coordinator_update()
