import asyncio
from typing import List

from bleak import BleakScanner
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData

from gtv.models import BtDeviceInfo

_ATV_NAME_PATTERNS = [
    "android tv", "google tv", "chromecast", "shield", "bravia",
    "mi box", "mi tv", "xiaomi", "onn.", "mecool", "tivo",
    "nvidia", "philips", "tcl", "hisense",
]

GOOGLE_MANUFACTURER_ID = 0x00E0


def _is_likely_android_tv(name: str, adv: AdvertisementData) -> bool:
    lower = name.lower()
    if any(pat in lower for pat in _ATV_NAME_PATTERNS):
        return True
    if GOOGLE_MANUFACTURER_ID in adv.manufacturer_data:
        return True
    return False


async def discover_devices_bluetooth(
    timeout: float = 8.0, show_all: bool = False
) -> List[BtDeviceInfo]:
    devices: List[BtDeviceInfo] = []
    seen: set = set()

    def callback(device: BLEDevice, adv: AdvertisementData):
        if device.address in seen:
            return
        seen.add(device.address)
        name = device.name or adv.local_name or "Unknown"
        likely = _is_likely_android_tv(name, adv)
        if show_all or likely:
            devices.append(BtDeviceInfo(
                name=name,
                address=device.address,
                rssi=adv.rssi if adv.rssi is not None else -999,
                is_likely_atv=likely,
            ))

    scanner = BleakScanner(detection_callback=callback)
    await scanner.start()
    await asyncio.sleep(timeout)
    await scanner.stop()

    devices.sort(key=lambda d: (-d.is_likely_atv, -d.rssi))
    return devices
