"""The tests for Z-Wave JS device triggers."""
from unittest.mock import patch

import pytest
import voluptuous_serialize
from zwave_js_server.const import CommandClass
from zwave_js_server.event import Event
from zwave_js_server.model.node import Node

from homeassistant.components import automation
from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.device_automation.exceptions import (
    InvalidDeviceAutomationConfig,
)
from homeassistant.components.zwave_js import DOMAIN, device_trigger
from homeassistant.components.zwave_js.helpers import (
    async_get_node_status_sensor_entity_id,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import (
    async_entries_for_config_entry,
    async_get as async_get_dev_reg,
)
from homeassistant.helpers.entity_registry import async_get as async_get_ent_reg
from homeassistant.setup import async_setup_component

from tests.common import (
    assert_lists_same,
    async_get_device_automations,
    async_mock_service,
)


@pytest.fixture
def calls(hass):
    """Track calls to a mock service."""
    return async_mock_service(hass, "test", "automation")


async def test_get_notification_notification_triggers(
    hass, client, lock_schlage_be469, integration
):
    """Test we get the expected triggers from a zwave_js device with the Notification CC."""
    dev_reg = async_get_dev_reg(hass)
    device = async_entries_for_config_entry(dev_reg, integration.entry_id)[0]
    expected_trigger = {
        "platform": "device",
        "domain": DOMAIN,
        "type": "event.notification.notification",
        "device_id": device.id,
        "command_class": CommandClass.NOTIFICATION,
    }
    triggers = await async_get_device_automations(
        hass, DeviceAutomationType.TRIGGER, device.id
    )
    assert expected_trigger in triggers


async def test_if_notification_notification_fires(
    hass, client, lock_schlage_be469, integration, calls
):
    """Test for event.notification.notification trigger firing."""
    node: Node = lock_schlage_be469
    dev_reg = async_get_dev_reg(hass)
    device = async_entries_for_config_entry(dev_reg, integration.entry_id)[0]

    assert await async_setup_component(
        hass,
        automation.DOMAIN,
        {
            automation.DOMAIN: [
                # event, type, label
                {
                    "trigger": {
                        "platform": "device",
                        "domain": DOMAIN,
                        "device_id": device.id,
                        "type": "event.notification.notification",
                        "command_class": CommandClass.NOTIFICATION.value,
                        "type.": 6,
                        "event": 5,
                        "label": "Access Control",
                    },
                    "action": {
                        "service": "test.automation",
                        "data_template": {
                            "some": (
                                "event.notification.notification - "
                                "{{ trigger.platform}} - "
                                "{{ trigger.event.event_type}} - "
                                "{{ trigger.event.data.command_class }}"
                            )
                        },
                    },
                },
                # no type, event, label
                {
                    "trigger": {
                        "platform": "device",
                        "domain": DOMAIN,
                        "device_id": device.id,
                        "type": "event.notification.notification",
                        "command_class": CommandClass.NOTIFICATION.value,
                    },
                    "action": {
                        "service": "test.automation",
                        "data_template": {
                            "some": (
                                "event.notification.notification2 - "
                                "{{ trigger.platform}} - "
                                "{{ trigger.event.event_type}} - "
                                "{{ trigger.event.data.command_class }}"
                            )
                        },
                    },
                },
            ]
        },
    )

    # Publish fake Notification CC notification
    event = Event(
        type="notification",
        data={
            "source": "node",
            "event": "notification",
            "nodeId": node.node_id,
            "ccId": 113,
            "args": {
                "type": 6,
                "event": 5,
                "label": "Access Control",
                "eventLabel": "Keypad lock operation",
                "parameters": {"userId": 1},
            },
        },
    )
    node.receive_event(event)
    await hass.async_block_till_done()
    assert len(calls) == 2
    assert calls[0].data[
        "some"
    ] == "event.notification.notification - device - zwave_js_notification - {}".format(
        CommandClass.NOTIFICATION
    )
    assert calls[1].data[
        "some"
    ] == "event.notification.notification2 - device - zwave_js_notification - {}".format(
        CommandClass.NOTIFICATION
    )


async def test_get_trigger_capabilities_notification_notification(
    hass, client, lock_schlage_be469, integration
):
    """Test we get the expected capabilities from a notification.notification trigger."""
    dev_reg = async_get_dev_reg(hass)
    device = async_entries_for_config_entry(dev_reg, integration.entry_id)[0]
    capabilities = await device_trigger.async_get_trigger_capabilities(
        hass,
        {
            "platform": "device",
            "domain": DOMAIN,
            "device_id": device.id,
            "type": "event.notification.notification",
            "command_class": CommandClass.NOTIFICATION.value,
        },
    )
    assert capabilities and "extra_fields" in capabilities

    assert_lists_same(
        voluptuous_serialize.convert(
            capabilities["extra_fields"], custom_serializer=cv.custom_serializer
        ),
        [
            {"name": "type.", "optional": True, "type": "string"},
            {"name": "label", "optional": True, "type": "string"},
            {"name": "event", "optional": True, "type": "string"},
            {"name": "event_label", "optional": True, "type": "string"},
        ],
    )


async def test_if_entry_control_notification_fires(
    hass, client, lock_schlage_be469, integration, calls
):
    """Test for notification.entry_control trigger firing."""
    node: Node = lock_schlage_be469
    dev_reg = async_get_dev_reg(hass)
    device = async_entries_for_config_entry(dev_reg, integration.entry_id)[0]

    assert await async_setup_component(
        hass,
        automatio
n.DOMAIN,
  
      {
            automation.DOMAIN: [
                # event_type and data_type
                {
                    "trigger": {
                        "platform": "device",
                        "domain": DOMAIN,
                        "device_id": device.id,
                        "type": "event.notification.entry_control",
                        "command_class": CommandClass.ENTRY_CONTROL.value,
                        "event_type": 5,
                        "data_type": 2,
                    },
                    "action": {
                        "service": "test.automation",
                        "data_template": {
                            "some": (
                                "event.notification.notification - "
                                "{{ trigger.platform}} - "
                                "{{ trigger.event.event_type}} - "
                                "{{ trigger.event.data.command_class }}"
                            )
                        },
                    },
                },
                # no event_type and data_type
                {
                    "trigger": {
                        "platform": "device",
                        "domain": DOMAIN,
     