"""Todo platform for the Cookidoo integration."""

from __future__ import annotations

from typing import TYPE_CHECKING

from cookidoo_api import (
    CookidooAdditionalItem,
    CookidooException,
    CookidooIngredientItem,
)

from homeassistant.components.todo import (
    TodoItem,
    TodoItemStatus,
    TodoListEntity,
    TodoListEntityFeature,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .const import DOMAIN
from .coordinator import CookidooConfigEntry, CookidooDataUpdateCoordinator
from .entity import CookidooBaseEntity

PARALLEL_UPDATES = 0


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: CookidooConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the todo list from a config entry created in the integrations UI."""
    coordinator = config_entry.runtime_data

    async_add_entities(
        [
            CookidooIngredientsTodoListEntity(coordinator),
            CookidooAdditionalItemTodoListEntity(coordinator),
        ]
    )


class CookidooIngredientsTodoListEntity(CookidooBaseEntity, TodoListEntity):
    """A To-do List representation of the ingredients in the Cookidoo Shopping List."""

    _attr_translation_key = "ingredient_list"
    _attr_supported_features = TodoListEntityFeature.UPDATE_TODO_ITEM

    def __init__(self, coordinator: CookidooDataUpdateCoordinator) -> None:
        """Initialize the entity."""
        super().__init__(coordinator)
        assert coordinator.config_entry.unique_id
        self._attr_unique_id = f"{coordinator.config_entry.unique_id}_ingredients"

    @property
    def todo_items(self) -> list[TodoItem]:
        """Return the todo ingredients."""
        return [
            TodoItem(
                uid=item.id,
                summary=item.name,
                description=item.description or "",
                status=(
                    TodoItemStatus.COMPLETED
                    if item.is_owned
                    else TodoItemStatus.NEEDS_ACTION
                ),
            )
            for item in self.coordinator.data.ingredient_items
        ]

    async def async_update_todo_item(self, item: TodoItem) -> None:
        """Update an ingredient to the To-do list.

        Cookidoo ingredients can be changed in state, but not in summary or description. This is currently not possible to distinguish in home assistant and just fails silently.
        """
        try:
            if TYPE_CHECKING:
                assert item.uid
            await self.coordinator.cookidoo.edit_ingredient_items_ownership(
                [
                    CookidooIngredientItem(
                        id=item.uid,
                        name="",
                        description="",
                        is_owned=item.status == TodoItemStatus.COMPLETED,
                    )
                ]
            )
        except CookidooException as e:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="todo_update_item_failed",
                translation_placeholders={"name": item.summary or ""},
            ) from e

        await self.coordinator.async_refresh()


class CookidooAdditionalItemTodoListEntity(CookidooBaseEntity, TodoListEntity):
    """A To-do List representation of the additional items in the Cookidoo Shopping List."""

    _attr_translation_key = "additional_item_list"
    _attr_supported_features = (
        TodoListEntityFeature.CREATE_TODO_ITEM
        | TodoListEntityFeature.UPDATE_TODO_ITEM
        | TodoListEntityFeature.DELETE_TODO_ITEM
    )

    def __init__(self, coordinator: CookidooDataUpdateCoordinator) -> None:
        """Initialize the entity."""
        super().__init__(coordinator)
        assert coordinator.config_entry.unique_id
        self._attr_unique_id = f"{coordinator.config_entry.unique_id}_additional_items"

    @property
    def todo_items(self) -> list[TodoItem]:
        """Return the todo items."""

        return [
            TodoItem(
                uid=item.id,
                summary=item.name,
                status=(
                    TodoItemStatus.COMPLETED
                    if item.is_owned
                    else TodoItemStatus.NEEDS_ACTION
                ),
            )
            for item in self.coordinator.data.additional_items
        ]

    async def async_create_todo_item(self, item: TodoItem) -> None:
        """Add an item to the To-do list."""

        try:
            if TYPE_CHECKING:
                assert item.summary
            await self.coordinator.cookidoo.add_additional_items([item.summary])
        except CookidooException as e:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="todo_save_item_failed",
                translation_placeholders={"name": item.summary or ""},
            ) from e

        await self.coordinator.async_refresh()

    async def async_update_todo_item(self, item: TodoItem) -> None:
        """Update an item to the To-do list."""

        try:
            if TYPE_CHECKING:
                assert item.uid
                assert item.summary
            new_item = CookidooAdditionalItem(
                id=item.uid,
                name=item.summary,
                is_owned=item.status == TodoItemStatus.COMPLETED,
            )
            await self.coordinator.cookidoo.edit_additional_items_ownership([new_item])
            await self.coordinator.cookidoo.edit_additional_items([new_item])
        except CookidooException as e:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="todo_update_item_failed",
                translation_placeholders={"name": item.summary or ""},
            ) from e

        await self.coordinator.async_refresh()

    async def async_delete_todo_items(self, uids: list[str]) -> None:
        """Delete an item from the To-do list."""

        try:
            await self.coordinator.cookidoo.remove_additional_items(uids)
        except CookidooException as e:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="todo_delete_item_failed",
                translation_placeholders={"count": str(len(uids))},
            ) from e

        await self.coordinator.async_refresh()
