import logging
from logging import Logger

from homeassistant_api import Client, HomeassistantAPIError, Domain

from cookbook.connectors.connector import Connector
from cookbook.models import ShoppingListEntry, ConnectorConfig, Space


class HomeAssistant(Connector):
    _domains_cache: dict[str, Domain]
    _config: ConnectorConfig
    _logger: Logger
    _client: Client

    def __init__(self, config: ConnectorConfig):
        if not config.token or not config.url or not config.todo_entity:
            raise ValueError("config for HomeAssistantConnector in incomplete")

        self._domains_cache = dict()
        self._config = config
        self._logger = logging.getLogger("connector.HomeAssistant")
        self._client = Client(self._config.url, self._config.token, async_cache_session=False, use_async=True)

    async def on_shopping_list_entry_created(self, space: Space, shopping_list_entry: ShoppingListEntry) -> None:
        if not self._config.on_shopping_list_entry_created_enabled:
            return

        item, description = _format_shopping_list_entry(shopping_list_entry)

        todo_domain = self._domains_cache.get('todo')
        try:
            if todo_domain is None:
                todo_domain = await self._client.async_get_domain('todo')
                self._domains_cache['todo'] = todo_domain

            logging.debug(f"pushing {item} to {self._config.name}")
            await todo_domain.add_item(entity_id=self._config.todo_entity, item=item)
        except HomeassistantAPIError as err:
            self._logger.warning(f"[HomeAssistant {self._config.name}] Received an exception from the api: {err=}, {type(err)=}")

    async def on_shopping_list_entry_updated(self, space: Space, shopping_list_entry: ShoppingListEntry) -> None:
        if not self._config.on_shopping_list_entry_updated_enabled:
            return
        pass

    async def on_shopping_list_entry_deleted(self, space: Space, shopping_list_entry: ShoppingListEntry) -> None:
        if not self._config.on_shopping_list_entry_deleted_enabled:
            return

        item, description = _format_shopping_list_entry(shopping_list_entry)

        todo_domain = self._domains_cache.get('todo')
        try:
            if todo_domain is None:
                todo_domain = await self._client.async_get_domain('todo')
                self._domains_cache['todo'] = todo_domain

            logging.debug(f"deleting {item} from {self._config.name}")
            await todo_domain.remove_item(entity_id=self._config.todo_entity, item=item)
        except HomeassistantAPIError as err:
            self._logger.warning(f"[HomeAssistant {self._config.name}] Received an exception from the api: {err=}, {type(err)=}")

    async def close(self) -> None:
        await self._client.async_cache_session.close()


def _format_shopping_list_entry(shopping_list_entry: ShoppingListEntry):
    item = shopping_list_entry.food.name
    if shopping_list_entry.amount > 0:
        item += f" ({shopping_list_entry.amount:.2f}".rstrip('0').rstrip('.')
        if shopping_list_entry.unit and shopping_list_entry.unit.base_unit and len(shopping_list_entry.unit.base_unit) > 0:
            item += f" {shopping_list_entry.unit.base_unit})"
        elif shopping_list_entry.unit and shopping_list_entry.unit.name and len(shopping_list_entry.unit.name) > 0:
            item += f" {shopping_list_entry.unit.name})"
        else:
            item += ")"

    description = "Imported by TandoorRecipes"
    if shopping_list_entry.created_by.first_name and len(shopping_list_entry.created_by.first_name) > 0:
        description += f", created by {shopping_list_entry.created_by.first_name}"
    else:
        description += f", created by {shopping_list_entry.created_by.username}"

    return item, description
