"""Main CLI entry point for the disk manager application."""

import click
import curses
import sys
import time

# from p20260130_12_kilo01.disk_scanner import scan_disks
# from p20260130_12_kilo01.ui import DiskManagerUI
from jusfltuls.disk_scanner import scan_disks
from jusfltuls.shell_calls import (
    run_command,
    build_sudo_smartctl_x,
    build_sudo_btrfs_device_stats,
    build_sudo_btrfs_scrub_status,
    build_sudo_snapper_c_list,
    build_nvme_smart_log,
    build_nvme_device_self_test_status,
    set_debug_mode,
)
from jusfltuls.nvme_cli import check_nvme_cli_available, is_nvme_device
from jusfltuls.ui import DiskManagerUI


def check_nvme_tools(disks: list) -> tuple[bool, str]:
    """Check if nvme utility is installed when NVMe devices are present.

    Args:
        disks: List of Disk objects from scan_disks()

    Returns:
        Tuple of (ok, message) - ok is True if no NVMe devices or nvme is available
    """
    has_nvme = any(is_nvme_device(disk.device_path) for disk in disks)

    if not has_nvme:
        return True, ""

    # Check if nvme CLI is available
    if not check_nvme_cli_available():
        return False, (
            "NVMe devices detected but 'nvme' CLI utility is not installed.\n"
            "Please install nvme-cli package:\n"
            "  - Debian/Ubuntu: sudo apt install nvme-cli\n"
            "  - RHEL/CentOS: sudo yum install nvme-cli\n"
            "  - Arch: sudo pacman -S nvme-cli"
        )

    return True, ""


def check_sudo_access() -> tuple[bool, list[str]]:
    """Check if all required sudo commands can run without password.

    Returns:
        Tuple of (all_ok, list_of_failed_commands)
    """
    # List of commands to test with a sample device/mountpoint
    # We prepend "-n" to tell sudo not to prompt for password
    test_commands = [
        ("smartctl", lambda: ["sudo", "-n"] + build_sudo_smartctl_x("/dev/null")[1:]),
        (
            "btrfs device stats",
            lambda: ["sudo", "-n"] + build_sudo_btrfs_device_stats("/dev/null")[1:],
        ),
        (
            "btrfs scrub status",
            lambda: ["sudo", "-n"] + build_sudo_btrfs_scrub_status("/")[1:],
        ),
        (
            "snapper list",
            lambda: ["sudo", "-n"] + build_sudo_snapper_c_list("root")[1:],
        ),
        ("nvme smart-log", lambda: ["sudo", "-n"] + build_nvme_smart_log("/dev/null")[1:]),
        ("nvme device-self-test", lambda: ["sudo", "-n"] + build_nvme_device_self_test_status("/dev/null")[1:]),
    ]

    failed_commands = []

    for name, cmd_builder in test_commands:
        try:
            cmd = cmd_builder()
            returncode, output = run_command(cmd, timeout=5)

            # Check if sudo requires password (sudo -n returns error if password needed)
            # Typical error: "sudo: a password is required" or exit code != 0
            if returncode != 0:
                # Check for common password-related error messages
                output_lower = output.lower()
                if any(
                    msg in output_lower
                    for msg in ["password is required", "password:", "sorry, try again"]
                ):
                    failed_commands.append(name)
                elif "sudo" in output_lower and returncode == 1:
                    # Likely permission denied or requires password
                    failed_commands.append(name)
        except Exception:
            failed_commands.append(name)

    return len(failed_commands) == 0, failed_commands


def show_sudo_warning(failed_commands: list[str]) -> bool:
    """Show warning about missing sudo permissions and ask user what to do.

    Returns:
        True if user wants to continue, False to quit
    """
    print("\n" + "=" * 70, file=sys.stderr)
    print("  SUDO PERMISSION CHECK FAILED", file=sys.stderr)
    print("=" * 70, file=sys.stderr)
    print("\nThe following commands require passwordless sudo access:", file=sys.stderr)
    print("\n  Commands that need visudo configuration:", file=sys.stderr)
    for cmd in failed_commands:
        print(f"    - {cmd}", file=sys.stderr)

    print("\n" + "-" * 70, file=sys.stderr)
    print("REQUIRED VISUDO CONFIGURATION:", file=sys.stderr)
    print("-" * 70, file=sys.stderr)
    print("\nAdd this line to /etc/sudoers (using 'sudo visudo'):", file=sys.stderr)
    print(
        "\n  myuser ALL=(ALL) NOPASSWD: /usr/sbin/smartctl, /usr/bin/btrfs, /usr/bin/snapper, /usr/sbin/nvme",
        file=sys.stderr,
    )
    print("\nReplace 'myuser' with your actual username.", file=sys.stderr)
    print(
        "\nOr run this command (replace USERNAME with your username):", file=sys.stderr
    )
    print(
        '  echo "USERNAME ALL=(ALL) NOPASSWD: /usr/sbin/smartctl, /usr/bin/btrfs, /usr/bin/snapper, /usr/sbin/nvme" | sudo tee /etc/sudoers.d/diskmanager',
        file=sys.stderr,
    )
    print("-" * 70, file=sys.stderr)
    print("\nWithout passwordless sudo, some features will not work.", file=sys.stderr)
    print("=" * 70 + "\n", file=sys.stderr)

    while True:
        response = input("Continue anyway? [y/N]: ").strip().lower()
        if response in ("y", "yes"):
            return True
        elif response in ("n", "no", ""):
            return False
        else:
            print("Please enter 'y' or 'n'")


def run_ui(stdscr, refresh_interval: int = 10) -> None:
    """Main UI loop using curses.

    Args:
        stdscr: Curses window object
        refresh_interval: Auto-refresh interval in seconds
    """
    # Initialize UI
    ui = DiskManagerUI(stdscr)
    ui.left_panel.is_active = True

    # Initial disk scan
    disks, error = scan_disks()
    if error:
        ui.set_error(error)
    ui.update_disks(disks)

    # Load health info for all disks on startup
    for idx in range(len(disks)):
        ui.load_disk_health(idx)
    ui._update_left_panel()

    # Draw initial UI
    ui.draw()

    # Track last refresh time
    last_refresh = time.time()

    # Main loop - only redraw on user input or timer
    stdscr.nodelay(True)  # Non-blocking input
    while True:
        # Get user input (non-blocking)
        try:
            key = stdscr.getch()
        except KeyboardInterrupt:
            break

        # Check for auto-refresh
        current_time = time.time()
        needs_redraw = False

        if refresh_interval > 0 and (current_time - last_refresh) >= refresh_interval:
            # Auto-refresh: reload health info for all disks and update scrub status
            ui.set_status("refresh")
            for idx in range(len(ui.disks)):
                ui.load_disk_health(idx)
            ui._update_left_panel()
            ui.update_scrub_status()
            ui._update_all_partitions_panel()
            last_refresh = current_time
            needs_redraw = True

        # Also update scrub status on every keypress for responsiveness
        if key != -1:
            ui.update_scrub_status()

        # Handle input
        if key == ord("q") or key == ord("Q"):
            break
        elif key == ord("r") or key == ord("R"):
            # Manual refresh - reload health info for all disks to update test progress
            disks, error = scan_disks()
            if error:
                ui.set_error(error)
            else:
                ui.clear_messages()
            ui.update_disks(disks)
            # Reload health info for all disks to get updated test progress
            for idx in range(len(disks)):
                ui.load_disk_health(idx)
            ui._update_left_panel()
            needs_redraw = True
        elif key == ord("t") or key == ord("T"):
            # Start short self-test for selected disk
            if ui.active_panel == "left":
                selected_idx = ui.left_panel.selected_index
                success, message = ui.start_short_test(selected_idx)
                if success:
                    ui.set_status(message)
                else:
                    ui.set_error(message)
                ui._update_left_panel()
                needs_redraw = True
        elif key == ord("l") or key == ord("L"):
            # Start long self-test for selected disk
            if ui.active_panel == "left":
                selected_idx = ui.left_panel.selected_index
                success, message = ui.start_long_test(selected_idx)
                if success:
                    ui.set_status(message)
                else:
                    ui.set_error(message)
                ui._update_left_panel()
                needs_redraw = True
        elif key == ord("s") or key == ord("S"):
            # Start btrfs scrub for selected partition in right panel
            if ui.active_panel == "right":
                selected_idx = ui.right_panel.selected_index
                success, message = ui.start_btrfs_scrub(selected_idx)
                if success:
                    ui.set_status(message)
                    ui._update_all_partitions_panel()
                else:
                    ui.set_error(message)
                needs_redraw = True
        elif key == ord("\t") or key == 9:  # Tab key
            ui.switch_panel()
            needs_redraw = True
        elif key == curses.KEY_UP:
            ui.move_up()
            needs_redraw = True
        elif key == curses.KEY_DOWN:
            ui.move_down()
            needs_redraw = True
        elif key == curses.KEY_LEFT:
            if ui.active_panel == "right":
                ui.switch_panel()
                needs_redraw = True
        elif key == curses.KEY_RIGHT:
            if ui.active_panel == "left":
                ui.switch_panel()
                needs_redraw = True

        # Redraw when something changed
        if needs_redraw:
            ui.draw()

        # Small sleep to prevent CPU spinning
        time.sleep(0.1)


@click.command()
@click.option(
    "--refresh",
    "-r",
    default=10,
    help="Auto-refresh interval in seconds (0 to disable).",
    type=int,
)
@click.option(
    "--debug",
    "-d",
    is_flag=True,
    default=False,
    help="Enable debug mode to show all command executions.",
)
@click.version_option(package_name="jusfltuls", prog_name="jusfltuls")
def main(refresh: int, debug: bool) -> None:
    """
    Midnight Commander-style disk manager.

    Displays disks and partitions in a two-panel interface.
    Navigate with arrow keys, switch panels with Tab, quit with 'q'.
    """
    # Set global debug mode
    set_debug_mode(debug)

    # Check sudo access before starting
    all_ok, failed_commands = check_sudo_access()
    if not all_ok:
        if not show_sudo_warning(failed_commands):
            print(
                "\nExiting. Please configure sudo permissions and try again.",
                file=sys.stderr,
            )
            sys.exit(1)
        print("\nContinuing without full sudo permissions...\n", file=sys.stderr)

    # Scan disks and check for nvme tools if needed
    disks, error = scan_disks()
    if error:
        print(f"\nError scanning disks: {error}", file=sys.stderr)
        sys.exit(1)

    nvme_ok, nvme_message = check_nvme_tools(disks)
    if not nvme_ok:
        print("\n" + "=" * 70, file=sys.stderr)
        print("  NVME TOOLS NOT FOUND", file=sys.stderr)
        print("=" * 70, file=sys.stderr)
        print(f"\n{nvme_message}", file=sys.stderr)
        print("=" * 70 + "\n", file=sys.stderr)

    try:
        # Run the curses UI with refresh interval
        curses.wrapper(lambda stdscr: run_ui(stdscr, refresh))
    except Exception as e:
        click.echo(f"Error: {e}", err=True)
        raise click.Abort()


if __name__ == "__main__":
    main()
