"""Provides device actions for Mobile App."""
from __future__ import annotations

import voluptuous as vol

from homeassistant.components import notify
from homeassistant.components.device_automation import InvalidDeviceAutomationConfig
from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_TYPE
from homeassistant.core import Context, HomeAssistant
from homeassistant.exceptions import TemplateError
from homeassistant.helpers import config_validation as cv, template
from homeassistant.helpers.typing import ConfigType, TemplateVarsType

from .const import DOMAIN
from .util import get_notify_service, supports_push, webhook_id_from_device_id

ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
    {
        vol.Required(CONF_TYPE): "notify",
        vol.Required(notify.ATTR_MESSAGE): cv.template,
        vol.Optional(notify.ATTR_TITLE): cv.template,
        vol.Optional(notify.ATTR_DATA): cv.template_complex,
    }
)


async def async_get_actions(
    hass: HomeAssistant, device_id: str
) -> list[dict[str, str]]:
    """List device actions for Mobile App devices."""
    webhook_id = webhook_id_from_device_id(hass, device_id)

    if webhook_id is None or not supports_push(hass, webhook_id):
        return []

    return [{CONF_DEVICE_ID: device_id, CONF_DOMAIN: DOMAIN, CONF_TYPE: "notify"}]


async def async_call_action_from_config(
    hass: HomeAssistant,
    config: ConfigType,
    variables: TemplateVarsType,
    context: Context | None,
) -> None:
    """Execute a device action."""
    webhook_id = webhook_id_from_device_id(hass, config[CONF_DEVICE_ID])

    if webhook_id is None:
        raise InvalidDeviceAutomationConfig(
            "Unable to resolve webhook ID from the device ID"
        )

    if (service_name := get_notify_service(hass, webhook_id)) is None:
        raise InvalidDeviceAutomationConfig(
            "Unable to find notify service for webhook ID"
        )

    service_data = {notify.ATTR_TARGET: webhook_id}

    # Render it here because we have access to variables here.
    for key in (notify.ATTR_MESSAGE, notify.ATTR_TITLE, notify.ATTR_DATA):
        if key not in config:
            continue

        value_template = config[key]
        template.attach(hass, value_template)

        try:
            service_data[key] = template.render_complex(value_template, variables)
        except TemplateError as err:
            raise InvalidDeviceAutomationConfig(
                f"Error rendering {key}: {err}"
            ) from err

    await hass.services.async_call(
        notify.DOMAIN, service_name, service_data, blocking=True, context=context
    )


async def async_get_action_capabilities(
    hass: HomeAssistant, config: ConfigType
) -> dict[str, vol.Schema]:
    """List action capabilities."""
    if config[CONF_TYPE] != "notify":
        return {}

    return {
        "extra_fields": vol.Schema(
            {
                vol.Required(notify.ATTR_MESSAGE): str,
                vol.Optional(notify.ATTR_TITLE): str,
            }
        )
    }