import sys
import shutil
import asyncio
import click
import tempfile
from pathlib import Path

import structlog

from .. import debugger

log = structlog.get_logger()


async def run_install_wormhole():
    proc = await asyncio.create_subprocess_exec(
        sys.executable, '-m', 'pip', 'install', 'magic-wormhole'
    )

    await proc.communicate()


async def run_wormhole(wormhole_cmd, file_name):

    proc = await asyncio.create_subprocess_exec(
        wormhole_cmd, 'send', file_name,
    )

    await proc.communicate()


def find_wormhole():
    wormhole_cmd = shutil.which('wormhole')
    if wormhole_cmd is not None:
        return wormhole_cmd
    wormhole_cmd = shutil.which(str(Path(sys.executable).parent.joinpath('wormhole')))
    if wormhole_cmd is not None:
        return wormhole_cmd


@click.command()
@click.option('--system', default='default', help="NETLAB+ system to communicate with.")
@click.option('--output-file', 'output_file', type=click.Path())
@click.option('--wormhole', is_flag=True, help="Send logs over magic-wormhole.")
@click.option('--install-wormhole', is_flag=True, help="Install magic-wormhole if needed.")
@click.pass_context
def debug(ctx, system, output_file, wormhole, install_wormhole):
    """
    This will collect debugging data that will be useful for us to assist you.
    It will:

    \b
    - Collects system data
    - Collects config and where it came from
    - Runs openssl s_client
    - Connects to a netlab and collects debug traffic
    - Collects `system_status_get`
    - Collects full traceback of all errors
    - Optional: outputs to file
    - Optional: installs magic wormhole
    - Optional: send the results over magic wormhole

    # Using magic wormhole

    https://magic-wormhole.readthedocs.io/en/latest/

    If you cannot easily collect the debug output, you can use the --wormhole
    flag to easily get the debug output at a different computer. Simply install
    magic-wormhole on the other computer and follow the instructions at the end
    if the debug output.

    Example::

    \b
        $ netlab debug --wormhole --install-wormhole
        2024-09-11 21:12:55 [info     ] writing file     path=/tmp/netlab_debug_0y5xltrx.txt
        ─────────────────────────────── Collecting system data ───────────────────────────────
        ───────────────────────────── Checking netlab sdk config ─────────────────────────────
        ───────────────────────────── Running `openssl s_client` ─────────────────────────────
        ──────────────────────────── Finished `openssl s_client` ─────────────────────────────
        ─────────────────────────── Debug data collection complete ───────────────────────────
        Sending 9.7 kB file named 'netlab_debug_0y5xltrx.txt'
        Wormhole code is: 88-headwaters-blowtorch
        On the other computer, please run:

        wormhole receive 88-headwaters-blowtorch

    In this example, you would run `wormhole receive 88-headwaters-blowtorch`
    on the reciving computer.
    """

    wormhole_cmd = find_wormhole()

    if wormhole_cmd is None and install_wormhole:
        log.info("trying to install magic-wormhole")
        asyncio.run(run_install_wormhole())

        wormhole_cmd = find_wormhole()

    if wormhole and wormhole_cmd is None:
        log.error("wormhole command not found")
        exit(1)

    if output_file is None and wormhole:
        fd, output_file = tempfile.mkstemp('.txt', 'netlab_debug_')

    if output_file:
        log.info("writing file", path=output_file)
        f = open(output_file, 'w', encoding='utf-8')
        structlog.configure(
            processors=[
                structlog.contextvars.merge_contextvars,
                structlog.processors.add_log_level,
                structlog.processors.StackInfoRenderer(),
                structlog.dev.set_exc_info,
                structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=False),
                structlog.dev.ConsoleRenderer(colors=False)
            ],
            logger_factory=structlog.PrintLoggerFactory(f)
        )

    asyncio.run(debugger.main(system=system))

    structlog.reset_defaults()

    if wormhole:
        asyncio.run(run_wormhole(wormhole_cmd, output_file))
