"""Entry setup/unload tests (CI)."""
import pytest


@pytest.fixture(autouse=True)
def _enable_custom_integrations(enable_custom_integrations):
    """Allow loading custom_components in the test hass."""
    yield

from homeassistant.core import HomeAssistant
from pytest_homeassistant_custom_component.common import MockConfigEntry

from custom_components.houseplan.const import DOMAIN


async def _setup(hass: HomeAssistant) -> MockConfigEntry:
    entry = MockConfigEntry(domain=DOMAIN, title="House Plan", data={}, options={})
    entry.add_to_hass(hass)
    assert await hass.config_entries.async_setup(entry.entry_id)
    await hass.async_block_till_done()
    return entry


async def test_setup_creates_runtime_data(hass: HomeAssistant) -> None:
    entry = await _setup(hass)
    assert entry.state.value == "loaded"
    assert entry.runtime_data is not None
    assert entry.runtime_data.store is not None
    assert entry.runtime_data.config_store is not None


async def test_unload(hass: HomeAssistant) -> None:
    entry = await _setup(hass)
    assert await hass.config_entries.async_unload(entry.entry_id)
    await hass.async_block_till_done()
    assert entry.state.value == "not_loaded"


async def test_square_migration_finishes_after_a_crash_between_the_writes(
    hass: HomeAssistant, hass_storage, monkeypatch
) -> None:
    """HP-1490-01, end to end on the real stores.

    The layout write is made to fail once, AFTER the config write succeeded —
    the exact boundary that used to strand the layout in the old coordinates
    forever, because the config write had already deleted the `aspect` fields
    the layout half needed. The durable intent must finish the job on the next
    setup.
    """
    from custom_components.houseplan.store import HouseplanStore

    hass_storage["houseplan.config"] = {
        "version": 1, "data": {
            "config": {"spaces": [{"id": "f1", "aspect": 2.0, "rooms": []}],
                       "markers": [], "settings": {}},
            "rev": 3,
        },
    }
    hass_storage["houseplan.layout"] = {
        "version": 1, "data": {"layout": {"m": {"s": "f1", "x": 0.1, "y": 0.1}}, "rev": 7},
    }

    real_save = HouseplanStore.async_save
    state = {"layout_saves": 0}

    async def failing_save(self, data):
        if self.key == "houseplan.layout" and "geom_pending" not in data:
            state["layout_saves"] += 1
            if state["layout_saves"] == 1:
                raise OSError("disk full at the worst possible moment")
        await real_save(self, data)

    monkeypatch.setattr(HouseplanStore, "async_save", failing_save)

    entry = MockConfigEntry(domain=DOMAIN, title="House Plan", data={}, options={})
    entry.add_to_hass(hass)
    await hass.config_entries.async_setup(entry.entry_id)
    await hass.async_block_till_done()

    # the crash boundary: config migrated, layout not, intent saved
    cfg = hass_storage["houseplan.config"]["data"]["config"]
    assert "aspect" not in cfg["spaces"][0], "the config half committed"
    lay = hass_storage["houseplan.layout"]["data"]
    assert lay["layout"]["m"]["y"] == 0.1, "the layout half did NOT commit"
    assert lay.get("geom_pending") == {"f1": 2.0}, "but the intent is durable"

    # next start: the store write works again
    monkeypatch.setattr(HouseplanStore, "async_save", real_save)
    if entry.state.value == "loaded":
        await hass.config_entries.async_unload(entry.entry_id)
    await hass.config_entries.async_reload(entry.entry_id)
    await hass.async_block_till_done()

    lay = hass_storage["houseplan.layout"]["data"]
    assert lay["layout"]["m"] == {"s": "f1", "x": 0.1, "y": 0.3}, (
        "the saved intent finished the layout half"
    )
    assert "geom_pending" not in lay, "and left with the layout write"
    cfg = hass_storage["houseplan.config"]["data"]["config"]
    assert cfg["spaces"][0]["view_box"] == [0.0, 0.0, 1.0, 1.0]

    # a third start changes nothing — both triggers are gone
    before = repr(hass_storage["houseplan.layout"]) + repr(hass_storage["houseplan.config"])
    await hass.config_entries.async_reload(entry.entry_id)
    await hass.async_block_till_done()
    assert repr(hass_storage["houseplan.layout"]) + repr(hass_storage["houseplan.config"]) == before
