"""WebSocket handlers for group CRUD operations."""

from __future__ import annotations

from typing import Any
from uuid import uuid4

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

from ..const import (
    DOMAIN,
    MAX_GROUP_TASK_REFS,
    MAX_ID_LENGTH,
    MAX_NAME_LENGTH,
    MAX_TEXT_LENGTH,
)
from ..helpers.permissions import require_write
from . import _get_global_entry, _load_global_options, _save_global_options


@websocket_api.websocket_command({vol.Required("type"): f"{DOMAIN}/groups"})
@websocket_api.async_response
async def ws_get_groups(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
) -> None:
    """Return all maintenance groups."""
    from ..const import CONF_GROUPS

    global_entry = _get_global_entry(hass)
    if global_entry is None:
        connection.send_result(msg["id"], {"groups": {}})
        return

    options = global_entry.options or global_entry.data
    groups = options.get(CONF_GROUPS, {})
    connection.send_result(msg["id"], {"groups": groups})


@websocket_api.websocket_command(
    {
        vol.Required("type"): f"{DOMAIN}/group/create",
        vol.Required("name"): vol.All(str, vol.Length(min=1, max=MAX_NAME_LENGTH)),
        vol.Optional("description", default=""): vol.All(str, vol.Length(max=MAX_TEXT_LENGTH)),
        vol.Optional("task_refs", default=[]): vol.All(
            [
                {
                    vol.Required("entry_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
                    vol.Required("task_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
                }
            ],
            vol.Length(max=MAX_GROUP_TASK_REFS),
        ),
    }
)
@require_write
@websocket_api.async_response
async def ws_create_group(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
) -> None:
    """Create a new maintenance group."""
    from ..const import CONF_GROUPS

    ctx = _load_global_options(hass, connection, msg)
    if ctx is None:
        return
    global_entry, options = ctx

    name = msg["name"].strip()
    if not name:
        connection.send_error(msg["id"], "invalid_input", "Name must not be empty")
        return

    group_id = uuid4().hex
    groups = dict(options.get(CONF_GROUPS, {}))
    groups[group_id] = {
        "name": name,
        "description": msg.get("description", ""),
        "task_refs": msg.get("task_refs", []),
    }
    options[CONF_GROUPS] = groups
    _save_global_options(hass, global_entry, options)

    connection.send_result(msg["id"], {"group_id": group_id})


@websocket_api.websocket_command(
    {
        vol.Required("type"): f"{DOMAIN}/group/update",
        vol.Required("group_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
        vol.Optional("name"): vol.All(str, vol.Length(min=1, max=MAX_NAME_LENGTH)),
        vol.Optional("description"): vol.All(str, vol.Length(max=MAX_TEXT_LENGTH)),
        vol.Optional("task_refs"): vol.All(
            [
                {
                    vol.Required("entry_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
                    vol.Required("task_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
                }
            ],
            vol.Length(max=MAX_GROUP_TASK_REFS),
        ),
    }
)
@require_write
@websocket_api.async_response
async def ws_update_group(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
) -> None:
    """Update an existing maintenance group."""
    from ..const import CONF_GROUPS

    ctx = _load_global_options(hass, connection, msg)
    if ctx is None:
        return
    global_entry, options = ctx

    groups = dict(options.get(CONF_GROUPS, {}))
    group_id = msg["group_id"]

    if group_id not in groups:
        connection.send_error(msg["id"], "not_found", "Group not found")
        return

    group = dict(groups[group_id])
    if "name" in msg:
        group["name"] = msg["name"]
    if "description" in msg:
        group["description"] = msg["description"]
    if "task_refs" in msg:
        group["task_refs"] = msg["task_refs"]

    groups[group_id] = group
    options[CONF_GROUPS] = groups
    _save_global_options(hass, global_entry, options)

    connection.send_result(msg["id"], {"success": True})


@websocket_api.websocket_command(
    {
        vol.Required("type"): f"{DOMAIN}/group/delete",
        vol.Required("group_id"): vol.All(str, vol.Length(max=MAX_ID_LENGTH)),
    }
)
@require_write
@websocket_api.async_response
async def ws_delete_group(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
) -> None:
    """Delete a maintenance group."""
    from ..const import CONF_GROUPS

    ctx = _load_global_options(hass, connection, msg)
    if ctx is None:
        return
    global_entry, options = ctx

    groups = dict(options.get(CONF_GROUPS, {}))
    group_id = msg["group_id"]

    if group_id not in groups:
        connection.send_error(msg["id"], "not_found", "Group not found")
        return

    del groups[group_id]
    options[CONF_GROUPS] = groups
    _save_global_options(hass, global_entry, options)

    connection.send_result(msg["id"], {"success": True})
