from __future__ import annotations

import asyncio
import contextlib
import logging
from typing import Any

from gateway_core.application.ports.NodesPort import NodesPort

from gateway_core.application.usecases.SystemInfoUseCase import SystemInfoUseCase

from gateway_integration_deltagrid.inbound.DeltaGridMqttCommandListener import DeltaGridMqttCommandListener
from gateway_integration_deltagrid.inbound.RpcRouter import RpcRouter
from gateway_integration_deltagrid.outbound.DeltaGridMqttOutboundAdapter import DeltaGridMqttOutboundAdapter
from gateway_platform.filessystem.LinuxFileSystemAdapter import LinuxFileSystemAdapter
from gateway_platform.nodeAgent.HttpNodeAgentAdapter import HttpNodeAgentAdapter
from gateway_runtime.RuntimeConfig import IntegrationConfig
from gateway_transport.http.FileTransferClient import FileTransferClient
from gateway_transport.mqtt.PahoMqttClient import PahoMqttClient

logger = logging.getLogger(__name__)

class DeltaGridIntegration:
    def __init__(
        self,
        mqttClient: PahoMqttClient,
        listener: DeltaGridMqttCommandListener,
        systemInfoUseCase: SystemInfoUseCase,
    ) -> None:
        self._task: asyncio.Task | None = None
        self._mqtt = mqttClient
        self._listener = listener
        self._systemInfoUseCase = systemInfoUseCase

    async def start(self) -> None:
        self._task = asyncio.create_task(self._mqtt.runForever())
        await self._mqtt.waitConnected(timeout=10)
        await self._listener.registerCallbacks()

        # send boot notification message
        await self._systemInfoUseCase.execute()

    async def stop(self) -> None:
        if self._task:
            self._task.cancel()
            with contextlib.suppress(asyncio.CancelledError):
                await self._task

def _asBool(value: Any) -> bool:
    """
    Convert common env / config representations to bool.
    Avoids bool("false") == True.
    """
    if isinstance(value, bool):
        return value
    if value is None:
        return False
    if isinstance(value, (int, float)):
        return bool(value)
    if isinstance(value, str):
        return value.strip().lower() in ("1", "true", "yes", "on")
    return bool(value)

async def buildDeltaGridIntegration(*, integrationConfig: IntegrationConfig, nodes: NodesPort):
    mqttCfg = integrationConfig.mqtt

    logger.info("DeltaGridIntegrationFactory: nodeDiscovery=%s", nodes)

    useTls = _asBool(mqttCfg.get("tls", False))
    port = int(mqttCfg.get("port", 8883 if useTls else 1883))
    cafile = (
        mqttCfg.get("cafile")
        or mqttCfg.get("caFile")
        or mqttCfg.get("caCert")
    )

    mqttClient = PahoMqttClient(
        host=mqttCfg["host"],
        port=port,
        useTls=useTls,
        cafile=cafile,
        username=mqttCfg.get("username"),
        password=mqttCfg.get("password"),
    )

    # platform clients
    deltaGridOutboundAdapter = DeltaGridMqttOutboundAdapter(mqttClient=mqttClient)

    router = RpcRouter(
        notifier=deltaGridOutboundAdapter,
        nodes=nodes,
        nodeAgent = HttpNodeAgentAdapter(),
        fileSystemAdapter = LinuxFileSystemAdapter(),
        fileTransferClient=FileTransferClient(),
    )

    listener = DeltaGridMqttCommandListener(
        mqttClient=mqttClient,
        router=router,
        commandTopic=mqttCfg.get("rpcTopic", "cpsp/rpc"),
    )

    return DeltaGridIntegration(
        mqttClient=mqttClient,
        listener=listener,
        systemInfoUseCase=SystemInfoUseCase(notifier=deltaGridOutboundAdapter),
    )
