from unittest.mock import patch

import dbus_fast.aio as dbus_aio

from jsonargparse.typing import SecretStr

from dbus2mqtt import AppContext, config
from dbus2mqtt.config import FlowActionConfig, FlowConfig, FlowTriggerConfig, InterfaceConfig
from dbus2mqtt.dbus.dbus_client import DbusClient
from dbus2mqtt.event_broker import EventBroker
from dbus2mqtt.flow.flow_processor import FlowProcessor, FlowScheduler
from dbus2mqtt.mqtt.mqtt_client import MqttClient
from dbus2mqtt.template.templating import TemplateEngine


def mocked_app_context():

    test_config = config.Config(
        dbus=config.DbusConfig(
            subscriptions=[
                config.SubscriptionConfig(
                    bus_name="test.bus_name.*",
                    path="/",
                    interfaces=[InterfaceConfig(interface="test-interface-name")],
                )
            ]
        ),
        mqtt=config.MqttConfig(host="localhost", username="test", password=SecretStr("test")),
        flows=[],
    )

    event_broker = EventBroker()
    template_engine = TemplateEngine()
    app_context = AppContext(test_config, event_broker, template_engine)

    return app_context


def mocked_flow_processor(
    app_context: AppContext,
    triggers: list[FlowTriggerConfig],
    actions: list[FlowActionConfig],
    conditions: list[str] = [],
):

    flow_config = FlowConfig(triggers=triggers, actions=actions, conditions=conditions)

    app_context.config.dbus.subscriptions[0].flows = [flow_config]

    processor = FlowProcessor(app_context)
    return processor, flow_config


def mocked_dbus_client(app_context: AppContext):

    with patch("socket.socket", autospec=True):
        flow_scheduler = FlowScheduler(app_context)

        bus = dbus_aio.message_bus.MessageBus(bus_address="unix:path=/test-path")
        bus.unique_name = "FAKE-CONNECTION-NAME"

        dbus_client = DbusClient(app_context, flow_scheduler, bus)
        return dbus_client


def mocked_mqtt_client(app_context: AppContext):

    dbus_client = MqttClient(app_context, None)
    return dbus_client
