"""Network overview widget."""

from __future__ import annotations

from textual.app import ComposeResult
from textual.containers import Grid
from textual.dom import NoMatches
from textual.events import Key
from textual.message import Message
from textual.reactive import var
from textual.widgets import Label

from flux_networking_shared.tui.messages import FocusTabsRequested
from flux_networking_shared.tui.widgets.interface_group import FocusButtonsRequested


class NetworkOverview(Grid, can_focus=True):
    """Displays key network metrics in a grid layout."""

    class NetworkAvailableMessage(Message):
        """Posted when network availability status changes."""

        def __init__(self, available: bool) -> None:
            super().__init__()
            self.available = available

    BORDER_TITLE = "Network Overview"

    DEFAULT_CSS = """
        NetworkOverview {
            grid-size: 2;
            grid-columns: auto 1fr;
            grid-gutter: 0 1;
            height: auto;
            border: solid $primary;
            padding: 1;
        }

        NetworkOverview .right-align {
            text-align: right;
        }

        NetworkOverview.--highlight {
            border: double $primary;
            background: $panel;
        }
    """

    network_address = var("")
    connectivity = var("")
    name_resolution = var("")
    dns = var("")
    default_route = var("")
    upnp_enabled = var("")
    upnp_port = var("")

    network_available = var(False)

    def __init__(
        self,
        *,
        network_address: str = "Unknown",
        connectivity: str = "Unknown",
        name_resolution: str = "Unknown",
        dns: str = "Unknown",
        default_route: str = "Unknown",
        upnp_enabled: str = "False",
        upnp_port: str = "Unknown",
    ) -> None:
        super().__init__()

        self._network_address = network_address
        self._connectivity = connectivity
        self._name_resolution = name_resolution
        self._dns = dns
        self._default_route = default_route
        self._upnp_enabled = upnp_enabled
        self._upnp_port = upnp_port

    def compose(self) -> ComposeResult:
        yield Label("Primary Network Address:", classes="right-align")
        yield Label(self._network_address, id="network-address")
        yield Label("Network Connectivity:", classes="right-align")
        yield Label(self._connectivity, id="network-connectivity")
        yield Label("Name Resolution:", classes="right-align")
        yield Label(self._name_resolution, id="name_resolution")
        yield Label("Domain Name Servers:", classes="right-align")
        yield Label(self._dns, id="dns")
        yield Label("Default Route:", classes="right-align")
        yield Label(self._default_route, id="default-route")
        yield Label("UpnP Enabled:", classes="right-align")
        yield Label(self._upnp_enabled, id="upnp-enabled")
        yield Label("UPnP Port:", classes="right-align")
        yield Label(self._upnp_port, id="upnp-port")

    def update_values(
        self,
        network_address: str,
        connectivity: str,
        dns: str,
        default_route: str,
        upnp_enabled: str,
        upnp_port: str,
    ) -> None:
        """Update all values at once."""
        if self.is_mounted:
            self.network_address = network_address
            self.connectivity = connectivity
            self.dns = dns
            self.default_route = default_route
            self.upnp_enabled = upnp_enabled
            self.upnp_port = upnp_port
        else:
            self._network_address = network_address
            self._connectivity = connectivity
            self._dns = dns
            self._default_route = default_route
            self._upnp_enabled = upnp_enabled
            self._upnp_port = upnp_port

    def on_key(self, event: Key) -> None:
        """Handle up/down navigation."""
        event_name = event.name

        if event_name not in ["up", "down"]:
            return

        event.stop()

        msg_cls = FocusTabsRequested if event_name == "up" else FocusButtonsRequested

        self.post_message(msg_cls())

    def compute_network_available(self) -> bool:
        """Check if network is available based on connectivity status."""
        return self.connectivity in [
            "Degraded",
            "Connected",
        ] and self.name_resolution in ["Degraded", "Pass"]

    def watch_network_available(self, old: bool, new: bool) -> None:
        if old == new:
            return
        self.post_message(self.NetworkAvailableMessage(new))

    def watch_has_focus(self, has_focus: bool) -> None:
        """Toggle highlight class on focus."""
        super().watch_has_focus(has_focus)
        self.set_class(has_focus, "--highlight")

    def _update_label(self, label_id: str, value: str) -> None:
        """Helper to update a label by ID."""
        try:
            self.query_one(f"#{label_id}", Label).update(value)
        except NoMatches:
            pass

    def watch_network_address(self, old: str, new: str) -> None:
        if old == new:
            return
        self._network_address = new
        self._update_label("network-address", new)

    def watch_connectivity(self, old: str, new: str) -> None:
        if old == new:
            return
        self._connectivity = new
        self._update_label("network-connectivity", new)

    def watch_name_resolution(self, old: str, new: str) -> None:
        if old == new:
            return
        self._name_resolution = new
        self._update_label("name_resolution", new)

    def watch_dns(self, old: str, new: str) -> None:
        if old == new:
            return
        self._dns = new
        self._update_label("dns", new)

    def watch_default_route(self, old: str, new: str) -> None:
        if old == new:
            return
        self._default_route = new
        self._update_label("default-route", new)

    def watch_upnp_enabled(self, old: str, new: str) -> None:
        if old == new:
            return
        self._upnp_enabled = new
        self._update_label("upnp-enabled", new)

    def watch_upnp_port(self, old: str, new: str) -> None:
        if old == new:
            return
        self._upnp_port = new
        self._update_label("upnp-port", new)
