import shlex
import subprocess
from typing import List, Sequence, Optional, Tuple

# Global debug flag
_DEBUG_MODE = False


def set_debug_mode(enabled: bool) -> None:
    """Set debug mode to enable/disable command logging."""
    global _DEBUG_MODE
    _DEBUG_MODE = enabled


def get_debug_mode() -> bool:
    """Get current debug mode state."""
    return _DEBUG_MODE


#
# Construct the smartctl/btrfs/...  commands safely.
#


def build_smartctl_scan(device: str) -> List[str]:
    """
    Get disks available:
    """
    return shlex.split(f"smartctl --scan {shlex.quote(device)}")


def build_sudo_smartctl_a(device: str) -> List[str]:
    """
    Legacy way to retrieve info
    """
    return shlex.split(f"sudo smartctl -a {shlex.quote(device)}")


def build_sudo_smartctl_l_error(device: str) -> List[str]:
    """
    retrieve errors
    """
    return shlex.split(f"sudo smartctl -l error {shlex.quote(device)}")


def build_sudo_smartctl_x(device: str) -> List[str]:
    """
    SMART overall-health self-assessment test result:
    test in progress
    completed test in power_on_hours
    """
    return shlex.split(f"sudo smartctl -x {shlex.quote(device)}")


def build_sudo_smartctl_t_short(device: str) -> List[str]:
    """
    run short test
    """
    return shlex.split(f"sudo smartctl -t short {shlex.quote(device)}")


def build_sudo_smartctl_t_long(device: str) -> List[str]:
    """
    run long test
    """
    return shlex.split(f"sudo smartctl -t long {shlex.quote(device)}")


def build_sudo_smartctl_l_selftest(device: str) -> List[str]:
    """
    show self-test log (subset of -x )
    """
    return shlex.split(f"sudo smartctl -l selftest {shlex.quote(device)}")


# NVMe CLI command builders (for NVMe disks that don't support smartctl)


def build_nvme_smart_log(device: str) -> List[str]:
    """
    Get SMART log via nvme-cli
    """
    return shlex.split(f"sudo nvme smart-log {shlex.quote(device)}")


def build_nvme_self_test_log(device: str) -> List[str]:
    """
    Get self-test log via nvme-cli
    """
    return shlex.split(f"sudo nvme self-test-log {shlex.quote(device)}")


def build_nvme_device_self_test_status(device: str) -> List[str]:
    """
    Get current device self-test operation status via nvme-cli.
    Uses -s 0h to query the current test status.
    """
    return shlex.split(f"sudo nvme device-self-test {shlex.quote(device)} -s 0h")


def build_nvme_device_self_test_short(device: str) -> List[str]:
    """
    Start short device self-test via nvme-cli.
    Uses -s 1h to start short test.
    """
    return shlex.split(f"sudo nvme device-self-test {shlex.quote(device)} -s 1h")


def build_nvme_device_self_test_long(device: str) -> List[str]:
    """
    Start extended/long device self-test via nvme-cli.
    Uses -s 2h to start extended test.
    """
    return shlex.split(f"sudo nvme device-self-test {shlex.quote(device)} -s 2h")


def build_nvme_start_self_test(device: str, test_type: str) -> List[str]:
    """
    Start self-test via nvme-cli using device-self-test command.
    test_type: "1" for short, "2" for extended/long

    DEPRECATED: Use build_nvme_device_self_test_short() or
    build_nvme_device_self_test_long() instead.
    """
    if test_type == "1":
        return build_nvme_device_self_test_short(device)
    elif test_type == "2":
        return build_nvme_device_self_test_long(device)
    else:
        # Fallback to old command format
        return shlex.split(
            f"sudo nvme self-test {shlex.quote(device)} --test-type={test_type}"
        )


def build_sudo_btrfs_filesystem_show() -> List[str]:
    """
    list all partitions with btrfs; last info in every paragraph
    is: "path /dev/nvme0n1p1"
    """
    return shlex.split(f"sudo btrfs filesystem show")


def build_sudo_btrfs_scrub_status(mountpoint: str) -> List[str]:
    """
    Show if scrub is running. Show errors.
    """
    return shlex.split(f"sudo btrfs scrub status {shlex.quote(mountpoint)}")


def build_sudo_btrfs_scrub_start(mountpoint: str) -> List[str]:
    """
    Start scrub if it is not already running.
    """
    return shlex.split(f"sudo btrfs scrub start {shlex.quote(mountpoint)}")


def build_sudo_btrfs_device_stats(device: str) -> List[str]:
    """
    Show if scrub is running. Show errors.
    """
    return shlex.split(f"sudo btrfs device stats {shlex.quote(device)}")


def build_snapper_list_configs() -> List[str]:
    """
    Snapper operated btrfs mountpoints:
    Drop 1st 3 lines, the rest is rows with:  configname | mountpoint
    """
    return shlex.split(f"snapper list-configs")


def build_sudo_snapper_c_list(configname: str) -> List[str]:
    """
    list all snapshots
    """
    return shlex.split(f"sudo snapper -c {shlex.quote(configname)} list")


def run_command(command: Sequence[str], timeout: int = 10) -> Tuple[int, str]:
    """Execute a command and return (returncode, output).

    Args:
        command: List of command arguments
        timeout: Maximum time to wait for command completion (seconds)

    Returns:
        Tuple of (returncode, combined_stdout_stderr)
    """
    # Debug: print command being executed
    import sys

    cmd_str = " ".join(command)
    if _DEBUG_MODE:
        print(f"\n[DEBUG] >>> Executing: {cmd_str}", file=sys.stderr, flush=True)

    # Log to file for troubleshooting even without --debug
    try:
        with open("/tmp/diskmanager_debug.log", "a") as f:
            f.write(f"{cmd_str}\n")
    except:
        pass

    try:
        result = subprocess.run(
            list(command),
            capture_output=True,
            text=True,
            timeout=timeout,
            check=False,
        )
        output = result.stdout + result.stderr

        # Check for sudo password prompt or authentication failure - only print in debug mode
        if _DEBUG_MODE and result.returncode != 0:
            error_msg = ""
            if "password" in output.lower() or "sudo" in output.lower():
                error_msg = f"\n[ERROR] SUDO PASSWORD REQUIRED: {cmd_str}"
                error_msg += "\n[ERROR] This command requires sudo authentication"
            else:
                error_msg = (
                    f"\n[ERROR] Command failed (exit {result.returncode}): {cmd_str}"
                )

            # Print error in red if terminal supports it
            if sys.stderr.isatty():
                print(f"\033[91m{error_msg}\033[0m", file=sys.stderr, flush=True)
            else:
                print(error_msg, file=sys.stderr, flush=True)

        return result.returncode, output
    except subprocess.TimeoutExpired:
        if _DEBUG_MODE:
            error_msg = (
                f"\n[ERROR] Command timed out after {timeout} seconds: {cmd_str}"
            )
            if sys.stderr.isatty():
                print(f"\033[91m{error_msg}\033[0m", file=sys.stderr, flush=True)
            else:
                print(error_msg, file=sys.stderr, flush=True)
        return 1, f"Command timed out after {timeout} seconds"
    except Exception as e:
        if _DEBUG_MODE:
            error_msg = f"\n[ERROR] Command failed with exception: {cmd_str}\n  {e}"
            if sys.stderr.isatty():
                print(f"\033[91m{error_msg}\033[0m", file=sys.stderr, flush=True)
            else:
                print(error_msg, file=sys.stderr, flush=True)
        return 1, str(e)
