from __future__ import annotations

import os

from fastapi import FastAPI

from gateway_core.domain.Reboot import RebootEntity, RebootType

from gateway_node_agent.inbound.router import buildRouter
from gateway_node_agent.application.usecases.localRebootUseCase import LocalRebootUseCase
from gateway_node_agent.application.usecases.localUpgradeUseCase import LocalUpgradeUseCase

from gateway_node_agent.outbound.reboot.logindRebootAdapter import LogindRebootAdapter
from gateway_node_agent.outbound.reboot.systemdUnitRestartAdapter import SystemdUnitRestartAdapter
from gateway_node_agent.outbound.upgrade.raucUpgradeAdapter import RaucUpgradeAdapter
from gateway_platform.logind.LogindManagerClient import LogindManagerClient
from gateway_platform.systemd.SystemdManagerClient import SystemdManagerClient


def buildApp() -> FastAPI:
    """
    Build the NodeAgent FastAPI app + wire all dependencies (composition root).
    """
    isArmed = os.getenv("NODEAGENT_IS_ARMED", "false").lower() == "true"

    # platform clients
    logindClient = LogindManagerClient()
    systemdClient = SystemdManagerClient()

    # use cases
    rebootUseCase = LocalRebootUseCase(
        rebootAdapters=[
            LogindRebootAdapter(client=logindClient, isArmed=isArmed),
            SystemdUnitRestartAdapter(
                systemd=systemdClient,
                unitName="ECP.service",
                allowedEntity=RebootEntity.ecp,
                allowedType=RebootType.soft,
                isArmed=isArmed,
            ),
            SystemdUnitRestartAdapter(
                systemd=systemdClient,
                unitName="LAN.service",
                allowedEntity=RebootEntity.modem,
                allowedType=RebootType.soft,
                isArmed=isArmed,
            ),
        ]
    )

    upgradeUseCase = LocalUpgradeUseCase(executor=RaucUpgradeAdapter(isArmed=isArmed))

    # app
    app = FastAPI(title="gateway-node-agent")

    app.include_router(
        buildRouter(
            rebootUseCase=rebootUseCase,
            upgradeUseCase=upgradeUseCase,
        )
    )

    return app
