import os

from dbus_next import DBusError, InvalidObjectPathError
from dbus_next.constants import BusType
from dbus_next.aio import MessageBus


from fastapi import (  # noqa: F401
    APIRouter,
    Body,
    Cookie,
    Depends,
    Form,
    Header,
    Path,
    Query,
    Response,
    Security,
    status,
    HTTPException,
    UploadFile,
)
from typing import Dict, List, Union, Any  # noqa: F401

from . import appData
from server.data.definitions import API_SUB_PATH, ECP_WORK_FILES_DIR, Paths, SystemdServices, SystemdData
from server.models.device_info import DeviceInfo
from server.models.error import Error
from server.models.extra_models import TokenModel  # noqa: F401
from ..utils.app_data import setup_app_data

PATH_ECP_WORK_DIR = f"{os.environ.get(ECP_WORK_FILES_DIR, Paths.DEFAULT_ECP_WORK_DIR.value)}"
PATH_ECP_CONFIGS_DIR = f"{PATH_ECP_WORK_DIR}/{Paths.ECP_CONFIGS_SUBDIR.value}"


router = APIRouter(prefix=API_SUB_PATH)


@router.get(
    "/info",
    responses={
        200: {"model": DeviceInfo, "description": "Get information about the device"},
        400: {"model": Error, "description": "Bad request"},
    },
    tags=["info"],
    response_model_by_alias=True,
)
async def device_info_get() -> DeviceInfo:
    await setup_app_data()

    return DeviceInfo(
        serial=appData.serial,
        deviceId=appData.deviceId,
        ecpVersion=appData.ecpVersion,
        msiiVersion=appData.msiiVersion,
        osReleaseVersion=appData.osReleaseVersion,
        rescueOsVersion=appData.rescueOsVersion,
        role=appData.role,
    )


@router.get(
    "/systemd",
    responses={
        200: {"model": List[SystemdData], "description": "Get information about the systemd services"},
        400: {"model": Error, "description": "Bad request"},
    },
    tags=["info"],
    response_model_by_alias=True,
)
async def systemd_get() -> List[SystemdData]:
    # Do not execute when running in a docker
    if os.path.exists("/.dockerenv"):
        found_units = []

        found_units.append(
            SystemdData(
                name="ECP.service",
                description="EVTEC ECP",
                status_loaded="loaded",
                status_active="active",
                status_running="running",
            )
        )

        found_units.append(
            SystemdData(
                name="LAN.service",
                description="EVTEC LAN",
                status_loaded="loaded",
                status_active="active",
                status_running="exited",
            )
        )

        return found_units

    try:
        # Connect to the system bus
        bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
        api = await bus.introspect("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
        systemd_proxy = bus.get_proxy_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1", api)

        # look here under functions with debugger for full informations of all possible methods
        manager = systemd_proxy.get_interface("org.freedesktop.systemd1.Manager")

        # Get the unit object path
        units = await manager.call_list_units()
    except (AttributeError, DBusError, InvalidObjectPathError, TypeError, IndexError, EOFError) as e:
        print(e)

    # Get the names of all  EVTEC systemd services
    service_names = [service.value for service in SystemdServices]

    # Find the active units filtered by EVTEC relevant units
    found_units = []

    for unit in units:
        # Check if the name of any SystemdServices is in unit[0]
        for service_name in service_names:
            if service_name == unit[0]:
                unit_meta_data = SystemdData(
                    name=unit[0],
                    description=unit[1],
                    status_loaded=unit[2],
                    status_active=unit[3],
                    status_running=unit[4],
                )
                found_units.append(unit_meta_data)

    # Disconnect the bus again
    if bus:
        bus.disconnect()

    return found_units
