"""Midnight Commander-style TUI for rclone."""

import curses
import os
import socket
from typing import List, Optional, Tuple


class Panel:
    """Represents a panel in the MC-style interface."""

    def __init__(self, name: str):
        self.name = name
        self.items: List[str] = []
        self.selected_index = 0
        self.is_active = False
        self.offset = 0  # Offset for scrolling

    def set_items(self, items: List[str]) -> None:
        """Set the items to display in the panel."""
        self.items = items
        # Ensure selected index is within bounds
        if self.selected_index >= len(self.items):
            self.selected_index = max(0, len(self.items) - 1)
        if self.offset >= len(self.items):
            self.offset = 0

    def move_up(self) -> None:
        """Move selection up."""
        if self.selected_index > 0:
            self.selected_index -= 1
            if self.selected_index < self.offset:
                self.offset = self.selected_index

    def move_down(self, height: int) -> None:
        """Move selection down."""
        if self.selected_index < len(self.items) - 1:
            self.selected_index += 1
            if self.selected_index >= self.offset + height:
                self.offset = self.selected_index - height + 1

    def move_home(self) -> None:
        """Move selection to top."""
        self.selected_index = 0
        self.offset = 0

    def move_end(self, height: int) -> None:
        """Move selection to bottom."""
        if self.items:
            self.selected_index = len(self.items) - 1
            if self.selected_index >= height:
                self.offset = self.selected_index - height + 1
            else:
                self.offset = 0

    def move_pgup(self, height: int) -> None:
        """Move selection up by height."""
        self.selected_index = max(0, self.selected_index - height)
        if self.selected_index < self.offset:
            self.offset = self.selected_index

    def move_pgdown(self, height: int) -> None:
        """Move selection down by height."""
        if self.items:
            self.selected_index = min(len(self.items) - 1, self.selected_index + height)
            if self.selected_index >= self.offset + height:
                self.offset = self.selected_index - height + 1

    def get_selected_item(self) -> Optional[str]:
        """Get the currently selected item."""
        if 0 <= self.selected_index < len(self.items):
            return self.items[self.selected_index]
        return None


class RcloneManagerUI:
    """Midnight Commander-style rclone UI."""

    # Color pairs
    COLOR_NORMAL = 1
    COLOR_SELECTED = 2
    COLOR_HEADER = 3
    COLOR_BORDER = 4
    COLOR_FOOTER = 5
    COLOR_DIR = 6

    def __init__(self, stdscr):
        self.stdscr = stdscr
        self.left_panel = Panel("Local")
        self.right_panel = Panel("Remote")
        self.active_panel = "left"  # "left" or "right"
        self.error_message: Optional[str] = None
        self.status_message: Optional[str] = None

        self.local_path = os.getcwd()
        self.remote_name = ""
        self.remote_path = ""

        # Initialize curses
        curses.noecho()
        curses.cbreak()
        self.stdscr.keypad(True)
        curses.curs_set(0)  # Hide cursor
        self.stdscr.nodelay(True)  # Non-blocking input
        self._init_colors()

        # Get terminal dimensions
        self.height, self.width = self.stdscr.getmaxyx()

    def _init_colors(self) -> None:
        """Initialize color pairs."""
        if curses.has_colors():
            curses.start_color()
            try:
                curses.use_default_colors()
                bg = -1
            except:
                bg = curses.COLOR_BLACK

            # Define color pairs
            curses.init_pair(self.COLOR_NORMAL, curses.COLOR_WHITE, bg)
            curses.init_pair(self.COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_CYAN)
            curses.init_pair(self.COLOR_HEADER, curses.COLOR_WHITE, curses.COLOR_BLUE)
            curses.init_pair(self.COLOR_BORDER, curses.COLOR_CYAN, bg)
            curses.init_pair(self.COLOR_FOOTER, curses.COLOR_BLACK, curses.COLOR_WHITE)
            curses.init_pair(self.COLOR_DIR, curses.COLOR_YELLOW, bg)

    def update_local(self) -> None:
        """Update local directory listing."""
        from jusfltuls.rclone_scanner import list_local_dir

        items = list_local_dir(self.local_path)
        if self.local_path != "/":
            items = [".."] + items
        self.left_panel.set_items(items)

    def update_remote(self) -> None:
        """Update remote directory listing."""
        if not self.remote_name:
            return
        from jusfltuls.rclone_scanner import list_remote_dir

        items = list_remote_dir(self.remote_name, self.remote_path)
        if self.remote_path:
            items = [".."] + items
        self.right_panel.set_items(items)

    def switch_panel(self) -> None:
        """Switch between left and right panels."""
        if self.active_panel == "left":
            self.active_panel = "right"
            self.left_panel.is_active = False
            self.right_panel.is_active = True
        else:
            self.active_panel = "left"
            self.left_panel.is_active = True
            self.right_panel.is_active = False

    def move_up(self) -> None:
        """Move selection up in active panel."""
        if self.active_panel == "left":
            self.left_panel.move_up()
        else:
            self.right_panel.move_up()

    def move_down(self) -> None:
        """Move selection down in active panel."""
        panel_height = self.height - 6  # Estimated height for content
        if self.active_panel == "left":
            self.left_panel.move_down(panel_height)
        else:
            self.right_panel.move_down(panel_height)

    def move_home(self) -> None:
        """Move selection to top in active panel."""
        if self.active_panel == "left":
            self.left_panel.move_home()
        else:
            self.right_panel.move_home()

    def move_end(self) -> None:
        """Move selection to bottom in active panel."""
        panel_height = self.height - 6
        if self.active_panel == "left":
            self.left_panel.move_end(panel_height)
        else:
            self.right_panel.move_end(panel_height)

    def move_pgup(self) -> None:
        """Move selection up by height in active panel."""
        panel_height = self.height - 6
        if self.active_panel == "left":
            self.left_panel.move_pgup(panel_height)
        else:
            self.right_panel.move_pgup(panel_height)

    def move_pgdown(self) -> None:
        """Move selection down by height in active panel."""
        panel_height = self.height - 6
        if self.active_panel == "left":
            self.left_panel.move_pgdown(panel_height)
        else:
            self.right_panel.move_pgdown(panel_height)

    def _safe_addstr(self, y: int, x: int, text: str, attr: int = 0) -> None:
        """Safely add a string to the screen, handling boundary issues."""
        try:
            if x < self.width and y < self.height:
                max_len = self.width - x
                if max_len > 0:
                    self.stdscr.addnstr(y, x, text, max_len, attr)
        except curses.error:
            pass

    def draw(self) -> None:
        """Draw the complete UI."""
        self.stdscr.clear()
        self.height, self.width = self.stdscr.getmaxyx()

        # Calculate panel dimensions
        panel_width = (self.width - 3) // 2
        panel_height = self.height - 4  # Leave room for header and footer

        # Draw header
        self._draw_header()

        # Draw left panel (Local)
        self._draw_panel(
            self.left_panel,
            1,
            0,
            panel_height,
            panel_width,
            f"Local: {self.local_path}",
        )

        # Draw separator line between panels
        for y in range(1, self.height - 2):
            self._safe_addstr(
                y, panel_width + 1, "│", curses.color_pair(self.COLOR_BORDER)
            )

        # Draw right panel (Remote)
        self._draw_panel(
            self.right_panel,
            1,
            panel_width + 2,
            panel_height,
            panel_width,
            f"Remote: {self.remote_name}{self.remote_path}",
        )

        # Draw footer
        self._draw_footer()

        self.stdscr.refresh()

    def _draw_header(self) -> None:
        """Draw the top header bar."""
        hostname = socket.gethostname()
        title = f" Rclone Manager (mcrc) - {hostname} "
        header_text = title.center(self.width)
        self._safe_addstr(
            0, 0, header_text, curses.color_pair(self.COLOR_HEADER) | curses.A_BOLD
        )

    def _draw_panel(
        self, panel: Panel, y: int, x: int, height: int, width: int, title: str
    ) -> None:
        """Draw a panel with its contents."""
        # Draw panel border
        border_attr = curses.color_pair(self.COLOR_BORDER)
        if panel.is_active:
            border_attr |= curses.A_BOLD

        # Top border with title (truncated to fit)
        display_title = (
            title if len(title) <= width - 4 else "..." + title[-(width - 7) :]
        )
        self._safe_addstr(
            y, x, "+" + f" {display_title} ".center(width - 2, "-") + "+", border_attr
        )

        # Content area
        content_start_y = y + 1
        content_height = height - 2  # Account for borders

        total_items = len(panel.items)

        for i in range(content_height):
            item_idx = panel.offset + i
            row_y = content_start_y + i

            if row_y >= y + height - 1:
                break

            if item_idx < total_items:
                item_text = panel.items[item_idx]
                is_selected = (item_idx == panel.selected_index) and panel.is_active

                if is_selected:
                    attr = curses.color_pair(self.COLOR_SELECTED) | curses.A_BOLD
                elif item_text.endswith("/"):
                    attr = curses.color_pair(self.COLOR_DIR)
                else:
                    attr = curses.color_pair(self.COLOR_NORMAL)

                # Truncate or pad to fit
                display_text = item_text[: width - 2]
                line = f"|{display_text:<{width - 2}}|"
                self._safe_addstr(row_y, x, line, attr)
            else:
                # Empty line
                line = f"|{' ' * (width - 2)}|"
                self._safe_addstr(row_y, x, line, curses.color_pair(self.COLOR_NORMAL))

        # Bottom border
        bottom_y = y + height - 1
        if bottom_y < self.height - 2:
            self._safe_addstr(bottom_y, x, "+" + "-" * (width - 2) + "+", border_attr)

    def _draw_footer(self) -> None:
        """Draw the bottom footer bar."""
        footer_y = self.height - 2
        keys = [
            ("↑↓", "Navigate"),
            ("Tab", "Switch panel"),
            ("Enter", "Change dir"),
            ("3", "Check"),
            ("5", "Copy"),
            ("7", "Mkdir"),
            ("8", "Delete"),
            ("9", "Sync"),
            ("h", "Help"),
            ("q", "Quit"),
        ]

        footer_parts = [f" {key}:{action} " for key, action in keys]
        footer_text = "".join(footer_parts)

        if self.status_message:
            footer_text += f" | {self.status_message}"
        elif self.error_message:
            footer_text += f" | ERROR: {self.error_message[:30]}"

        footer_text = footer_text.ljust(self.width)[: self.width]
        self._safe_addstr(
            footer_y, 0, footer_text, curses.color_pair(self.COLOR_FOOTER)
        )

    def handle_check(self) -> None:
        """Handle check operation (F3) - compare current directories."""
        # Determine src and dst paths from current directories in both panels
        src = self.local_path
        if not src.endswith("/"):
            src += "/"
        dst = f"{self.remote_name}{self.remote_path}"

        # Show dialog with warning
        dialog_h = 10
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()
        win.addstr(1, 2, "CURRENT DIRS CHECK:", curses.A_BOLD)
        win.addstr(2, 4, f"SRC: {src}"[:52])
        win.addstr(3, 4, f"DST: {dst}"[:52])
        win.addstr(5, 4, "WARNING: --size-only comparison")
        win.addstr(6, 4, "Press 'Y' to CHECK, any other key to CANCEL")
        win.refresh()

        confirm_key = win.getch()
        if confirm_key not in (ord("y"), ord("Y")):
            self.set_status("Check cancelled.")
            return

        # Save current curses state
        curses.def_prog_mode()
        curses.curs_set(1)
        curses.endwin()
        curses.reset_shell_mode()
        os.system("stty sane")

        from jusfltuls.rclone_scanner import run_rclone_check

        try:
            run_rclone_check(src, dst)
        except Exception as e:
            print(f"Internal Error in check execution: {e}")
            print("Press Enter to return...")
            import sys

            sys.stdin.readline()

        os.system("stty sane")
        curses.reset_prog_mode()
        curses.curs_set(0)
        self.stdscr.refresh()
        self.draw()

        self.set_status("Check operation completed.")

    def handle_copy(self) -> None:
        """Handle copy operation (F5)."""
        # Determine src and dst paths
        if self.active_panel == "left":
            selected = self.left_panel.get_selected_item()
            if not selected or selected == "..":
                self.set_error("Select a file or directory to copy")
                return

            src = os.path.join(self.local_path, selected)

            # Destination directory in the other panel
            dst_dir = f"{self.remote_name}{self.remote_path}"
            # Destination full path (including the name)
            dst_full = f"{self.remote_name}{self.remote_path}{selected}"

            # For directories, MC behavior is to copy the dir into the dst_dir
            # rclone copy src_dir dst_dir/src_dir
            if selected.endswith("/"):
                target_copy_dst = dst_full
            else:
                target_copy_dst = dst_dir

        else:
            selected = self.right_panel.get_selected_item()
            if not selected or selected == "..":
                self.set_error("Select a file or directory to copy")
                return

            src = f"{self.remote_name}{self.remote_path}{selected}"

            # Destination directory in the local panel
            dst_dir = self.local_path
            # Destination full path
            dst_full = os.path.join(self.local_path, selected)

            if selected.endswith("/"):
                target_copy_dst = dst_full
            else:
                target_copy_dst = dst_dir

        # Show dialog to select copy mode based on type
        is_dir = selected.endswith("/")
        dialog_h = 12
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()
        win.addstr(1, 2, "COPY OPERATION:", curses.A_BOLD)
        win.addstr(2, 2, f"SRC: {src}"[:56])
        win.addstr(3, 2, f"DST: {dst_full if is_dir else dst_dir}"[:56])

        if is_dir:
            win.addstr(5, 4, "2. Dir traverse (rclone copy)")
            win.addstr(6, 4, "3. Dir no-traverse (rclone copy --no-traverse)")
            win.addstr(7, 4, "4. Dry run (rclone copy --dry-run)")
            win.addstr(9, 4, "Press 2, 3, 4 or Escape to cancel")
        else:
            win.addstr(5, 4, "1. One file (rclone copyto)")
            win.addstr(9, 4, "Press 1 or Escape to cancel")

        win.refresh()

        mode = 0
        dry_run = False
        while True:
            key = win.getch()
            if is_dir and key in (ord("2"), ord("3"), ord("4")):
                mode = int(chr(key))
                if mode == 4:
                    mode = 2  # Use regular traverse mode for dry-run
                    dry_run = True
                break
            elif not is_dir and key == ord("1"):
                mode = 1
                break
            elif key == 27:  # Escape
                break

        if mode > 0:
            # Save current curses state
            curses.def_prog_mode()
            curses.curs_set(1)  # Show cursor for shell

            # Critical sequence for shelling out from curses
            # 1. End curses mode
            curses.endwin()

            # 2. Reset the terminal to shell mode (pre-curses state)
            # This handles standard terminal configuration
            curses.reset_shell_mode()

            # 3. Forced reset of stty as a fail-safe for the "staircase" effect
            # and ^M input issues in some environments.
            os.system("stty sane")

            from jusfltuls.rclone_scanner import run_rclone_copy

            # Mode 1 (copyto) uses full destination path
            # Modes 2 & 3 (copy) use target_copy_dst which handles the dir-in-dir logic
            final_dst = dst_full if mode == 1 else target_copy_dst

            try:
                run_rclone_copy(mode, src, final_dst, dry_run=dry_run)
            except Exception as e:
                # We are out of curses here, can print normally
                print(f"Internal Error in copy execution: {e}")
                print("Press Enter to return...")
                import sys

                sys.stdin.readline()

            # Ensure terminal is clean before returning to curses
            os.system("stty sane")

            # Restore curses state
            curses.reset_prog_mode()
            curses.curs_set(0)  # Hide cursor again
            self.stdscr.refresh()
            self.draw()  # Force full redraw

            # Reload panels after copy
            self.update_local()
            self.update_remote()
            self.set_status("Copy operation completed.")

    def handle_sync(self) -> None:
        """Handle sync operation (dangerous!)."""
        # Determine src and dst paths based on active panel (cursor position)
        if self.active_panel == "left":
            # Sync from local to remote
            src = self.local_path
            if not src.endswith("/"):
                src += "/"
            dst = f"{self.remote_name}{self.remote_path}"
        else:
            # Sync from remote to local
            src = f"{self.remote_name}{self.remote_path}"
            dst = self.local_path
            if not dst.endswith("/"):
                dst += "/"

        # Show dialog to select sync mode
        dialog_h = 10
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()
        win.addstr(
            1, 2, "CURRENT DIRS SYNC (DANGEROUS):", curses.A_BOLD | curses.A_REVERSE
        )
        win.addstr(2, 2, f"SRC: {src}"[:56])
        win.addstr(3, 2, f"DST: {dst}"[:56])
        win.addstr(5, 4, "1. DRY RUN (rclone sync --dry-run)")
        win.addstr(6, 4, "2. REAL SYNC (DELETES FILES IN DST!)")
        win.addstr(8, 4, "Press 1, 2 or Escape to cancel")
        win.refresh()

        mode = 0
        while True:
            key = win.getch()
            if key in (ord("1"), ord("2")):
                mode = int(chr(key))
                break
            elif key == 27:  # Escape
                break

        if mode > 0:
            dry_run = mode == 1

            # Additional confirmation for real sync
            if not dry_run:
                win.clear()
                win.box()
                win.addstr(
                    1,
                    2,
                    "!!! FINAL SYNC CONFIRMATION !!!",
                    curses.A_BOLD | curses.A_REVERSE,
                )
                win.addstr(2, 2, f"SRC: {src}"[:56])
                win.addstr(3, 2, f"DST: {dst}"[:56])
                win.addstr(5, 4, "REALLY SYNC? DESTINATION FILES")
                win.addstr(6, 4, "NOT IN SOURCE WILL BE DELETED!")
                win.addstr(8, 4, "Press 'Y' to SYNC, any other key to CANCEL")
                win.refresh()
                confirm_key = win.getch()
                if confirm_key not in (ord("y"), ord("Y")):
                    self.set_status("Sync cancelled.")
                    return

            # Save current curses state
            curses.def_prog_mode()
            curses.curs_set(1)  # Show cursor for shell
            curses.endwin()
            curses.reset_shell_mode()
            os.system("stty sane")

            from jusfltuls.rclone_scanner import run_rclone_sync

            try:
                run_rclone_sync(src, dst, dry_run=dry_run)
            except Exception as e:
                print(f"Internal Error in sync execution: {e}")

            print("Press Enter to return...")
            import sys

            sys.stdin.readline()

            os.system("stty sane")
            curses.reset_prog_mode()
            curses.curs_set(0)  # Hide cursor again
            self.stdscr.refresh()
            self.draw()  # Force full redraw

            # Reload panels after sync
            self.update_local()
            self.update_remote()
            self.set_status(f"Sync {'dry-run ' if dry_run else ''}completed.")

    def handle_delete(self) -> None:
        """Handle delete operation (F8) for remote."""
        if self.active_panel != "right":
            self.set_error("Delete is only implemented for Remote panel")
            return

        selected = self.right_panel.get_selected_item()
        if not selected or selected == "..":
            self.set_error("Select a remote directory/file to delete")
            return

        is_directory = selected.endswith("/")
        remote_path = f"{self.remote_name}{self.remote_path}{selected}"

        # Show dialog to confirm delete
        dialog_h = 8
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()

        if is_directory:
            win.addstr(
                1,
                2,
                "PURGE REMOTE DIRECTORY:",
                curses.A_BOLD | curses.color_pair(self.COLOR_DIR),
            )
            win.addstr(2, 4, f"{remote_path}"[:52])
            win.addstr(4, 4, "1. DRY RUN (rclone purge --dry-run)")
            win.addstr(5, 4, "2. REAL PURGE (DANGEROUS!)")
            win.addstr(6, 4, "Press 1, 2 or Escape to cancel")
        else:
            win.addstr(
                1,
                2,
                "DELETE REMOTE FILE:",
                curses.A_BOLD | curses.color_pair(self.COLOR_NORMAL),
            )
            win.addstr(2, 4, f"{remote_path}"[:52])
            win.addstr(4, 4, "Really delete this file?")
            win.addstr(6, 4, "Press 'Y' to DELETE, any other key to CANCEL")

        win.refresh()

        if is_directory:
            mode = 0
            while True:
                key = win.getch()
                if key in (ord("1"), ord("2")):
                    mode = int(chr(key))
                    break
                elif key == 27:  # Escape
                    break

            if mode > 0:
                dry_run = mode == 1

                # Additional confirmation for real purge
                if not dry_run:
                    # Reuse window for second confirmation
                    win.clear()
                    win.box()
                    win.addstr(
                        1,
                        2,
                        "!!! FINAL CONFIRMATION !!!",
                        curses.A_BOLD | curses.A_REVERSE,
                    )
                    win.addstr(3, 4, "REALLY PURGE THIS REMOTE PATH?")
                    win.addstr(4, 4, f"{remote_path}"[:52])
                    win.addstr(6, 4, "Press 'Y' to DELETE, any other key to CANCEL")
                    win.refresh()
                    confirm_key = win.getch()
                    if confirm_key not in (ord("y"), ord("Y")):
                        self.set_status("Delete cancelled.")
                        return

                # Save current curses state
                curses.def_prog_mode()
                curses.curs_set(1)  # Show cursor for shell
                curses.endwin()
                curses.reset_shell_mode()
                os.system("stty sane")

                from jusfltuls.rclone_scanner import run_rclone_purge

                try:
                    run_rclone_purge(remote_path, dry_run=dry_run)
                except Exception as e:
                    print(f"Internal Error in purge execution: {e}")
                    print("Press Enter to return...")
                    import sys

                    sys.stdin.readline()

                os.system("stty sane")
                curses.reset_prog_mode()
                curses.curs_set(0)  # Hide cursor again
                self.stdscr.refresh()
                self.draw()  # Force full redraw

                # Reload panels after delete
                self.update_remote()
                self.set_status(f"Purge {'dry-run ' if dry_run else ''}completed.")
        else:
            # File deletion flow
            while True:
                key = win.getch()
                if key in (ord("y"), ord("Y")):
                    # Save current curses state
                    curses.def_prog_mode()
                    curses.curs_set(1)  # Show cursor for shell
                    curses.endwin()
                    curses.reset_shell_mode()
                    os.system("stty sane")

                    from jusfltuls.rclone_scanner import run_rclone_deletefile

                    try:
                        run_rclone_deletefile(remote_path)
                    except Exception as e:
                        print(f"Internal Error in deletefile execution: {e}")
                        print("Press Enter to return...")
                        import sys

                        sys.stdin.readline()

                    os.system("stty sane")
                    curses.reset_prog_mode()
                    curses.curs_set(0)  # Hide cursor again
                    self.stdscr.refresh()
                    self.draw()  # Force full redraw

                    # Reload panels after delete
                    self.update_remote()
                    self.set_status("File deleted.")
                    break
                elif key != -1:  # Any other key to cancel
                    self.set_status("Delete cancelled.")
                    break

    def handle_enter(self) -> None:
        """Handle Enter key press."""
        if self.active_panel == "left":
            selected = self.left_panel.get_selected_item()
            if selected == "..":
                # Remember current directory name for cursor positioning after going up
                prev_dir = os.path.basename(self.local_path.rstrip("/")) + "/"
                self.local_path = os.path.dirname(self.local_path)
                self.update_local()

                # Find the previous directory in the new list and select it
                if prev_dir in self.left_panel.items:
                    self.left_panel.selected_index = self.left_panel.items.index(
                        prev_dir
                    )
                    # Adjust offset if needed
                    panel_height = self.height - 6
                    if self.left_panel.selected_index >= panel_height:
                        self.left_panel.offset = (
                            self.left_panel.selected_index - panel_height + 1
                        )
                else:
                    self.left_panel.selected_index = 0
                    self.left_panel.offset = 0
            elif selected and selected.endswith("/"):
                self.local_path = os.path.join(self.local_path, selected.rstrip("/"))
                self.update_local()
                self.left_panel.selected_index = 0
                self.left_panel.offset = 0
        else:
            selected = self.right_panel.get_selected_item()
            if selected == "..":
                if self.remote_path and self.remote_path != "/":
                    # Remember current directory name for cursor positioning after going up
                    # remote_path typically looks like "dir1/dir2/" or "dir1/"
                    path_stripped = self.remote_path.rstrip("/")
                    prev_dir = os.path.basename(path_stripped) + "/"

                    parts = path_stripped.split("/")
                    self.remote_path = "/".join(parts[:-1])
                    if self.remote_path and not self.remote_path.endswith("/"):
                        self.remote_path += "/"
                    if self.remote_path == "/":
                        self.remote_path = ""

                    self.update_remote()

                    # Find the previous directory in the new list and select it
                    if prev_dir in self.right_panel.items:
                        self.right_panel.selected_index = self.right_panel.items.index(
                            prev_dir
                        )
                        # Adjust offset if needed
                        panel_height = self.height - 6
                        if self.right_panel.selected_index >= panel_height:
                            self.right_panel.offset = (
                                self.right_panel.selected_index - panel_height + 1
                            )
                    else:
                        self.right_panel.selected_index = 0
                        self.right_panel.offset = 0
            elif selected and selected.endswith("/"):
                self.remote_path = f"{self.remote_path}{selected}"
                self.update_remote()
                self.right_panel.selected_index = 0
                self.right_panel.offset = 0

    def handle_mkdir(self) -> None:
        """Handle mkdir operation (F7) for remote."""
        if self.active_panel != "right":
            self.set_error("Mkdir is only implemented for Remote panel")
            return

        # Show dialog to enter directory name
        dialog_h = 8
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()
        win.addstr(
            1,
            2,
            "CREATE REMOTE DIRECTORY:",
            curses.A_BOLD | curses.color_pair(self.COLOR_DIR),
        )
        win.addstr(3, 4, "Enter directory name:")
        win.refresh()

        # Enable cursor and echo for input
        curses.curs_set(1)
        curses.echo()
        win.nodelay(False)

        # Get input
        curses.noecho()
        curses.curs_set(0)

        # Use a simple approach - collect chars
        dirname = ""
        input_x = 4
        input_y = 4
        max_input_len = 50

        win.move(input_y, input_x)
        win.refresh()

        while True:
            key = win.getch()
            if key in (10, 13, curses.KEY_ENTER):  # Enter
                break
            elif key == 27:  # Escape
                self.set_status("Mkdir cancelled.")
                return
            elif key == curses.KEY_BACKSPACE or key == 127:  # Backspace
                if dirname:
                    dirname = dirname[:-1]
                    win.addstr(input_y, input_x + len(dirname), " ")
                    win.move(input_y, input_x + len(dirname))
                    win.refresh()
            elif 32 <= key <= 126 and len(dirname) < max_input_len:  # Printable chars
                dirname += chr(key)
                win.addch(input_y, input_x + len(dirname) - 1, key)
                win.refresh()

        dirname = dirname.strip()
        if not dirname:
            self.set_status("Mkdir cancelled (empty name).")
            return

        # Create full path
        remote_path = f"{self.remote_name}{self.remote_path}{dirname}"

        # Save current curses state
        curses.def_prog_mode()
        curses.curs_set(1)
        curses.endwin()
        curses.reset_shell_mode()
        os.system("stty sane")

        from jusfltuls.rclone_scanner import run_rclone_mkdir

        try:
            run_rclone_mkdir(remote_path)
        except Exception as e:
            print(f"Internal Error in mkdir execution: {e}")
            print("Press Enter to return...")
            import sys

            sys.stdin.readline()

        os.system("stty sane")
        curses.reset_prog_mode()
        curses.curs_set(0)
        self.stdscr.refresh()
        self.draw()

        # Reload panels after mkdir
        self.update_remote()
        self.set_status(f"Directory '{dirname}' created.")

    def handle_help(self) -> None:
        """Handle help command (F1/h) - show all allowed keys."""
        dialog_h = 19
        dialog_w = 60
        dialog_y = (self.height - dialog_h) // 2
        dialog_x = (self.width - dialog_w) // 2

        win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
        win.box()
        win.addstr(1, 2, "MCRC - Help / Key Bindings", curses.A_BOLD | curses.A_REVERSE)

        # Key bindings list
        bindings = [
            ("↑↓", "Navigate up/down"),
            ("PgUp/PgDn", "Page up/down"),
            ("Home/End", "Go to first/last item"),
            ("Tab/←→", "Switch between panels"),
            ("Enter", "Enter directory"),
            ("", ""),
            ("F3 / 3", "Check/compare (size-only)"),
            ("F5 / 5", "Copy file/directory"),
            ("F7 / 7", "Create directory (remote)"),
            ("F8 / 8", "Delete file/directory (remote)"),
            ("F9 / 9 / s", "Sync src to dest (with delete)"),
            ("r", "Refresh panels"),
            ("", ""),
            ("F1 / h", "Show this help"),
            ("q", "Quit application"),
        ]

        row = 3
        for key, action in bindings:
            if key:
                win.addstr(row, 4, f"{key:12} {action}"[:52])
            row += 1

        win.addstr(dialog_h - 2, 4, "Press any key to close...")
        win.refresh()

        # Wait for any key
        win.nodelay(False)
        win.getch()

    def set_status(self, message: str) -> None:
        """Set a status message."""
        self.status_message = message
        self.error_message = None

    def set_error(self, message: str) -> None:
        """Set an error message."""
        self.error_message = message
        self.status_message = None
