# Copyright 2025 Alessandro Astone
# SPDX-License-Identifier: GPL-3.0-or-later
import tools.config
import dbus

import logging
import os
import shutil
import subprocess
import sys
import tarfile
import tempfile
import time

WAYDROID = sys.argv[0]
TARBALL = "waydroid-bugreport.tar.xz"

def logcat(output_path):
    with open(output_path, "w+") as fd:
        return subprocess.Popen(["sudo", WAYDROID, "logcat"], stdout=fd, stderr=sys.stderr, stdin=None)

def dmesg(params, output_path):
    with open(output_path, "w+") as fd:
        return subprocess.Popen(["sudo", "dmesg", "-T"] + params, stdout=fd, stderr=fd, stdin=None)

def waydroid_session(output_path):
    with open(output_path, "w+") as fd:
        return subprocess.Popen([WAYDROID, "session", "start"], stdout=fd, stderr=fd, stdin=None, start_new_session=True)

def clear_line():
    sys.stdout.write("\33[2K\r")

def sleep_progress(seconds):
    bar_length = 50
    time_increment = 0.1
    spinner_chars = ['|', '/', '-', '\\']

    iteration = 0
    time_slept = 0

    try:
        while time_slept < seconds:
            spinner_char = spinner_chars[iteration % len(spinner_chars)]
            filled_length = int(bar_length * time_slept // seconds)
            sys.stdout.write(f"[{'=' * filled_length}{' ' * (bar_length - filled_length)}] {spinner_char}\r")
            sys.stdout.flush()

            time.sleep(time_increment)
            time_slept += time_increment
            iteration += 1
        clear_line()
    except KeyboardInterrupt:
        clear_line()
        print("Interrupted.")


def bugreport(args):
    tmp = tempfile.mkdtemp()

    print("""\
The following information will be collected:
  - System kernel logs (kmsg)
  - Android system and user logs (logcat)
  - Waydroid container manager logs (/var/lib/waydroid/waydroid.log)
  - Waydroid configuration files (/var/lib/waydroid/*)

The information will be stored on your machine.

Please authenticate as administrator in order to read system logs.
""")

    try:
        subprocess.run(["sudo", "-v"], check=True)
        print()
    except FileNotFoundError:
        print("The 'sudo' command is not available. Cannot read system logs.")
        return
    except subprocess.CalledProcessError:
        print("Authentication failed or was cancelled.")
        return

    procs = []
    logfiles = []
    def logfile(name):
        file = os.path.join(tmp, name)
        logfiles.append(file)
        return file

    session = None
    try:
        session = tools.helpers.ipc.DBusContainerService().GetSession()
    except dbus.DBusException:
        pass

    if not session:
        print("Waydroid session not found. Trying to start one...")
        procs.append(waydroid_session(logfile("session.txt")))
        sleep_progress(10)
        try:
            session = tools.helpers.ipc.DBusContainerService().GetSession()
        except dbus.DBusException:
            pass

    if session:
        print("\n\
\033[1mPlease try to reproduce the problem now.\033[0m\n\
Waydroid will collect logs for up to 5 minutes. You may interrupt this operation earlier.\n\
")
        procs.append(logcat(logfile("logcat.txt")))
        procs.append(dmesg(["-w"], logfile("dmesg.txt")))
        sleep_progress(5 * 60)
    else:
        print("Session did not start\n")
        procs.append(dmesg([], logfile("dmesg.txt")))

    for p in procs:
        p.terminate()
    for p in procs:
        p.wait()

    print("Creating archive...")

    try:
        with tarfile.open(TARBALL, "w:xz", preset=9) as tar:
            files = [
                "/var/lib/waydroid/waydroid.log",
                "/var/lib/waydroid/waydroid.cfg",
                "/var/lib/waydroid/waydroid_base.prop",
                "/var/lib/waydroid/waydroid.prop",
                "/var/lib/waydroid/lxc",
            ] + logfiles

            for f in files:
                try:
                    tar.add(f, arcname=os.path.basename(f), recursive=True)
                except Exception as e:
                    logging.debug(f"Failed to archive {f}: {repr(e)}")

    except Exception as e:
        raise e
    finally:
        shutil.rmtree(tmp)

    print(f"Created \033[1m{TARBALL}\033[0m")
