"""A todo platform for OurGroceries."""

import asyncio
from typing import Any, override

from homeassistant.components.todo import (
    TodoItem,
    TodoItemStatus,
    TodoListEntity,
    TodoListEntityFeature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .coordinator import OurGroceriesConfigEntry, OurGroceriesDataUpdateCoordinator


async def async_setup_entry(
    hass: HomeAssistant,
    entry: OurGroceriesConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the OurGroceries todo platform config entry."""
    coordinator = entry.runtime_data
    async_add_entities(
        OurGroceriesTodoListEntity(coordinator, sl["id"], sl["name"])
        for sl in coordinator.lists
    )


def _completion_status(item: dict[str, Any]) -> TodoItemStatus:
    if item.get("crossedOffAt", False):
        return TodoItemStatus.COMPLETED
    return TodoItemStatus.NEEDS_ACTION


class OurGroceriesTodoListEntity(
    CoordinatorEntity[OurGroceriesDataUpdateCoordinator], TodoListEntity
):
    """An OurGroceries TodoListEntity."""

    _attr_has_entity_name = True
    _attr_supported_features = (
        TodoListEntityFeature.CREATE_TODO_ITEM
        | TodoListEntityFeature.UPDATE_TODO_ITEM
        | TodoListEntityFeature.DELETE_TODO_ITEM
    )

    def __init__(
        self,
        coordinator: OurGroceriesDataUpdateCoordinator,
        list_id: str,
        list_name: str,
    ) -> None:
        """Initialize TodoistTodoListEntity."""
        super().__init__(coordinator=coordinator)
        self._list_id = list_id
        self._attr_unique_id = list_id
        self._attr_name = list_name

    @callback
    @override
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        if self.coordinator.data is None:
            self._attr_todo_items = None
        else:
            self._attr_todo_items = [
                TodoItem(
                    summary=item["name"],
                    uid=item["id"],
                    status=_completion_status(item),
                )
                for item in self.coordinator.data[self._list_id]["list"]["items"]
            ]
        super()._handle_coordinator_update()

    @override
    async def async_create_todo_item(self, item: TodoItem) -> None:
        """Create a To-do item."""
        if item.status != TodoItemStatus.NEEDS_ACTION:
            raise ValueError("Only active tasks may be created.")
        await self.coordinator.og.add_item_to_list(
            self._list_id, item.summary, auto_category=True
        )
        await self.coordinator.async_refresh()

    @override
    async def async_update_todo_item(self, item: TodoItem) -> None:
        """Update a To-do item."""
        if item.summary:
            api_items = self.coordinator.data[self._list_id]["list"]["items"]
            category = next(
                api_item.get("categoryId")
                for api_item in api_items
                if api_item["id"] == item.uid
            )
            await self.coordinator.og.change_item_on_list(
                self._list_id, item.uid, category, item.summary
            )
        if item.status is not None:
            cross_off = item.status == TodoItemStatus.COMPLETED
            await self.coordinator.og.toggle_item_crossed_off(
                self._list_id, item.uid, cross_off=cross_off
            )
        await self.coordinator.async_refresh()

    @override
    async def async_delete_todo_items(self, uids: list[str]) -> None:
        """Delete a To-do item."""
        await asyncio.gather(
            *[
                self.coordinator.og.remove_item_from_list(self._list_id, uid)
                for uid in uids
            ]
        )
        await self.coordinator.async_refresh()

    @override
    async def async_added_to_hass(self) -> None:
        """When entity is added to hass update state from existing coordinator data."""
        await super().async_added_to_hass()
        self._handle_coordinator_update()
