from __future__ import annotations

import platform
import socket

from ..models import WifiBand, WifiResult
from ..net import get_wireless_interface

LABEL = "WiFi:"


def summary(result: WifiResult | None) -> str:
    lbl = f"{LABEL:14s}"
    if result is None:
        return f"{lbl}not available"
    parts = [f"{result.signal_dbm} dBm ({result.band.value})"]
    if result.tx_bitrate_mbps is not None:
        parts.append(f"{result.tx_bitrate_mbps:.0f} Mbps TX")
    if result.rx_bitrate_mbps is not None:
        parts.append(f"{result.rx_bitrate_mbps:.0f} Mbps RX")
    return f"{lbl}{', '.join(parts)}"


def _parse_bitrate(rate_nla) -> float | None:  # type: ignore[no-any-explicit]
    """Extract bitrate in Mbps from a rate info NLA."""
    if rate_nla is None:
        return None
    bitrate = rate_nla.get_attr("NL80211_RATE_INFO_BITRATE32")
    if bitrate is None:
        bitrate = rate_nla.get_attr("NL80211_RATE_INFO_BITRATE")
    if bitrate is not None:
        return bitrate / 10.0
    return None


def _freq_from_scan(iw, ifindex: int) -> int | None:  # type: ignore[no-any-explicit]
    """Fall back to BSS scan dump to find the frequency of the connected AP."""
    try:
        bss_msg = iw.get_associated_bss(ifindex)
    except Exception:
        return None
    if bss_msg is None:
        return None
    bss = bss_msg.get_attr("NL80211_ATTR_BSS")
    if bss is None:
        return None
    return bss.get_attr("NL80211_BSS_FREQUENCY")


def run() -> WifiResult | None:
    """Check wifi signal strength. Returns None if not on wifi or not Linux."""
    if platform.system() != "Linux":
        return None

    iface = get_wireless_interface()
    if iface is None:
        return None

    try:
        from pyroute2 import IW
    except ImportError:
        return None

    ifindex = socket.if_nametoindex(iface)
    with IW() as iw:
        iface_msgs = iw.get_interface_by_ifindex(ifindex)
        if not iface_msgs:
            return None
        frequency_mhz = iface_msgs[0].get_attr("NL80211_ATTR_WIPHY_FREQ")

        if frequency_mhz is None:
            frequency_mhz = _freq_from_scan(iw, ifindex)
        if frequency_mhz is None:
            return None

        station_msgs = list(iw.get_stations(ifindex))
        if not station_msgs:
            return None
        sta = station_msgs[0].get_attr("NL80211_ATTR_STA_INFO")
        if sta is None:
            return None

        signal_dbm = sta.get_attr("NL80211_STA_INFO_SIGNAL")
        signal_avg_dbm = sta.get_attr("NL80211_STA_INFO_SIGNAL_AVG")
        if signal_dbm is None or signal_avg_dbm is None:
            return None

        tx_bitrate = _parse_bitrate(sta.get_attr("NL80211_STA_INFO_TX_BITRATE"))
        rx_bitrate = _parse_bitrate(sta.get_attr("NL80211_STA_INFO_RX_BITRATE"))

    return WifiResult(
        interface=iface,
        signal_dbm=signal_dbm,
        signal_avg_dbm=signal_avg_dbm,
        frequency_mhz=frequency_mhz,
        band=WifiBand.from_frequency(frequency_mhz),
        tx_bitrate_mbps=tx_bitrate,
        rx_bitrate_mbps=rx_bitrate,
    )
