# Copyright 2024 sysmocom - s.f.m.c. GmbH
# SPDX-License-Identifier: GPL-3.0-or-later
import datetime
import fnmatch
import json
import logging
import os
import shlex
import shutil
import subprocess
import testenv
import testenv.daemons
import testenv.testdir

executable_path = None


def executable_is_relevant(exe):
    if testenv.args.binary_repo:
        patterns = [
            "*/usr/bin/open5gs-*",
            "*/usr/bin/osmo-*",
        ]

        for pattern in patterns:
            if fnmatch.fnmatch(exe, pattern):
                return True
    else:
        if exe.startswith(testenv.args.cache):
            return True

    return False


def get_from_coredumpctl():
    global executable_path

    logging.info("Looking for a coredump")

    if not shutil.which("coredumpctl"):
        logging.debug("coredumpctl is not available, won't try to get coredump")
        return

    # Check for any coredump within last 3 seconds
    since = (datetime.datetime.now() - datetime.timedelta(seconds=3)).strftime("%Y-%m-%d %H:%M:%S")
    cmd = ["coredumpctl", "-q", "-S", since, "--json=short", "-n1"]
    logging.debug(f"+ {cmd}")

    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        logging.debug("No coredump found")
        return

    # Check if the coredump executable is from osmo-*, open5gs-*, etc.
    coredump = json.loads(p.stdout)[0]
    if not executable_is_relevant(coredump["exe"]):
        logging.debug("Found an unrelated coredump, ignoring")
        return

    logging.debug("Coredump found, copying to log dir")
    core_path = f"{testenv.testdir.testdir}/core"
    testenv.cmd.run(
        ["coredumpctl", "dump", "-q", "-S", since, "-o", core_path, str(coredump["pid"]), coredump["exe"]],
        stdout=subprocess.DEVNULL,
        no_podman=True,
    )

    executable_path = coredump["exe"]


def get_backtrace():
    global executable_path

    core_path = f"{testenv.testdir.testdir}/core"
    if not executable_path or not os.path.exists(core_path):
        return

    logging.info("Running gdb to get a backtrace")

    cmd = "gdb"
    cmd += " --batch"
    cmd += f" {shlex.quote(executable_path)}"
    cmd += f" {shlex.quote(core_path)}"
    cmd += " -ex bt"
    cmd += f" | tee {shlex.quote(core_path)}.backtrace"

    testenv.cmd.run(cmd)

    executable_path = None