"""The WeatherflowCloud integration."""

import asyncio

from weatherflow4py.api import WeatherFlowRestAPI
from weatherflow4py.ws import WeatherFlowWebsocketAPI
from websockets.exceptions import WebSocketException

from homeassistant.const import CONF_API_TOKEN, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.util.ssl import client_context

from .const import LOGGER
from .coordinator import (
    WeatherFlowCloudConfigEntry,
    WeatherFlowCloudUpdateCoordinatorREST,
    WeatherFlowCoordinators,
    WeatherFlowObservationCoordinator,
    WeatherFlowWindCoordinator,
)

PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.WEATHER]


async def async_setup_entry(
    hass: HomeAssistant, entry: WeatherFlowCloudConfigEntry
) -> bool:
    """Set up WeatherFlowCloud from a config entry."""

    LOGGER.debug("Initializing WeatherFlowCloudDataUpdateCoordinatorREST coordinator")

    rest_api = WeatherFlowRestAPI(
        api_token=entry.data[CONF_API_TOKEN], session=async_get_clientsession(hass)
    )

    stations = await rest_api.async_get_stations()

    # Define Rest Coordinator
    rest_data_coordinator = WeatherFlowCloudUpdateCoordinatorREST(
        hass=hass, config_entry=entry, rest_api=rest_api, stations=stations
    )

    # Initialize the stations
    await rest_data_coordinator.async_config_entry_first_refresh()

    # Construct Websocket Coordinators
    LOGGER.debug("Initializing websocket coordinators")
    websocket_device_ids = rest_data_coordinator.device_ids

    # Build API once
    websocket_api = WeatherFlowWebsocketAPI(
        access_token=entry.data[CONF_API_TOKEN], device_ids=websocket_device_ids
    )

    websocket_observation_coordinator = WeatherFlowObservationCoordinator(
        hass=hass,
        config_entry=entry,
        rest_api=rest_api,
        websocket_api=websocket_api,
        stations=stations,
    )

    websocket_wind_coordinator = WeatherFlowWindCoordinator(
        hass=hass,
        config_entry=entry,
        rest_api=rest_api,
        websocket_api=websocket_api,
        stations=stations,
    )

    async def _async_disconnect_websocket() -> None:
        """Disconnect the WeatherFlow websocket."""
        await websocket_api.stop_all_listeners()
        await websocket_api.close()

    # Connect once because both websocket coordinators share this API instance.
    try:
        await websocket_api.connect(client_context())
    except (OSError, WebSocketException) as err:
        raise ConfigEntryNotReady("Error connecting to WeatherFlow websocket") from err

    entry.async_on_unload(_async_disconnect_websocket)

    try:
        await asyncio.gather(
            websocket_wind_coordinator.async_setup(),
            websocket_observation_coordinator.async_setup(),
        )
    except (OSError, WebSocketException) as err:
        raise ConfigEntryNotReady("Error setting up WeatherFlow websocket") from err

    entry.runtime_data = WeatherFlowCoordinators(
        rest_data_coordinator,
        websocket_wind_coordinator,
        websocket_observation_coordinator,
    )
    await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

    return True


async def async_unload_entry(
    hass: HomeAssistant, entry: WeatherFlowCloudConfigEntry
) -> bool:
    """Unload a config entry."""
    return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
