"""Functions for rclone and local filesystem interaction."""

import os
import subprocess
import re
from typing import List, Optional, Tuple


def check_rclone_version() -> Tuple[bool, str, str]:
    """Check rclone version and return (is_ok, version_string, message).

    Returns:
        Tuple of (is_valid: bool, version: str, message: str)
    """
    try:
        result = subprocess.run(
            ["rclone", "version"], capture_output=True, text=True, timeout=10
        )
        if result.returncode != 0:
            return False, "", "rclone not found or error executing"

        # Parse version from output like "rclone v1.73.3"
        version_match = re.search(r"rclone v(\d+\.\d+)", result.stdout)
        if not version_match:
            return False, "", "Could not parse rclone version"

        version_str = version_match.group(1)
        major, minor = map(int, version_str.split("."))

        # Check if version >= 1.73
        if major > 1 or (major == 1 and minor >= 73):
            return True, version_str, f"rclone v{version_str} (OK)"
        else:
            return False, version_str, f"rclone v{version_str} (minimum required: 1.73)"
    except FileNotFoundError:
        return False, "", "rclone not found in PATH"
    except Exception as e:
        return False, "", f"Error checking rclone: {e}"


def check_restic_version() -> Tuple[bool, str, str]:
    """Check restic version and return (is_ok, version_string, message).

    Returns:
        Tuple of (is_valid: bool, version: str, message: str)
    """
    try:
        result = subprocess.run(
            ["restic", "version"], capture_output=True, text=True, timeout=10
        )
        if result.returncode != 0:
            return False, "", "restic not found or error executing"

        # Parse version from output like "restic 0.18.1 compiled with go1.25.1 on linux/amd64"
        version_match = re.search(r"restic (\d+\.\d+)", result.stdout)
        if not version_match:
            return False, "", "Could not parse restic version"

        version_str = version_match.group(1)
        major, minor = map(int, version_str.split("."))

        # Check if version >= 0.18
        if major > 0 or (major == 0 and minor >= 18):
            return True, version_str, f"restic v{version_str} (OK)"
        else:
            return False, version_str, f"restic v{version_str} (minimum required: 0.18)"
    except FileNotFoundError:
        return False, "", "restic not found in PATH"
    except Exception as e:
        return False, "", f"Error checking restic: {e}"


def prompt_download(tool: str, download_url: str) -> bool:
    """Prompt user to download a tool.

    Args:
        tool: Name of the tool (rclone/restic)
        download_url: URL to download from

    Returns:
        True if user wants to download
    """
    import sys

    print(f"\n{'=' * 60}")
    print(f"  {tool.upper()} VERSION CHECK FAILED")
    print(f"{'=' * 60}")
    print(f"\nDownload URL: {download_url}")
    print("\nWould you like to download it now? (Y/n): ", end="")
    sys.stdout.flush()

    try:
        response = input().strip().lower()
        return response in ("", "y", "yes")
    except (EOFError, KeyboardInterrupt):
        return False


def run_command(command: List[str], timeout: int = 10) -> Tuple[int, str]:
    """Execute a command and return (returncode, output)."""
    try:
        result = subprocess.run(
            command,
            capture_output=True,
            text=True,
            timeout=timeout,
            check=False,
        )
        return result.returncode, result.stdout + result.stderr
    except subprocess.TimeoutExpired:
        return 1, "Command timed out"
    except Exception as e:
        return 1, str(e)


def list_remotes() -> List[str]:
    """Get list of rclone remotes."""
    rc, output = run_command(["rclone", "listremotes"])
    if rc != 0:
        return []
    return [line.strip() for line in output.splitlines() if line.strip()]


def list_remote_dir(remote: str, path: str = "") -> List[str]:
    """List directories and files in a remote path."""
    # The user specifically mentioned lsd, so let's ensure we get directories
    full_remote_path = f"{remote}{path}"

    # Try using lsf as primary because it's much easier to parse and handles both
    # But we'll fallback to lsd for directories as suggested if lsf seems empty/failed
    rc, output = run_command(
        ["rclone", "lsf", "--dir-slash", "--format", "p", full_remote_path]
    )

    if rc == 0 and output.strip():
        items = [line.strip() for line in output.splitlines() if line.strip()]
        dirs = sorted([i for i in items if i.endswith("/")])
        files = sorted([i for i in items if not i.endswith("/")])
        return dirs + files

    # Fallback/Supplemental: Use lsd as specifically suggested
    rc_lsd, output_lsd = run_command(["rclone", "lsd", full_remote_path])
    if rc_lsd == 0:
        dirs = []
        for line in output_lsd.splitlines():
            if line.strip():
                # lsd output looks like: "          -1 2023-10-10 10:10:10         -1 My Directory"
                # We need to correctly capture the name after the first 4 columns
                parts = line.split(None, 4)
                if len(parts) >= 5:
                    dirs.append(parts[4].strip() + "/")
        return sorted(dirs)

    return []


def list_local_dir(path: str) -> List[str]:
    """List directories and files in a local path."""
    try:
        items = os.listdir(path)
        # Add trailing slash to directories
        formatted_items = []
        for item in items:
            if os.path.isdir(os.path.join(path, item)):
                formatted_items.append(item + "/")
            else:
                formatted_items.append(item)

        # Sort: directories first, then files
        dirs = sorted([i for i in formatted_items if i.endswith("/")])
        files = sorted([i for i in formatted_items if not i.endswith("/")])
        return dirs + files
    except Exception:
        return []


def run_rclone_copy(mode: int, src: str, dst: str, dry_run: bool = False):
    """Run rclone copy command based on mode.

    Modes:
    1: Single file (copyto)
    2: Directory traversed (copy)
    3: Directory no-traverse (copy --no-traverse)
    """
    import sys
    import subprocess
    import os

    # Common exclude patterns - use /** for directories to exclude their contents
    exclude_patterns = [
        "--exclude",
        ".git/**",
        "--exclude",
        ".venv/**",
        "--exclude",
        "venv/**",
        "--exclude",
        "env/**",
        "--exclude",
        ".opencode/**",
        "--exclude",
        ".openai_*",
        "--exclude",
        ".*~",
        "--exclude",
        ".python-version",
        "--exclude",
        ".python-cache/**",
        "--exclude",
        ".pytest_cache/**",
    ]

    if mode == 1:
        # Single file copy - exclude patterns not supported
        cmd = ["rclone", "copyto", src, dst, "--progress"]
    elif mode == 2:
        cmd = ["rclone", "copy", src, dst, "--progress"] + exclude_patterns
    elif mode == 3:
        cmd = [
            "rclone",
            "copy",
            src,
            dst,
            "--progress",
            "--no-traverse",
        ] + exclude_patterns
    else:
        return

    if dry_run:
        cmd.append("--dry-run")

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    if dry_run:
        print("!!! DRY RUN MODE - No files will be copied !!!\n")
    print("-" * 60)

    try:
        # Run and allow user to see output
        result = subprocess.run(cmd, check=False)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mOperation finished successfully.\033[0m Press Enter to return to mcrc..."
            )
        else:
            print(
                f"\n\033[91mOperation failed (exit code {result.returncode}).\033[0m Press Enter to return to mcrc..."
            )

        # Use a more robust input waiting mechanism
        try:
            sys.stdin.read(1)
        except:
            pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mOperation cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_deletefile(remote_path: str):
    """Run rclone deletefile command.

    Args:
        remote_path: The remote path to the file (remote:path/to/file)
    """
    import sys
    import subprocess
    import os

    cmd = ["rclone", "deletefile", remote_path, "--progress"]

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    print("!!! WARNING: REAL DELETE MODE - File will be permanently deleted !!!\n")
    print("-" * 60)

    try:
        # Run and allow user to see output
        result = subprocess.run(cmd, check=False)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mOperation finished successfully.\033[0m Press Enter to return to mcrc..."
            )
        else:
            print(
                f"\n\033[91mOperation failed (exit code {result.returncode}).\033[0m Press Enter to return to mcrc..."
            )

        # Use a more robust input waiting mechanism
        try:
            sys.stdin.read(1)
        except:
            pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mOperation cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_purge(remote_path: str, dry_run: bool = True):
    """Run rclone purge command.

    Args:
        remote_path: The remote path to purge (remote:path/to/dir)
        dry_run: If True, adds --dry-run flag
    """
    import sys
    import subprocess
    import os

    cmd = ["rclone", "purge", remote_path, "--progress"]
    if dry_run:
        cmd.append("--dry-run")

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    if dry_run:
        print("!!! DRY RUN MODE - No files will be deleted !!!\n")
    else:
        print("!!! WARNING: REAL PURGE MODE - Files will be permanently deleted !!!\n")
    print("-" * 60)

    try:
        # Run and allow user to see output
        result = subprocess.run(cmd, check=False)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mOperation finished successfully.\033[0m Press Enter to return to mcrc..."
            )
        else:
            print(
                f"\n\033[91mOperation failed (exit code {result.returncode}).\033[0m Press Enter to return to mcrc..."
            )

        # Use a more robust input waiting mechanism
        try:
            sys.stdin.read(1)
        except:
            pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mOperation cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_sync(src: str, dst: str, dry_run: bool = True):
    """Run rclone sync command.

    Args:
        src: Source path
        dst: Destination path
        dry_run: If True, adds --dry-run flag
    """
    import sys
    import subprocess
    import os

    # Common exclude patterns - use /** for directories to exclude their contents
    exclude_patterns = [
        "--exclude",
        ".git/**",
        "--exclude",
        ".venv/**",
        "--exclude",
        "venv/**",
        "--exclude",
        "env/**",
        "--exclude",
        ".opencode/**",
        "--exclude",
        ".openai_*",
        "--exclude",
        ".*~",
        "--exclude",
        ".python-version",
        "--exclude",
        ".python-cache/**",
        "--exclude",
        ".pytest_cache/**",
    ]

    cmd = ["rclone", "sync", src, dst, "--metadata", "--progress"] + exclude_patterns
    if dry_run:
        cmd.append("--dry-run")

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    if dry_run:
        print("!!! DRY RUN MODE - No files will be deleted or moved !!!\n")
    else:
        print(
            "!!! WARNING: REAL SYNC MODE - Files in destination may be DELETED to match source !!!\n"
        )
    print("-" * 60)

    try:
        # Run and allow user to see output
        result = subprocess.run(cmd, check=False)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mOperation finished successfully.\033[0m Press Enter to return to mcrc..."
            )
        else:
            print(
                f"\n\033[91mOperation failed (exit code {result.returncode}).\033[0m Press Enter to return to mcrc..."
            )

        # Use a more robust input waiting mechanism
        try:
            sys.stdin.read(1)
        except:
            pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mOperation cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_mkdir(remote_path: str):
    """Run rclone mkdir command.

    Args:
        remote_path: The remote path to create (remote:path/to/dir)
    """
    import sys
    import subprocess
    import os

    cmd = ["rclone", "mkdir", remote_path]

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    print("-" * 60)

    try:
        # Run and allow user to see output
        result = subprocess.run(cmd, capture_output=True, text=True, check=False)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mDirectory created successfully.\033[0m Press Enter to return to mcrc..."
            )
        else:
            print(f"\n\033[91mError: {result.stderr}\033[0m")
            print("\n\033[91mOperation failed.\033[0m Press Enter to return to mcrc...")

        # Use a more robust input waiting mechanism
        try:
            sys.stdin.read(1)
        except:
            pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mOperation cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_check(src: str, dst: str):
    """Run rclone check command.

    Args:
        src: Source path
        dst: Destination path
    """
    import sys
    import subprocess
    import os
    import re
    import json
    from datetime import datetime

    # Common exclude patterns - use /** for directories to exclude their contents
    exclude_patterns = [
        "--exclude",
        ".git/**",
        "--exclude",
        ".venv/**",
        "--exclude",
        "venv/**",
        "--exclude",
        "env/**",
        "--exclude",
        ".opencode/**",
        "--exclude",
        ".openai_*",
        "--exclude",
        ".*~",
        "--exclude",
        ".python-version",
        "--exclude",
        ".python-cache/**",
        "--exclude",
        ".pytest_cache/**",
    ]

    cmd = ["rclone", "check", src, dst, "--size-only", "--progress"] + exclude_patterns

    # Clear screen for a clean output and ensure sane terminal state
    os.system("stty sane && clear")
    print(f"Executing: {' '.join(cmd)}\n")
    print("!!! INFO: Check compares files by size only, not content !!!\n")
    print("-" * 60)

    try:
        # Run and capture output while still displaying it
        result = subprocess.run(cmd, capture_output=True, text=True, check=False)

        # Display the output to user
        if result.stdout:
            print(result.stdout)
        if result.stderr:
            print(result.stderr, file=sys.stderr)

        # Call stty sane again after rclone completes
        os.system("stty sane")

        print("-" * 60)
        if result.returncode == 0:
            print(
                "\n\033[92mCheck completed - no differences found.\033[0m Press Enter to return to mcrc..."
            )
            try:
                sys.stdin.read(1)
            except:
                pass
        else:
            print(
                f"\n\033[93mCheck completed with differences (exit code {result.returncode}).\033[0m Press Enter to see details..."
            )
            try:
                sys.stdin.read(1)
            except:
                pass

            # Parse output for files with size differences
            differing_files = []
            output_text = result.stdout + result.stderr

            # Look for lines like: "2026-02-26 09:39:37 ERROR : filename: sizes differ"
            for line in output_text.split("\n"):
                if "ERROR" in line and "sizes differ" in line:
                    # Extract filename - it's between "ERROR : " and ": sizes differ"
                    match = re.search(r"ERROR\s*:\s*(.+?):\s*sizes differ", line)
                    if match:
                        filename = match.group(1).strip()
                        differing_files.append(filename)

            # Remove duplicates while preserving order
            seen = set()
            differing_files = [
                f for f in differing_files if not (f in seen or seen.add(f))
            ]

            if differing_files:
                print("\n\033[93m" + "=" * 80 + "\033[0m")
                print("\033[93mFILES WITH SIZE DIFFERENCES:\033[0m")
                print("\033[93m" + "=" * 80 + "\033[0m\n")

                for filename in differing_files:
                    print(f"\033[96mFile: {filename}\033[0m")
                    print("-" * 80)

                    # Get source file info
                    src_path = f"{src}{filename}"
                    dst_path = f"{dst}{filename}"

                    # Use rclone lsjson to get file info
                    src_info = None
                    dst_info = None

                    try:
                        src_result = subprocess.run(
                            ["rclone", "lsjson", "--stat", src_path],
                            capture_output=True,
                            text=True,
                            timeout=10,
                        )
                        if src_result.returncode == 0:
                            src_info = json.loads(src_result.stdout)
                    except:
                        pass

                    try:
                        dst_result = subprocess.run(
                            ["rclone", "lsjson", "--stat", dst_path],
                            capture_output=True,
                            text=True,
                            timeout=10,
                        )
                        if dst_result.returncode == 0:
                            dst_info = json.loads(dst_result.stdout)
                    except:
                        pass

                    # Display comparison
                    if src_info:
                        size_src = src_info.get("Size", "N/A")
                        if isinstance(size_src, int):
                            size_src = f"{size_src:,} bytes"
                        mtime_src = src_info.get("ModTime", "N/A")
                        if mtime_src and mtime_src != "N/A":
                            try:
                                # Parse ISO format timestamp
                                dt = datetime.fromisoformat(
                                    mtime_src.replace("Z", "+00:00")
                                )
                                mtime_src = dt.strftime("%Y-%m-%d %H:%M:%S")
                            except:
                                pass
                        print(f"  local:  Size: {size_src:<20}  Modified: {mtime_src}")
                    else:
                        print(
                            f"  local:  \033[91mFile not found or inaccessible\033[0m"
                        )

                    if dst_info:
                        size_dst = dst_info.get("Size", "N/A")
                        if isinstance(size_dst, int):
                            size_dst = f"{size_dst:,} bytes"
                        mtime_dst = dst_info.get("ModTime", "N/A")
                        if mtime_dst and mtime_dst != "N/A":
                            try:
                                dt = datetime.fromisoformat(
                                    mtime_dst.replace("Z", "+00:00")
                                )
                                mtime_dst = dt.strftime("%Y-%m-%d %H:%M:%S")
                            except:
                                pass
                        print(f"  remote: Size: {size_dst:<20}  Modified: {mtime_dst}")
                    else:
                        print(
                            f"  remote: \033[91mFile not found or inaccessible\033[0m"
                        )

                    print()

                print("\033[93m" + "=" * 80 + "\033[0m")
                print("Press Enter to return to mcrc...")
                try:
                    sys.stdin.read(1)
                except:
                    pass

    except KeyboardInterrupt:
        os.system("stty sane")
        print("\n\n\033[91mCheck cancelled by user.\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass
    except Exception as e:
        os.system("stty sane")
        print(f"\n\n\033[91mError in rclone execution: {e}\033[0m")
        print("Press Enter to return to mcrc...")
        try:
            sys.stdin.read(1)
        except:
            pass


def run_rclone_mount(remote_name: str, mountpoint: str) -> Tuple[bool, str]:
    """Mount a remote rclone storage at a local mountpoint.

    Args:
        remote_name: The rclone remote name (e.g., "mydrive:")
        mountpoint: The local path to mount at (e.g., "/mnt/mydrive")

    Returns:
        Tuple of (success: bool, message: str)
    """
    import os
    import subprocess
    import pwd

    try:
        # Get current user info
        user_info = pwd.getpwuid(os.getuid())
        username = user_info.pw_name
        user_id = user_info.pw_uid
        group_id = user_info.pw_gid

        # Create mountpoint directory if it doesn't exist
        if not os.path.exists(mountpoint):
            print(f"Creating mountpoint: {mountpoint}")
            try:
                os.makedirs(mountpoint, exist_ok=True)
            except Exception as e:
                return False, f"Failed to create mountpoint: {e}"

        # Set sticky bit (chmod +t)
        try:
            current_mode = os.stat(mountpoint).st_mode
            os.chmod(mountpoint, current_mode | 0o1000)  # Add sticky bit
            print(f"Set sticky bit on {mountpoint}")
        except Exception as e:
            return False, f"Failed to set sticky bit: {e}"

        # Change ownership to current user
        try:
            os.chown(mountpoint, user_id, group_id)
            print(f"Changed ownership of {mountpoint} to {username}:{username}")
        except Exception as e:
            return False, f"Failed to change ownership: {e}"

        # Build rclone mount command
        cmd = [
            "rclone",
            "mount",
            remote_name,
            mountpoint,
            "--vfs-cache-mode",
            "writes",
            "--daemon",
        ]

        print(f"\nExecuting: {' '.join(cmd)}\n")
        print("-" * 60)

        # Run mount command
        result = subprocess.run(cmd, capture_output=True, text=True, check=False)

        print("-" * 60)

        if result.returncode == 0:
            return True, f"Remote '{remote_name}' mounted successfully at {mountpoint}"
        else:
            error_msg = result.stderr if result.stderr else result.stdout
            return False, f"Mount failed: {error_msg}"

    except KeyboardInterrupt:
        return False, "Mount cancelled by user"
    except Exception as e:
        return False, f"Error in mount execution: {e}"


def run_rclone_view(
    src_path: str, is_remote: bool, editor: Optional[str] = None
) -> Tuple[bool, str]:
    """View a file using the default editor.

    For remote files, copies to /tmp first then opens.
    Supports .txt, .md, .org, .config, and files named 'config'.

    Args:
        src_path: Path to the file (local or remote)
        is_remote: True if remote file, False if local
        editor: Editor to use (defaults to $EDITOR, vi, or nano)

    Returns:
        Tuple of (success: bool, message: str)
    """
    import os
    import subprocess
    import tempfile
    import shutil

    # Determine editor
    if editor is None:
        editor = os.environ.get("EDITOR", "vi")
        # Fallback chain
        for fallback in ["nano", "vim", "vi"]:
            if shutil.which(editor):
                break
            editor = fallback

    # Check if it's a viewable file
    viewable_extensions = {".txt", ".md", ".org", ".config"}
    basename = os.path.basename(src_path)
    _, ext = os.path.splitext(basename)

    is_viewable = (
        ext.lower() in viewable_extensions
        or basename == "config"
        or ".config" in basename
    )

    if not is_viewable:
        return False, f"File type not supported for viewing: {basename}"

    tmp_file = None
    try:
        if is_remote:
            # Copy remote file to tmp
            fd, tmp_file = tempfile.mkstemp(prefix="mcrc_view_", suffix=ext)
            os.close(fd)

            print(f"Copying remote file to {tmp_file}...")
            copy_cmd = ["rclone", "copyto", src_path, tmp_file]
            result = subprocess.run(
                copy_cmd, capture_output=True, text=True, check=False
            )

            if result.returncode != 0:
                os.unlink(tmp_file)
                return False, f"Failed to copy remote file: {result.stderr}"

            file_to_edit = tmp_file
        else:
            file_to_edit = src_path

        # Open with editor
        print(f"\nOpening with {editor}: {basename}")
        print("-" * 60)

        # Clear screen and reset terminal
        os.system("stty sane && clear")

        edit_cmd = [editor, file_to_edit]
        result = subprocess.run(edit_cmd, check=False)

        print("-" * 60)

        if result.returncode == 0:
            return True, f"Viewed {basename}"
        else:
            return True, f"Editor exited with code {result.returncode}"

    except KeyboardInterrupt:
        return False, "View cancelled by user"
    except Exception as e:
        return False, f"Error viewing file: {e}"
    finally:
        # Cleanup tmp file if it was created
        if tmp_file and os.path.exists(tmp_file):
            try:
                os.unlink(tmp_file)
            except:
                pass


def run_restic_backup(
    remote_name: str, local_folder: str, backup_name: str
) -> Tuple[bool, str]:
    """Run restic backup from local folder to remote repository.

    Args:
        remote_name: The rclone remote name (e.g., "mydrive:")
        local_folder: Local folder path to backup
        backup_name: Name for the backup (will be prefixed with "restic_")

    Returns:
        Tuple of (success: bool, message: str)
    """
    import os
    import subprocess

    # Ensure backup_name starts with restic_
    if not backup_name.startswith("restic_"):
        backup_name = f"restic_{backup_name}"

    repo_path = f"rclone:{remote_name}{backup_name}"

    # Environment variables for restic
    env = os.environ.copy()
    env["RESTIC_REPOSITORY"] = repo_path

    # Check if repository exists by running snapshots
    print(f"Checking if repository {backup_name} exists...")
    check_cmd = ["restic", "snapshots", "--insecure-no-password"]
    check_result = subprocess.run(
        check_cmd, capture_output=True, text=True, env=env, timeout=30
    )

    if check_result.returncode != 0:
        print(f"Repository does not exist. Initializing {backup_name}...")
        init_cmd = ["restic", "init", "--insecure-no-password"]
        init_result = subprocess.run(init_cmd, capture_output=True, text=True, env=env)
        if init_result.returncode != 0:
            return False, f"Failed to initialize repository: {init_result.stderr}"
        print(f"Repository {backup_name} initialized successfully.")

    # Run backup
    print(f"\nStarting backup of {local_folder} to {backup_name}...")
    print("-" * 60)

    # Clear screen for clean output
    os.system("stty sane && clear")

    backup_cmd = [
        "restic",
        "backup",
        local_folder,
        "--verbose",
        "--insecure-no-password",
        "--exclude=.venv/*",
        "--exclude=uv.lock",
        "--exclude=.*~",
        "--exclude=.ruff_cache/*",
    ]

    try:
        result = subprocess.run(backup_cmd, env=env, check=False)

        print("-" * 60)

        if result.returncode == 0:
            return True, f"Backup completed successfully to {backup_name}"
        else:
            return False, f"Backup failed with exit code {result.returncode}"

    except KeyboardInterrupt:
        return False, "Backup cancelled by user"
    except Exception as e:
        return False, f"Error during backup: {e}"


def run_restic_restore(
    remote_name: str, backup_name: str, target_folder: str
) -> Tuple[bool, str]:
    """Run restic restore from remote repository to local folder.

    Args:
        remote_name: The rclone remote name (e.g., "mydrive:")
        backup_name: Backup repository name (must start with "restic_")
        target_folder: Local folder to restore to

    Returns:
        Tuple of (success: bool, message: str)
    """
    import os
    import subprocess

    # Ensure backup_name starts with restic_
    if not backup_name.startswith("restic_"):
        return False, "Invalid backup name - must start with 'restic_'"

    repo_path = f"rclone:{remote_name}{backup_name}"

    # Environment variables for restic
    env = os.environ.copy()
    env["RESTIC_REPOSITORY"] = repo_path

    # Clear screen for clean output
    os.system("stty sane && clear")

    print(f"Restoring from {backup_name} to {target_folder}...")
    print("-" * 60)

    restore_cmd = [
        "restic",
        "restore",
        "latest",
        "--target",
        target_folder,
        "--insecure-no-password",
    ]

    try:
        result = subprocess.run(restore_cmd, env=env, check=False)

        print("-" * 60)

        if result.returncode == 0:
            return True, f"Restore completed successfully to {target_folder}"
        else:
            return False, f"Restore failed with exit code {result.returncode}"

    except KeyboardInterrupt:
        return False, "Restore cancelled by user"
    except Exception as e:
        return False, f"Error during restore: {e}"


def run_restic_snapshots(remote_name: str, backup_name: str) -> Tuple[bool, str]:
    """Run restic snapshots command and return the output.

    Args:
        remote_name: The rclone remote name (e.g., "mydrive:")
        backup_name: Backup repository name (must start with "restic_")

    Returns:
        Tuple of (success: bool, output: str)
    """
    import os
    import subprocess

    # Ensure backup_name starts with restic_
    if not backup_name.startswith("restic_"):
        return False, "Invalid backup name - must start with 'restic_'"

    repo_path = f"rclone:{remote_name}{backup_name}"

    # Environment variables for restic
    env = os.environ.copy()
    env["RESTIC_REPOSITORY"] = repo_path

    # Run snapshots command
    snapshots_cmd = ["restic", "snapshots", "--insecure-no-password"]

    try:
        result = subprocess.run(
            snapshots_cmd, capture_output=True, text=True, env=env, timeout=60
        )

        if result.returncode == 0:
            return True, result.stdout
        else:
            return False, f"Error: {result.stderr}"

    except subprocess.TimeoutExpired:
        return False, "Timeout: Command took too long to execute"
    except Exception as e:
        return False, f"Error running snapshots: {e}"
