"""Tests for the homewizard component."""

from unittest.mock import MagicMock

from homewizard_energy.errors import DisabledError, HomeWizardEnergyException
import pytest

from homeassistant.components.homewizard.const import DOMAIN
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er

from tests.common import MockConfigEntry


async def test_load_unload(
    hass: HomeAssistant,
    mock_config_entry: MockConfigEntry,
    mock_homewizardenergy: MagicMock,
) -> None:
    """Test loading and unloading of integration."""
    mock_config_entry.add_to_hass(hass)
    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state is ConfigEntryState.LOADED
    assert len(mock_homewizardenergy.device.mock_calls) == 1

    await hass.config_entries.async_unload(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state is ConfigEntryState.NOT_LOADED


async def test_load_failed_host_unavailable(
    hass: HomeAssistant,
    mock_config_entry: MockConfigEntry,
    mock_homewizardenergy: MagicMock,
) -> None:
    """Test setup handles unreachable host."""
    mock_homewizardenergy.device.side_effect = TimeoutError()
    mock_config_entry.add_to_hass(hass)
    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY


async def test_load_detect_api_disabled(
    hass: HomeAssistant,
    mock_config_entry: MockConfigEntry,
    mock_homewizardenergy: MagicMock,
) -> None:
    """Test setup detects disabled API."""
    mock_homewizardenergy.device.side_effect = DisabledError()
    mock_config_entry.add_to_hass(hass)
    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY

    flows = hass.config_entries.flow.async_progress()
    assert len(flows) == 1

    flow = flows[0]
    assert flow.get("step_id") == "reauth_confirm"
    assert flow.get("handler") == DOMAIN

    assert "context" in flow
    assert flow["context"].get("source") == SOURCE_REAUTH
    assert flow["context"].get("entry_id") == mock_config_entry.entry_id


@pytest.mark.usefixtures("mock_homewizardenergy")
async def test_load_removes_reauth_flow(
    hass: HomeAssistant,
    mock_config_entry: MockConfigEntry,
) -> None:
    """Test setup removes reauth flow when API is enabled."""
    mock_config_entry.add_to_hass(hass)

    # Add reauth flow from 'previously' failed init
    mock_config_entry.async_start_reauth(hass)
    await hass.async_block_till_done()

    flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
    assert len(flows) == 1

    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state is ConfigEntryState.LOADED

    # Flow should be removed
    flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
    assert len(flows) == 0


@pytest.mark.parametrize(
    "exception",
    [
        HomeWizardEnergyException,
        Exception,
    ],
)
async def test_load_handles_homewizardenergy_exception(
    hass: HomeAssistant,
    mock_config_entry: MockConfigEntry,
    mock_homewizardenergy: MagicMock,
    exception: Exception,
) -> None:
    """Test setup handles exception from API."""
    mock_homewizardenergy.device.side_effect = exception
    mock_config_entry.add_to_hass(hass)
    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert mock_config_entry.state in (
        ConfigEntryState.SETUP_RETRY,
        ConfigEntryState.SETUP_ERROR,
    )


@pytest.mark.parametrize(
    ("device_fixture", "old_unique_id", "new_unique_id"),
    [
        (
            "HWE-SKT-11",
            "aabbccddeeff_total_power_import_t1_kwh",
            "aabbccddeeff_total_power_import_kwh",
        ),
        (
            "HWE-SKT-11",
            "aabbccddeeff_total_power_export_t1_kwh",
            "aabbccddeeff_total_power_export_kwh",
        ),
        (
            "HWE-SKT-21",
            "aabbccddeeff_total_power_import_t1_kwh",
            "aabbccddeeff_total_power_import_kwh",
        ),
        (
            "HWE-SKT-21",
            "aabbccddeeff_total_power_export_t1_kwh",
            "aabbccddeeff_total_power_export_kwh",
        ),
    ],
)
@pytest.mark.usefixtures("mock_homewizardenergy")
async def test_sensor_migration(
    hass: HomeAssistant,
    entity_registry: er.EntityRegistry,
    mock_config_entry: MockConfigEntry,
    old_unique_id: str,
    new_unique_id: str,
) -> None:
    """Test total power T1 sensors are migrated."""
    mock_config_entry.add_to_hass(hass)

    entity: er.RegistryEntry = entity_registry.async_get_or_create(
        domain=Platform.SENSOR,
        platform=DOMAIN,
        unique_id=old_unique_id,
        config_entry=mock_config_entry,
    )

    assert entity.unique_id == old_unique_id

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

    entity_migrated = entity_registry.async_get(entity.entity_id)
    assert entity_migrated
    assert entity_migrated.unique_id == new_unique_id
    assert entity_migrated.previous_unique_id == old_unique_id


@pytest.mark.parametrize(
    ("device_fixture", "old_unique_id", "new_unique_id"),
    [
        (
            "HWE-SKT-11",
            "aabbccddeeff_total_power_import_t1_kwh",
            "aabbccddeeff_total_power_import_kwh",
        ),
        (
            "HWE-SKT-11",
            "aabbccddeeff_total_power_export_t1_kwh",
            "aabbccddeeff_total_power_export_kwh",
        ),
        (
            "HWE-SKT-21",
            "aabbccddeeff_total_power_import_t1_kwh",
            "aabbccddeeff_total_power_import_kwh",
        ),
        (
            "HWE-SKT-21",
            "aabbccddeeff_total_power_export_t1_kwh",
            "aabbccddeeff_total_power_export_kwh",
        ),
    ],
)
@pytest.mark.usefixtures("mock_homewizardenergy")
async def test_sensor_migration_does_not_trigger(
    hass: HomeAssistant,
    entity_registry: er.EntityRegistry,
    mock_config_entry: MockConfigEntry,
    old_unique_id: str,
    new_unique_id: str,
) -> None:
    """Test total power T1 sensors are not migrated when not possible."""
    mock_config_entry.add_to_hass(hass)

    old_entity: er.RegistryEntry = entity_registry.async_get_or_create(
        domain=Platform.SENSOR,
        platform=DOMAIN,
        unique_id=old_unique_id,
        config_entry=mock_config_entry,
    )

    new_entity: er.RegistryEntry = entity_registry.async_get_or_create(
        domain=Platform.SENSOR,
        platform=DOMAIN,
        unique_id=new_unique_id,
        config_entry=mock_config_entry,
    )

    assert old_entity.unique_id == old_unique_id
    assert new_entity.unique_id == new_unique_id

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

    entity = entity_registry.async_get(old_entity.entity_id)
    assert entity
    assert entity.unique_id == old_unique_id
    assert entity.previous_unique_id is None

    entity = entity_registry.async_get(new_entity.entity_id)
    assert entity
    assert entity.unique_id == new_unique_id
    assert entity.previous_unique_id is None