"""Coordinator to update data from Aquacell API."""

import asyncio
from datetime import datetime
import logging

from aioaquacell import (
    AquacellApi,
    AquacellApiException,
    AuthenticationFailed,
    Softener,
)

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import (
    CONF_REFRESH_TOKEN,
    CONF_REFRESH_TOKEN_CREATION_TIME,
    REFRESH_TOKEN_EXPIRY_TIME,
    UPDATE_INTERVAL,
)

_LOGGER = logging.getLogger(__name__)


class AquacellCoordinator(DataUpdateCoordinator[dict[str, Softener]]):
    """My aquacell coordinator."""

    config_entry: ConfigEntry

    def __init__(self, hass: HomeAssistant, aquacell_api: AquacellApi) -> None:
        """Initialize coordinator."""
        super().__init__(
            hass,
            _LOGGER,
            name="Aquacell Coordinator",
            update_interval=UPDATE_INTERVAL,
        )

        self.refresh_token = self.config_entry.data[CONF_REFRESH_TOKEN]
        self.refresh_token_creation_time = self.config_entry.data[
            CONF_REFRESH_TOKEN_CREATION_TIME
        ]
        self.email = self.config_entry.data[CONF_EMAIL]
        self.password = self.config_entry.data[CONF_PASSWORD]
        self.aquacell_api = aquacell_api

    async def _async_update_data(self) -> dict[str, Softener]:
        """Fetch data from API endpoint.

        This is the place to pre-process the data to lookup tables
        so entities can quickly look up their data.
        """

        async with asyncio.timeout(10):
            # Check if the refresh token is expired
            expiry_time = (
                self.refresh_token_creation_time
                + REFRESH_TOKEN_EXPIRY_TIME.total_seconds()
            )
            try:
                if datetime.now().timestamp() >= expiry_time:
                    await self._reauthenticate()
                else:
                    await self.aquacell_api.authenticate_refresh(self.refresh_token)
                _LOGGER.debug("Logged in using: %s", self.refresh_token)

                softeners = await self.aquacell_api.get_all_softeners()
            except AuthenticationFailed as err:
                raise ConfigEntryError from err
            except AquacellApiException as err:
                raise UpdateFailed(f"Error communicating with API: {err}") from err

        return {softener.dsn: softener for softener in softeners}

    async def _reauthenticate(self) -> None:
        _LOGGER.debug("Attempting to renew refresh token")
        refresh_token = await self.aquacell_api.authenticate(self.email, self.password)
        self.refresh_token = refresh_token
        data = {
            **self.config_entry.data,
            CONF_REFRESH_TOKEN: self.refresh_token,
            CONF_REFRESH_TOKEN_CREATION_TIME: datetime.now().timestamp(),
        }

        self.hass.config_entries.async_update_entry(self.config_entry, data=data)
