#!/usr/bin/env python3

import argparse
import os
import subprocess
import sys
import textwrap
import threading
import signal

from cli.sounds import Sound

def format_command_help(name, description, indent=2, col_width=36, width=80):
    prefix = " " * indent + f"{name:<{col_width - indent}}"
    wrapper = textwrap.TextWrapper(
        width=width,
        initial_indent=prefix,
        subsequent_indent=" " * col_width
    )
    return wrapper.fill(description)

def list_cli_commands(cli_dir):
    return sorted(
        os.path.splitext(f.name)[0] for f in os.scandir(cli_dir)
        if f.is_file() and f.name.endswith(".py") and not f.name.startswith("__")
    )

def extract_description_via_help(cli_script_path):
    try:
        result = subprocess.run(
            [sys.executable, cli_script_path, "--help"],
            capture_output=True,
            text=True,
            check=True
        )
        lines = result.stdout.splitlines()
        for i, line in enumerate(lines):
            if line.strip().startswith("usage:"):
                continue
            if line.strip() == "":
                for j in range(i+1, len(lines)):
                    desc = lines[j].strip()
                    if desc:
                        return desc
        return "-"
    except Exception:
        return "-"

def play_start_intro():
    Sound.play_start_sound()
    Sound.play_cymais_intro_sound()

def failure_with_warning_loop():
    Sound.play_finished_failed_sound()
    print("Warning: command failed. Press Ctrl+C to stop sound warnings.")
    try:
        while True:
            Sound.play_warning_sound()
    except KeyboardInterrupt:
        print("Warnings stopped by user.")

if __name__ == "__main__":
    # Parse --no-sound early and remove from args
    no_sound = False
    if '--no-sound' in sys.argv:
        no_sound = True
        sys.argv.remove('--no-sound')

    # Setup segfault handler to catch crashes
    def segv_handler(signum, frame):
        if not no_sound:
            Sound.play_finished_failed_sound()
            # Loop warning until interrupted
            try:
                while True:
                    Sound.play_warning_sound()
            except KeyboardInterrupt:
                pass
        print("Segmentation fault detected. Exiting.")
        sys.exit(1)
    signal.signal(signal.SIGSEGV, segv_handler)

    # Play intro sounds
    if not no_sound:
        threading.Thread(target=play_start_intro, daemon=True).start()

    # Change to script directory
    script_dir = os.path.dirname(os.path.realpath(__file__))
    cli_dir = os.path.join(script_dir, "cli")
    os.chdir(script_dir)

    available_cli_commands = list_cli_commands(cli_dir)

            # Handle help invocation
    if len(sys.argv) == 1 or sys.argv[1] in ('-h', '--help'):
        print("CyMaIS CLI – proxy to tools in ./cli/")
        print("Usage: cymais [--no-sound] <command> [options]")
        print("Options:")
        print("  --no-sound        Suppress all sounds during execution")
        print("  -h, --help        Show this help message and exit")
        print("Available commands:")
        for cmd in available_cli_commands:
            path = os.path.join(cli_dir, f"{cmd}.py")
            desc = extract_description_via_help(path)
            print(format_command_help(cmd, desc))
        sys.exit(0)

    # Special-case per-command help
    if len(sys.argv) >= 3 and sys.argv[1] in available_cli_commands and sys.argv[2] in ('-h', '--help'):
        subprocess.run([sys.executable, os.path.join(cli_dir, f"{sys.argv[1]}.py"), "--help"])
        sys.exit(0)

    # Execute chosen command
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('cli_command', choices=available_cli_commands)
    parser.add_argument('cli_args', nargs=argparse.REMAINDER)
    args = parser.parse_args()

    cmd_path = os.path.join(cli_dir, f"{args.cli_command}.py")
    full_cmd = [sys.executable, cmd_path] + args.cli_args

    try:
        proc = subprocess.Popen(full_cmd)
        proc.wait()
        rc = proc.returncode
        if rc != 0:
            print(f"Command '{args.cli_command}' failed with exit code {rc}.")
            failure_with_warning_loop()
            sys.exit(rc)
        else:
            if not no_sound:
                Sound.play_finished_successfully_sound()
            sys.exit(0)
    except Exception as e:
        print(f"Exception running command: {e}")
        failure_with_warning_loop()
        sys.exit(1)
