"""WebSocket commands for the Battery Fleet.

``battery_fleet/overview`` (read) returns the live aggregated view — low now,
grouped shopping needs, forecast — for the fleet task's detail. ``setup``
(admin write) creates the fleet object + type-parts + the single task.
"""

from __future__ import annotations

from typing import Any

import voluptuous as vol
from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant

from ..const import DOMAIN, MAX_ENTITY_ID_LENGTH
from ..helpers.battery_fleet import compute_overview, has_batteries, has_battery_notes
from ..helpers.battery_fleet_setup import (
    async_mark_replaced,
    async_setup_battery_fleet,
    find_fleet_entry,
    fleet_task_trigger_ok,
)
from ..helpers.permissions import require_write


@websocket_api.websocket_command({vol.Required("type"): f"{DOMAIN}/battery_fleet/overview"})
@websocket_api.async_response
async def ws_battery_fleet_overview(hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any]) -> None:
    """Return the live fleet overview (low now, needs grouped, forecast)."""
    ov = compute_overview(hass)
    fleet = find_fleet_entry(hass)
    connection.send_result(
        msg["id"],
        {
            "available": has_batteries(hass),
            "has_battery_notes": has_battery_notes(hass),
            "configured": fleet is not None,
            # False when the fleet task was deleted or its trigger was wiped
            # (issue #106) — the detail section offers a one-click repair,
            # which re-runs the idempotent setup.
            "task_ok": fleet is not None and fleet_task_trigger_ok(fleet),
            "entry_id": fleet.entry_id if fleet else None,
            "total": ov.total,
            "low": ov.low,
            "soon": ov.soon,
            "needs_now": dict(ov.needs_now),
            "needs_soon": dict(ov.needs_soon),
            "types": ov.types,
        },
    )


@websocket_api.websocket_command(
    {
        vol.Required("type"): f"{DOMAIN}/battery_fleet/setup",
        # The caller's UI language (same contract as the template WS) —
        # the created object/task/part names are localized through _T.
        vol.Optional("language"): vol.All(str, vol.Length(max=10)),
    }
)
@require_write
@websocket_api.async_response
async def ws_battery_fleet_setup(hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any]) -> None:
    """Create (or reconcile) the Battery Fleet object + type-parts + task."""
    if not has_batteries(hass):
        connection.send_error(msg["id"], "not_available", "No battery devices found")
        return
    result = await async_setup_battery_fleet(hass, language=msg.get("language"))
    connection.send_result(msg["id"], result)


@websocket_api.websocket_command(
    {
        vol.Required("type"): f"{DOMAIN}/battery_fleet/mark_replaced",
        # battery_plus entity_ids to mark; omit to mark ALL currently low.
        vol.Optional("entity_ids"): [vol.All(str, vol.Length(max=MAX_ENTITY_ID_LENGTH))],
    }
)
@require_write
@websocket_api.async_response
async def ws_battery_fleet_mark_replaced(
    hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any]
) -> None:
    """Mark batteries replaced (press their button + consume the type-parts)."""
    result = await async_mark_replaced(hass, msg.get("entity_ids"))
    connection.send_result(msg["id"], result)
