"""Test Hue migration logic."""
from unittest.mock import patch

from homeassistant.components import hue
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er

from tests.common import MockConfigEntry


async def test_migrate_api_key(hass: HomeAssistant) -> None:
    """Test if username gets migrated to api_key."""
    config_entry = MockConfigEntry(
        domain=hue.DOMAIN,
        data={"host": "0.0.0.0", "api_version": 2, "username": "abcdefgh"},
    )
    await hue.migration.check_migration(hass, config_entry)
    # the username property should have been migrated to api_key
    assert config_entry.data == {
        "host": "0.0.0.0",
        "api_version": 2,
        "api_key": "abcdefgh",
    }


async def test_auto_switchover(hass: HomeAssistant) -> None:
    """Test if config entry from v1 automatically switches to v2."""
    config_entry = MockConfigEntry(
        domain=hue.DOMAIN,
        data={"host": "0.0.0.0", "api_version": 1, "username": "abcdefgh"},
    )

    with patch.object(hue.migration, "is_v2_bridge", retun_value=True), patch.object(
        hue.migration, "handle_v2_migration"
    ) as mock_mig:
        await hue.migration.check_migration(hass, config_entry)
        assert len(mock_mig.mock_calls) == 1
        # the api version should now be version 2
        assert config_entry.data == {
            "host": "0.0.0.0",
            "api_version": 2,
            "api_key": "abcdefgh",
        }


async def test_light_entity_migration(
    hass: HomeAssistant, mock_bridge_v2, mock_config_entry_v2, v2_resources_test_data
) -> None:
    """Test if entity schema for lights migrates from v1 to v2."""
    config_entry = mock_bridge_v2.config_entry = mock_config_entry_v2

    ent_reg = er.async_get(hass)
    dev_reg = dr.async_get(hass)

    # create device/entity with V1 schema in registry
    device = dev_reg.async_get_or_create(
        config_entry_id=config_entry.entry_id,
        identifiers={(hue.DOMAIN, "00:17:88:01:09:aa:bb:65-0b")},
    )
    ent_reg.async_get_or_create(
        "light",
        hue.DOMAIN,
        "00:17:88:01:09:aa:bb:65-0b",
        suggested_object_id="migrated_light_1",
        device_id=device.id,
    )

    # now run the migration and check results
    await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.hue.migration.HueBridgeV2",
        return_value=mock_bridge_v2.api,
    ):
        await hue.migration.handle_v2_migration(hass, config_entry)

    # migrated device should now have the new identifier (guid) instead of old style (mac)
    migrated_device = dev_reg.async_get(device.id)
    assert migrated_device is not None
    assert migrated_device.identifiers == {
        (hue.DOMAIN, "0b216218-d811-4c95-8c55-bbcda50f9d50")
    }
    # the entity should have the new unique_id (guid)
    migrated_entity = ent_reg.async_get("light.migrated_light_1")
    assert migrated_entity is not None
    assert migrated_entity.unique_id == "02cba059-9c2c-4d45-97e4-4f79b1bfbaa1"


async def test_sensor_entity_migration(
    hass: HomeAssistant, mock_bridge_v2, mock_config_entry_v2, v2_resources_test_data
) -> None:
    """Test if entity schema for sensors migrates from v1 to v2."""
    config_entry = mock_bridge_v2.config_entry = mock_config_entry_v2

    ent_reg = er.async_get(hass)
    dev_reg = dr.async_get(hass)

    # create device with V1 schema in registry for Hue motion sensor
    device_mac = "00:17:aa:bb:cc:09:ac:c3"
    device = dev_reg.async_get_or_create(
        config_entry_id=config_entry.entry_id, identifiers={(hue.DOMAIN, device_mac)}
    )

    # mapping of device_class to new id
    sensor_mappings = {
        ("temperature", "sensor", "66466e14-d2fa-4b96-b2a0-e10de9cd8b8b"),
        ("illuminance", "sensor", "d504e7a4-9a18-4854-90fd-c5b6ac102c40"),
        ("battery", "sensor", "669f609d-4860-4f1c-bc25-7a9cec1c3b6c"),
        ("motion", "binary_sensor", "b6896534-016d-4052-8cb4-ef04454df62c"),
    }

    # create entities with V1 schema in registry for Hue motion sensor
    for dev_class, platform, _ in sensor_mappings:
        ent_reg.async_get_or_create(
            platform,
            hue.DOMAIN,
            f"{device_mac}-{dev_class}",
            suggested_object_id=f"hue_migrated_{dev_class}_sensor",
            device_id=device.id,
            original_device_class=dev_class,
        )

    # now run the migration and check results
    await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.hue.migration.HueBridgeV2",
        return_value=mock_bridge_v2.api,
    ):
        await hue.migration.handle_v2_migration(hass, config_entry)

    # migrated device should now have the new identifier (guid) instead of old style (mac)
    migrated_device = dev_reg.async_get(device.id)
    assert migrated_device is not None
    assert migrated_device.identifiers == {
        (hue.DOMAIN, "2330b45d-6079-4c6e-bba6-1b68afb1a0d6")
    }
    # the entities should have the correct V2 unique_id (guid)
    for dev_class, platform, new_id in sensor_mappings:
        migrated_entity = ent_reg.async_get(
            f"{platform}.hue_migrated_{dev_class}_sensor"
        )
        assert migrated_entity is not None
        assert migrated_entity.unique_id == new_id


async def test_group_entity_migration_with_v1_id(
    hass: HomeAssistant, mock_bridge_v2, mock_config_entry_v2, v2_resources_test_data
) -> None:
    """Test if entity schema for grouped_lights migrates from v1 to v2."""
    config_entry = mock_bridge_v2.config_entry = mock_config_entry_v2

    ent_reg = er.async_get(hass)

    # create (deviceless) entity with V1 schema in registry
    # using the legacy style group id as unique id
    ent_reg.async_get_or_create(
        "light",
        hue.DOMAIN,
        "3",
        suggested_object_id="hue_migrated_grouped_light",
        config_entry=config_entry,
    )

    # now run the migration and check results
    await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
    await hass.async_block_till_done()
    with patch(
        "homeassistant.components.hue.migration.HueBridgeV2",
        return_value=mock_bridge_v2.api,
    ):
        await hue.migration.handle_v2_migration(hass, config_entry)

    # the entity should have the new identifier (guid)
    migrated_entity = ent_reg.async_get("light.hue_migrated_grouped_light")
    assert migrated_entity is not None
    assert migrated_entity.unique_id == "e937f8db-2f0e-49a0-936e-027e60e15b34"


async def test_group_entity_migration_with_v2_group_id(
    hass: HomeAssistant, mock_bridge_v2, mock_config_entry_v2, v2_resources_test_data
) -> None:
    """Test if entity schema for grouped_lights migrates from v1 to v2."""
    config_entry = mock_bridge_v2.config_entry = mock_config_entry_v2

    ent_reg = er.async_get(hass)

    # create (deviceless) entity with V1 schema in registry
    # using the V2 group id as unique id
    ent_reg.async_get_or_create(
        "light",
        hue.DOMAIN,
        "6ddc9066-7e7d-4a03-a773-c73937968296",
        suggested_object_id="hue_migrated_grouped_light",
        config_entry=config_entry,
    )

    # now run the migration and check results
    await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
    await hass.async_block_till_done()
    with patch(
        "homeassistant.components.hue.migration.HueBridgeV2",
        return_value=mock_bridge_v2.api,
    ):
        await hue.migration.handle_v2_migration(hass, config_entry)

    # the entity should have the new identifier (guid)
    migrated_entity = ent_reg.async_get("light.hue_migrated_grouped_light")
    assert migrated_entity is not None
    assert migrated_entity.unique_id == "e937f8db-2f0e-49a0-936e-027e60e15b34"