import json
import logging
import unittest.mock

import pytest

import intertechno_cc1101_mqtt
import intertechno_cc1101_mqtt._homeassistant

# pylint: disable=protected-access


# https://github.com/fphammerle/wireless-sensor-mqtt/blob/v0.3.0/tests/test_homeassistant.py
@pytest.mark.parametrize(
    ("object_id", "valid"),
    [
        ("raspberrypi", True),
        ("da-sh", True),
        ("under_score", True),
        ('" or ""="', False),
        ("", False),
    ],
)
def test_validate_object_id(object_id, valid):
    assert intertechno_cc1101_mqtt._homeassistant.validate_object_id(object_id) == valid


@pytest.mark.parametrize(
    ("aliases", "discovery_topics", "unique_ids", "command_topics"),
    (
        ({}, [], [], []),
        (
            {
                "some-name": {"address": 12345678, "button-index": 0},
                "another-name": {"address": 12345678, "button-index": 1},
            },
            [
                "homeassistant/switch/some-name/config",
                "homeassistant/switch/another-name/config",
            ],
            [
                "intertechno-cc1101-mqtt/aliases/some-name",
                "intertechno-cc1101-mqtt/aliases/another-name",
            ],
            ["intertechno-cc1101/some-name/set", "intertechno-cc1101/another-name/set"],
        ),
    ),
)
def test__publish_homeassistant_discovery_configs(
    caplog, aliases, discovery_topics, unique_ids, command_topics
):
    mqtt_client = unittest.mock.MagicMock()
    with caplog.at_level(logging.DEBUG):
        intertechno_cc1101_mqtt._publish_homeassistant_discovery_configs(
            mqtt_client=mqtt_client, aliases=aliases
        )
    assert mqtt_client.publish.call_count == len(aliases)
    assert all(
        not call.args and set(call.kwargs.keys()) == {"topic", "payload", "retain"}
        for call in mqtt_client.publish.call_args_list
    )
    assert [
        call.kwargs["topic"] for call in mqtt_client.publish.call_args_list
    ] == discovery_topics
    assert all(
        call.kwargs["retain"] is True for call in mqtt_client.publish.call_args_list
    )
    configs = [
        json.loads(call.kwargs["payload"])
        for call in mqtt_client.publish.call_args_list
    ]
    assert all(
        set(c.keys())
        == {"unique_id", "command_topic", "payload_on", "payload_off", "retain", "name"}
        for c in configs
    )
    assert all(
        c["payload_on"] == "ON" and c["payload_off"] == "OFF" and c["retain"] == "true"
        for c in configs
    )
    assert [c["unique_id"] for c in configs] == unique_ids
    assert [c["command_topic"] for c in configs] == command_topics
    assert [c["name"] for c in configs] == list(aliases.keys())
    assert caplog.record_tuples == [
        (
            "intertechno_cc1101_mqtt",
            logging.DEBUG,
            "publishing home assistant discovery config on topic {}".format(topic),
        )
        for topic in discovery_topics
    ]


def test__publish_homeassistant_discovery_configs_invalid_object_id(caplog):
    mqtt_client = unittest.mock.MagicMock()
    with caplog.at_level(logging.DEBUG):
        intertechno_cc1101_mqtt._publish_homeassistant_discovery_configs(
            mqtt_client=mqtt_client,
            aliases={
                "": {"address": 12345678, "button-index": 0},
                "invalid/alias": {"address": 12345678, "button-index": 0},
                "valid-alias": {"address": 12345678, "button-index": 0},
            },
        )
    assert mqtt_client.publish.call_count == 1
    assert (
        mqtt_client.publish.call_args.kwargs["topic"]
        == "homeassistant/switch/valid-alias/config"
    )
    assert caplog.record_tuples == [
        (
            "intertechno_cc1101_mqtt",
            logging.WARNING,
            "empty alias; skipping publishing of discovery config for home assistant",
        ),
        (
            "intertechno_cc1101_mqtt",
            logging.WARNING,
            "alias 'invalid/alias' contains characters unsupported by home assistant"
            " (supported characters: a-zA-Z0-9_-); skipping publishing of discovery config",
        ),
        (
            "intertechno_cc1101_mqtt",
            logging.DEBUG,
            "publishing home assistant discovery config"
            " on topic homeassistant/switch/valid-alias/config",
        ),
    ]