"""Adds config flow for Airly."""

from __future__ import annotations

from asyncio import timeout
from http import HTTPStatus
from typing import Any

from aiohttp import ClientSession
from airly import Airly
from airly.exceptions import AirlyError
import voluptuous as vol

from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv

from .const import CONF_USE_NEAREST, DOMAIN, NO_AIRLY_SENSORS


class AirlyFlowHandler(ConfigFlow, domain=DOMAIN):
    """Config flow for Airly."""

    VERSION = 1

    async def async_step_user(
        self, user_input: dict[str, Any] | None = None
    ) -> ConfigFlowResult:
        """Handle a flow initialized by the user."""
        errors = {}
        use_nearest = False

        websession = async_get_clientsession(self.hass)

        if user_input is not None:
            await self.async_set_unique_id(
                f"{user_input[CONF_LATITUDE]}-{user_input[CONF_LONGITUDE]}"
            )
            self._abort_if_unique_id_configured()
            try:
                location_point_valid = await test_location(
                    websession,
                    user_input["api_key"],
                    user_input["latitude"],
                    user_input["longitude"],
                )
                if not location_point_valid:
                    location_nearest_valid = await test_location(
                        websession,
                        user_input["api_key"],
                        user_input["latitude"],
                        user_input["longitude"],
                        use_nearest=True,
                    )
            except AirlyError as err:
                if err.status_code == HTTPStatus.UNAUTHORIZED:
                    errors["base"] = "invalid_api_key"
                if err.status_code == HTTPStatus.NOT_FOUND:
                    errors["base"] = "wrong_location"
            else:
                if not location_point_valid:
                    if not location_nearest_valid:
                        return self.async_abort(reason="wrong_location")
                    use_nearest = True
                return self.async_create_entry(
                    title=user_input[CONF_NAME],
                    data={**user_input, CONF_USE_NEAREST: use_nearest},
                )

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {
                    vol.Required(CONF_API_KEY): str,
                    vol.Optional(
                        CONF_LATITUDE, default=self.hass.config.latitude
                    ): cv.latitude,
                    vol.Optional(
                        CONF_LONGITUDE, default=self.hass.config.longitude
                    ): cv.longitude,
                    vol.Optional(
                        CONF_NAME, default=self.hass.config.location_name
                    ): str,
                }
            ),
            errors=errors,
        )


async def test_location(
    client: ClientSession,
    api_key: str,
    latitude: float,
    longitude: float,
    use_nearest: bool = False,
) -> bool:
    """Return true if location is valid."""
    airly = Airly(api_key, client)
    if use_nearest:
        measurements = airly.create_measurements_session_nearest(
            latitude=latitude, longitude=longitude, max_distance_km=5
        )
    else:
        measurements = airly.create_measurements_session_point(
            latitude=latitude, longitude=longitude
        )
    async with timeout(10):
        await measurements.update()

    current = measurements.current

    if current["indexes"][0]["description"] == NO_AIRLY_SENSORS:
        return False
    return True
