import asyncio
import ipaddress
import logging
import platform
import shutil
import socket
from typing import Union

from rich.console import Console

from .async_client import NetlabClient
from .config import NetlabServerConfig

log = logging.getLogger()
console = Console()


async def main(
    system: Union[str, None] = "default",
    config: Union[NetlabServerConfig, None] = None,
    config_path: Union[str, None] = None,
):
    console.rule("Collecting system data")
    release_string = None
    if platform.system() == "Linux":
        try:
            if hasattr(platform, "freedesktop_os_release"):  # TODO python>=3.10
                release_string = platform.freedesktop_os_release().get("PRETTY_NAME")
        except OSError:
            pass
    if platform.system() == "Darwin":
        release_string = str(platform.mac_ver())
    if platform.system() == "Windows":
        release_string = f"{platform.win32_edition()}-{platform.win32_ver()}"

    log.info(
        f"platform data platform={platform.platform()} python_version={platform.python_version()} system={platform.system()} os_release={release_string}",
    )

    console.rule("Checking netlab sdk config")
    try:
        client_factory = NetlabClient(system, config, config_path)
    except Exception:
        log.exception("Error getting config, cannot continue")
        return

    collected_config = client_factory._config

    host = client_factory._config.host

    try:
        ip = ipaddress.ip_address(host)
        log.info(f"host is an IP address {ip}")
    except ValueError:
        log.info("host is a hostname")
        ip = ipaddress.ip_address(socket.gethostbyname(host))
        log.info(f"host resolves {ip}")

    openssl_path = shutil.which("openssl")

    if openssl_path:
        openssl_cmd = [
            openssl_path,
            "s_client",
            "-connect",
            f"{collected_config.host}:{collected_config.port}",
        ]
        log.info(
            f"found openssl {openssl_path=} openssl_cmd={' '.join(openssl_cmd)}",
        )
    else:
        openssl_cmd = None
        log.warn("could not find openssl, will skip debugging step")

    if openssl_cmd:
        console.rule("Running `openssl s_client`")
        try:
            proc = await asyncio.create_subprocess_exec(
                *openssl_cmd,
                stdin=asyncio.subprocess.DEVNULL,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.STDOUT,
            )
            stdout, _ = await asyncio.wait_for(proc.communicate(), 10)
            log.info(stdout.decode(), extra={"highlighter": None})
        except asyncio.TimeoutError:
            log.warn("Running `openssl s_client` timed out")
            pass
        console.rule("Finished `openssl s_client`")

    log.info("connecting to netlab")
    try:
        async with client_factory as client:
            status = await client.system_status_get()
            log.info(f"netlab status {status}")
    except Exception:
        log.exception("An error occured while connecting to netlab")

    console.rule("Debug data collection complete")


if __name__ == "__main__":
    asyncio.run(main())
