"""Test bluetooth diagnostics."""


from unittest.mock import ANY, patch

from bleak.backends.scanner import BLEDevice

from homeassistant.components import bluetooth
from homeassistant.components.bluetooth.const import DEFAULT_ADDRESS

from . import generate_advertisement_data, inject_advertisement

from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry


async def test_diagnostics(
    hass, hass_client, mock_bleak_scanner_start, enable_bluetooth, two_adapters
):
    """Test we can setup and unsetup bluetooth with multiple adapters."""
    # Normally we do not want to patch our classes, but since bleak will import
    # a different scanner based on the operating system, we need to patch here
    # because we cannot import the scanner class directly without it throwing an
    # error if the test is not running on linux since we won't have the correct
    # deps installed when testing on MacOS.
    with patch(
        "homeassistant.components.bluetooth.scanner.HaScanner.discovered_devices",
        [BLEDevice(name="x", rssi=-60, address="44:44:33:11:23:45")],
    ), patch(
        "homeassistant.components.bluetooth.diagnostics.platform.system",
        return_value="Linux",
    ), patch(
        "homeassistant.components.bluetooth.diagnostics.get_dbus_managed_objects",
        return_value={
            "org.bluez": {
                "/org/bluez/hci0": {
                    "org.bluez.Adapter1": {
                        "Name": "BlueZ 5.63",
                        "Alias": "BlueZ 5.63",
                        "Modalias": "usb:v1D6Bp0246d0540",
                        "Discovering": False,
                    },
                    "org.bluez.AdvertisementMonitorManager1": {
                        "SupportedMonitorTypes": ["or_patterns"],
                        "SupportedFeatures": [],
                    },
                }
            }
        },
    ):
        entry1 = MockConfigEntry(
            domain=bluetooth.DOMAIN, data={}, unique_id="00:00:00:00:00:01"
        )
        entry1.add_to_hass(hass)

        entry2 = MockConfigEntry(
            domain=bluetooth.DOMAIN, data={}, unique_id="00:00:00:00:00:02"
        )
        entry2.add_to_hass(hass)

        assert await hass.config_entries.async_setup(entry1.entry_id)
        await hass.async_block_till_done()
        assert await hass.config_entries.async_setup(entry2.entry_id)
        await hass.async_block_till_done()

        diag = await get_diagnostics_for_config_entry(hass, hass_client, entry1)
        assert diag == {
            "adapters": {
                "hci0": {
                    "address": "00:00:00:00:00:01",
                    "hw_version": "usbid:1234",
                    "passive_scan": False,
                    "sw_version": "BlueZ 4.63",
                },
                "hci1": {
                    "address": "00:00:00:00:00:02",
                    "hw_version": "usbid:1234",
                    "passive_scan": True,
                    "sw_version": "BlueZ 4.63",
                },
            },
            "dbus": {
                "org.bluez": {
                    "/org/bluez/hci0": {
                        "org.bluez.Adapter1": {
                            "Alias": "BlueZ " "5.63",
                            "Discovering": False,
                            "Modalias": "usb:v1D6Bp0246d0540",
                            "Name": "BlueZ " "5.63",
                        },
                        "org.bluez.AdvertisementMonitorManager1": {
                            "SupportedFeatures": [],
                            "SupportedMonitorTypes": ["or_patterns"],
                        },
                    }
                }
            },
            "manager": {
                "adapters": {
                    "hci0": {
                        "address": "00:00:00:00:00:01",
                        "hw_version": "usbid:1234",
                        "passive_scan": False,
                        "sw_version": "BlueZ 4.63",
                    },
                    "hci1": {
                        "address": "00:00:00:00:00:02",
                        "hw_version": "usbid:1234",
                        "passive_scan": True,
                        "sw_version": "BlueZ 4.63",
                    },
                },
                "advertisement_tracker": {
                    "intervals": {},
                    "sources": {},
                    "timings": {},
                },
                "connectable_history": [],
                "all_history": [],
                "scanners": [
                    {
                        "adapter": "hci0",
                        "discovered_devices": [
                            {"address": "44:44:33:11:23:45", "name": "x"}
                        ],
                        "last_detection": ANY,
                        "name": "hci0 (00:00:00:00:00:01)",
                        "source": "00:00:00:00:00:01",
                        "start_time": ANY,
                        "type": "HaScanner",
                    },
                    {
                        "adapter": "hci0",
                        "discovered_devices": [
                            {"address": "44:44:33:11:23:45", "name": "x"}
                        ],
                        "last_detection": ANY,
                        "name": "hci0 (00:00:00:00:00:01)",
                        "source": "00:00:00:00:00:01",
                        "start_time": ANY,
                        "type": "HaScanner",
                    },
                    {
                        "adapter": "hci1",
                        "discovered_devices": [
                            {"address": "44:44:33:11:23:45", "name": "x"}
                        ],
                        "last_detection": ANY,
                        "name": "hci1 (00:00:00:00:00:02)",
                        "source": "00:00:00:00:00:02",
                        "start_time": ANY,
                        "type": "HaScanner",
                    },
                ],
            },
        }


async def test_diagnostics_macos(
    hass, hass_client, mock_bleak_scanner_start, mock_bluetooth_adapters, macos_adapter
):
    """Test we can setup and unsetup bluetooth with multiple adapters."""
    # Normally we do not want to patch our classes, but since bleak will import
    # a different scanner based on the operating system, we need to patch here
    # because we cannot import the scanner class directly without it throwing an
    # error if the test is not running on linux since we won't have the correct
    # deps installed when testing on MacOS.
    switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
    switchbot_adv = generate_advertisement_data(
        local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
    )

    with patch(
        "homeassistant.components.bluetooth.scanner.HaScanner.discovered_devices",
        [BLEDevice(name="x", rssi=-60, address="44:44:33:11:23:45")],
    ), patch(
        "homeassistant.components.bluetooth.diagnostics.platform.system",
        return_value="Darwin",
    ), patch(
        "homeassistant.components.bluetooth.diagnostics.get_dbus_managed_objects",
        return_value={},
    ):
        entry1 = MockConfigEntry(
            domain=bluetooth.DOMAIN,
            data={},
            title="Core Bluetooth",
            unique_id=DEFAULT_ADDRESS,
        )
        entry1.add_to_hass(hass)

        assert await hass.config_entries.async_setup(entry1.entry_id)
        await hass.async_block_till_done()

        inject_advertisement(hass, switchbot_device, switchbot_adv)

        diag = await get_diagnostics_for_config_entry(hass, hass_client, entry1)
        assert diag == {
            "adapters": {
                "Core Bluetooth": {
                    "address": "00:00:00:00:00:00",
                    "passive_scan": False,
                    "sw_version": ANY,
                }
            },
            "manager": {
                "adapters": {
                    "Core Bluetooth": {
                        "address": "00:00:00:00:00:00",
                        "passive_scan": False,
                        "sw_version": ANY,
                    }
                },
                "advertisement_tracker": {
                    "intervals": {},
                    "sources": {"44:44:33:11:23:45": "local"},
                    "timings": {"44:44:33:11:23:45": [ANY]},
                },
                "connectable_history": [
                    {
                        "address": "44:44:33:11:23:45",
                        "advertisement": [
                            "wohand",
                            {"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}},
                            {},
                            [],
                            -127,
                            -127,
                            [[]],
                        ],
                        "connectable": True,
                        "manufacturer_data": {
                            "1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}
                        },
                        "name": "wohand",
                        "rssi": -127,
                        "service_data": {},
                        "service_uuids": [],
                        "source": "local",
                        "time": ANY,
                    }
                ],
                "all_history": [
                    {
                        "address": "44:44:33:11:23:45",
                        "advertisement": [
                            "wohand",
                            {"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}},
                            {},
                            [],
                            -127,
                            -127,
                            [[]],
                        ],
                        "connectable": True,
                        "manufacturer_data": {
                            "1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}
                        },
                        "name": "wohand",
                        "rssi": -127,
                        "service_data": {},
                        "service_uuids": [],
                        "source": "local",
                        "time": ANY,
                    }
                ],
                "scanners": [
                    {
                        "adapter": "Core Bluetooth",
                        "discovered_devices": [
                            {"address": "44:44:33:11:23:45", "name": "x"}
                        ],
                        "last_detection": ANY,
                        "name": "Core Bluetooth",
                        "source": "Core Bluetooth",
                        "start_time": ANY,
                        "type": "HaScanner",
                    }
                ],
            },
        }