#!/usr/bin/env bash
set -euo pipefail

# ─────────────────────────────────────────────────────────────────────────────
# 04-worktree-manager.sh — Parallel Development via Worktrees for SecureGit
#
# Manage git worktrees for parallel development: create, list, remove, switch,
# prune, and show cross-worktree status with auto dependency installation.
#
# Usage:
#   ./04-worktree-manager.sh                  # Launch interactive menu
#   ./04-worktree-manager.sh list             # List worktrees
#   ./04-worktree-manager.sh create [name]    # Quick create
#   ./04-worktree-manager.sh remove [path]    # Quick remove
#   ./04-worktree-manager.sh status           # Cross-worktree status
# ─────────────────────────────────────────────────────────────────────────────

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/lib/securegit-common.sh"

sg_require_repo

# ─── Constants ───────────────────────────────────────────────────────────────
_REPO_ROOT="$(git rev-parse --show-toplevel)"
_WORKTREE_BASE="${SG_WORKTREE_DIR:-.worktrees}"
_REMOTE="${SG_PRIMARY_REMOTE:-origin}"

# Resolve worktree base to absolute path
if [[ "$_WORKTREE_BASE" != /* ]]; then
    _WORKTREE_BASE="${_REPO_ROOT}/${_WORKTREE_BASE}"
fi

# ─── Helpers ─────────────────────────────────────────────────────────────────

# Parse `git worktree list --porcelain` into structured data
# Returns lines of: path|commit|branch
_parse_worktrees() {
    local path="" commit="" branch=""
    git worktree list --porcelain 2>/dev/null | while IFS= read -r line; do
        case "$line" in
            "worktree "*)
                path="${line#worktree }"
                ;;
            "HEAD "*)
                commit="${line#HEAD }"
                commit="${commit:0:8}"
                ;;
            "branch "*)
                branch="${line#branch refs/heads/}"
                ;;
            "detached")
                branch="(detached)"
                ;;
            "")
                if [[ -n "$path" ]]; then
                    echo "${path}|${commit}|${branch}"
                fi
                path="" commit="" branch=""
                ;;
        esac
    done
    # Flush last entry
    if [[ -n "$path" ]]; then
        echo "${path}|${commit}|${branch}"
    fi
}

# Count non-main worktrees
_worktree_count() {
    git worktree list 2>/dev/null | wc -l | tr -d ' '
}

# Check if a path is a worktree
_is_worktree() {
    local check_path="$1"
    git worktree list --porcelain 2>/dev/null | grep -q "^worktree ${check_path}$"
}

# Get the status summary for a worktree path
_worktree_status() {
    local wt_path="$1"
    if [[ ! -d "$wt_path" ]]; then
        echo "missing"
        return
    fi

    local status
    status="$(git -C "$wt_path" status --porcelain 2>/dev/null || echo "error")"

    if [[ "$status" == "error" ]]; then
        echo "error"
    elif [[ -z "$status" ]]; then
        echo "clean"
    else
        local modified untracked staged
        modified="$(echo "$status" | grep -c '^ M\| M ' 2>/dev/null || echo 0)"
        untracked="$(echo "$status" | grep -c '^??' 2>/dev/null || echo 0)"
        staged="$(echo "$status" | grep -c '^[MADRC]' 2>/dev/null || echo 0)"
        echo "${staged}S ${modified}M ${untracked}U"
    fi
}

# Detect and install dependencies for a worktree
_install_deps() {
    local wt_path="$1"
    local lang
    lang="$(cd "$wt_path" && sg_detect_language)"

    sg_info "Detected language: $lang"

    case "$lang" in
        rust)
            if [[ -f "$wt_path/Cargo.toml" ]] && command -v cargo &>/dev/null; then
                sg_info "Running: cargo fetch"
                (cd "$wt_path" && cargo fetch 2>&1) | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "Rust dependencies fetched."
            fi
            ;;
        go)
            if [[ -f "$wt_path/go.mod" ]] && command -v go &>/dev/null; then
                sg_info "Running: go mod download"
                (cd "$wt_path" && go mod download 2>&1) | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "Go dependencies downloaded."
            fi
            ;;
        python)
            if [[ -f "$wt_path/requirements.txt" ]]; then
                if command -v pip &>/dev/null; then
                    sg_info "Running: pip install -r requirements.txt"
                    (cd "$wt_path" && pip install -r requirements.txt 2>&1) | while IFS= read -r line; do
                        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                    done
                    sg_success "Python dependencies installed."
                fi
            elif [[ -f "$wt_path/pyproject.toml" ]]; then
                if command -v pip &>/dev/null; then
                    sg_info "Running: pip install -e ."
                    (cd "$wt_path" && pip install -e . 2>&1) | while IFS= read -r line; do
                        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                    done
                    sg_success "Python project installed."
                fi
            fi
            ;;
        js)
            if [[ -f "$wt_path/package.json" ]]; then
                if [[ -f "$wt_path/pnpm-lock.yaml" ]] && command -v pnpm &>/dev/null; then
                    sg_info "Running: pnpm install"
                    (cd "$wt_path" && pnpm install 2>&1) | while IFS= read -r line; do
                        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                    done
                    sg_success "pnpm dependencies installed."
                elif [[ -f "$wt_path/yarn.lock" ]] && command -v yarn &>/dev/null; then
                    sg_info "Running: yarn install"
                    (cd "$wt_path" && yarn install 2>&1) | while IFS= read -r line; do
                        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                    done
                    sg_success "Yarn dependencies installed."
                elif command -v npm &>/dev/null; then
                    sg_info "Running: npm install"
                    (cd "$wt_path" && npm install 2>&1) | while IFS= read -r line; do
                        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                    done
                    sg_success "npm dependencies installed."
                fi
            fi
            ;;
        java)
            if [[ -f "$wt_path/gradlew" ]]; then
                sg_info "Running: ./gradlew dependencies"
                (cd "$wt_path" && ./gradlew dependencies 2>&1) | tail -5 | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "Gradle dependencies resolved."
            elif [[ -f "$wt_path/mvnw" ]]; then
                sg_info "Running: ./mvnw dependency:resolve"
                (cd "$wt_path" && ./mvnw dependency:resolve 2>&1) | tail -5 | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "Maven dependencies resolved."
            fi
            ;;
        ruby)
            if [[ -f "$wt_path/Gemfile" ]] && command -v bundle &>/dev/null; then
                sg_info "Running: bundle install"
                (cd "$wt_path" && bundle install 2>&1) | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "Ruby dependencies installed."
            fi
            ;;
        php)
            if [[ -f "$wt_path/composer.json" ]] && command -v composer &>/dev/null; then
                sg_info "Running: composer install"
                (cd "$wt_path" && composer install 2>&1) | while IFS= read -r line; do
                    printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
                done
                sg_success "PHP dependencies installed."
            fi
            ;;
        *)
            sg_info "No dependency installation step for language: $lang"
            ;;
    esac
}

# ─── Operations ──────────────────────────────────────────────────────────────

op_list() {
    sg_header "Active Worktrees"

    local current_dir
    current_dir="$(pwd)"

    printf "  ${_C_BOLD}%-3s %-40s %-12s %-15s %s${_C_RESET}\n" "" "PATH" "COMMIT" "BRANCH" "STATUS"
    sg_divider

    local count=0
    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue
        (( count++ )) || true

        local marker=" "
        local color=""
        if [[ "$wt_path" == "$current_dir" ]] || [[ "$wt_path" == "$_REPO_ROOT" && "$current_dir" == "$_REPO_ROOT" ]]; then
            marker="*"
            color="$_C_GREEN"
        fi

        # Determine if this is the main worktree
        local is_main=""
        if [[ "$wt_path" == "$_REPO_ROOT" ]]; then
            is_main=" (main)"
        fi

        local status
        status="$(_worktree_status "$wt_path")"

        # Shorten path relative to repo root parent for readability
        local display_path="$wt_path"
        if [[ "$wt_path" == "$_REPO_ROOT"* ]] && [[ "$wt_path" != "$_REPO_ROOT" ]]; then
            display_path=".${wt_path#${_REPO_ROOT}}"
        fi

        printf "  ${color}${_C_BOLD}%-3s${_C_RESET}${color}%-40s${_C_RESET} ${_C_DIM}%-12s${_C_RESET} %-15s ${_C_DIM}%s${_C_RESET}\n" \
            "$marker" "${display_path}${is_main}" "$wt_commit" "$wt_branch" "$status"
    done < <(_parse_worktrees)

    echo
    sg_info "Total: $count worktree(s) (* = current)"
}

op_create() {
    sg_header "Create Worktree"

    local current_branch
    current_branch="$(sg_current_branch)"
    sg_info "Current branch: $current_branch"
    sg_info "Worktree base:  $_WORKTREE_BASE"
    echo

    # Get worktree name
    local wt_name="${1:-}"
    if [[ -z "$wt_name" ]]; then
        wt_name="$(sg_prompt "Worktree name (used as directory and branch)")"
    fi

    if [[ -z "$wt_name" ]]; then
        sg_error "Worktree name cannot be empty."
        return 1
    fi

    # Sanitize name
    local safe_name
    safe_name="$(echo "$wt_name" | tr -cs '[:alnum:]/-' '-' | sed 's/^-//;s/-$//')"

    local wt_path="${_WORKTREE_BASE}/${safe_name}"
    local branch_name="$safe_name"

    # Check if worktree path already exists
    if [[ -d "$wt_path" ]]; then
        sg_error "Directory already exists: $wt_path"
        return 1
    fi

    # Determine branch behavior
    local branch_action=""
    if sg_branch_exists "$branch_name"; then
        sg_info "Branch '$branch_name' already exists."
        if sg_confirm "Use existing branch '$branch_name'?"; then
            branch_action="existing"
        else
            branch_name="$(sg_prompt "Enter a different branch name")"
            if sg_branch_exists "$branch_name"; then
                branch_action="existing"
            else
                branch_action="new"
            fi
        fi
    else
        branch_action="new"
    fi

    # Select base branch for new branches
    local base_branch=""
    if [[ "$branch_action" == "new" ]]; then
        local default_base
        default_base="$(sg_default_branch)"
        base_branch="$(sg_prompt "Base branch" "$default_base")"
    fi

    # Create worktree directory
    mkdir -p "$(dirname "$wt_path")"

    sg_info "Creating worktree..."
    if [[ "$branch_action" == "new" ]]; then
        git worktree add -b "$branch_name" "$wt_path" "$base_branch" 2>&1 | while IFS= read -r line; do
            printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
        done
        sg_success "Created worktree with new branch: $branch_name"
    else
        git worktree add "$wt_path" "$branch_name" 2>&1 | while IFS= read -r line; do
            printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
        done
        sg_success "Created worktree with existing branch: $branch_name"
    fi

    sg_info "Path: $wt_path"
    echo

    # Auto-install dependencies
    if sg_confirm "Install dependencies in the new worktree?"; then
        _install_deps "$wt_path"
    fi

    echo
    sg_info "To work in this worktree:"
    sg_info "  cd $wt_path"
    echo
    sg_info "To return to main worktree:"
    sg_info "  cd $_REPO_ROOT"

    sg_undo_available
}

op_remove() {
    sg_header "Remove Worktree"

    # List non-main worktrees
    local worktrees=()
    local worktree_paths=()
    local worktree_branches=()

    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue
        [[ "$wt_path" == "$_REPO_ROOT" ]] && continue  # Skip main worktree

        worktrees+=("$wt_path ($wt_branch)")
        worktree_paths+=("$wt_path")
        worktree_branches+=("$wt_branch")
    done < <(_parse_worktrees)

    if (( ${#worktrees[@]} == 0 )); then
        sg_warn "No secondary worktrees to remove."
        return 0
    fi

    sg_info "Secondary worktrees:"
    local i
    for i in "${!worktrees[@]}"; do
        local status
        status="$(_worktree_status "${worktree_paths[$i]}")"
        printf "  ${_C_BOLD}%d)${_C_RESET} %-50s ${_C_DIM}[%s]${_C_RESET}\n" "$((i + 1))" "${worktrees[$i]}" "$status"
    done
    echo

    local choice
    while true; do
        printf "Select worktree to remove [1-%d]: " "${#worktrees[@]}"
        read -r choice
        if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#worktrees[@]} )); then
            break
        fi
        sg_warn "Invalid selection."
    done

    local target_path="${worktree_paths[$((choice - 1))]}"
    local target_branch="${worktree_branches[$((choice - 1))]}"
    local status
    status="$(_worktree_status "$target_path")"

    sg_info "Worktree: $target_path"
    sg_info "Branch:   $target_branch"
    sg_info "Status:   $status"
    echo

    # Warn about uncommitted changes
    if [[ "$status" != "clean" ]] && [[ "$status" != "missing" ]]; then
        sg_warn "This worktree has uncommitted changes that will be LOST."
    fi

    # Check if we're currently in this worktree
    local current_dir
    current_dir="$(pwd)"
    if [[ "$current_dir" == "$target_path"* ]]; then
        sg_error "You are currently inside this worktree. cd to another location first."
        return 1
    fi

    if ! sg_confirm "Remove worktree at '$target_path'?" "n"; then
        sg_info "Remove cancelled."
        return 0
    fi

    # Remove worktree
    local force_flag=""
    if [[ "$status" != "clean" ]] && [[ "$status" != "missing" ]]; then
        force_flag="--force"
    fi

    git worktree remove $force_flag "$target_path" 2>&1 | while IFS= read -r line; do
        printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
    done

    sg_success "Worktree removed: $target_path"

    # Offer to delete the branch too
    if sg_branch_exists "$target_branch" && ! sg_is_protected "$target_branch"; then
        if sg_confirm "Also delete branch '$target_branch'?" "n"; then
            local default_branch
            default_branch="$(sg_default_branch)"
            local unmerged
            unmerged="$(git log --oneline "${default_branch}..${target_branch}" 2>/dev/null | wc -l | tr -d ' ')"

            if (( unmerged > 0 )); then
                sg_warn "Branch has $unmerged unmerged commit(s)."
                if sg_confirm "Force delete unmerged branch?" "n"; then
                    git branch -D "$target_branch"
                    sg_success "Branch force-deleted: $target_branch"
                fi
            else
                git branch -d "$target_branch"
                sg_success "Branch deleted: $target_branch"
            fi
        fi
    fi

    sg_undo_available
}

op_switch() {
    sg_header "Switch Worktree"

    local current_dir
    current_dir="$(pwd)"

    local worktrees=()
    local worktree_paths=()

    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue

        local marker=""
        if [[ "$wt_path" == "$current_dir" ]]; then
            marker=" (current)"
        fi

        local display_path="$wt_path"
        if [[ "$wt_path" == "$_REPO_ROOT" ]]; then
            display_path="$wt_path (main)"
        fi

        worktrees+=("${display_path} [${wt_branch}]${marker}")
        worktree_paths+=("$wt_path")
    done < <(_parse_worktrees)

    if (( ${#worktrees[@]} <= 1 )); then
        sg_warn "No other worktrees to switch to."
        return 0
    fi

    sg_info "Available worktrees:"
    local i
    for i in "${!worktrees[@]}"; do
        printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((i + 1))" "${worktrees[$i]}"
    done
    echo

    local choice
    while true; do
        printf "Select [1-%d]: " "${#worktrees[@]}"
        read -r choice
        if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#worktrees[@]} )); then
            break
        fi
        sg_warn "Invalid selection."
    done

    local target="${worktree_paths[$((choice - 1))]}"

    if [[ ! -d "$target" ]]; then
        sg_error "Worktree directory does not exist: $target"
        return 1
    fi

    sg_success "Switch to worktree by running:"
    sg_info "  cd $target"
    echo
    sg_info "(Shell cannot change directory for you. Copy and run the command above.)"
}

op_status() {
    sg_header "Cross-Worktree Status"

    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue

        local display_path="$wt_path"
        if [[ "$wt_path" == "$_REPO_ROOT" ]]; then
            display_path="${wt_path} (main)"
        fi

        printf "\n  ${_C_BOLD}${_C_BLUE}%s${_C_RESET} ${_C_DIM}[%s @ %s]${_C_RESET}\n" \
            "$display_path" "$wt_branch" "$wt_commit"

        if [[ ! -d "$wt_path" ]]; then
            printf "    ${_C_RED}Directory missing!${_C_RESET}\n"
            continue
        fi

        local status
        status="$(git -C "$wt_path" status --porcelain 2>/dev/null || echo "")"

        if [[ -z "$status" ]]; then
            printf "    ${_C_GREEN}Clean${_C_RESET}\n"
        else
            # Group by status type
            local staged modified untracked
            staged="$(echo "$status" | grep '^[MADRC]' 2>/dev/null || true)"
            modified="$(echo "$status" | grep '^ [MD]' 2>/dev/null || true)"
            untracked="$(echo "$status" | grep '^??' 2>/dev/null || true)"

            if [[ -n "$staged" ]]; then
                local count
                count="$(echo "$staged" | wc -l | tr -d ' ')"
                printf "    ${_C_GREEN}Staged:    %d file(s)${_C_RESET}\n" "$count"
            fi
            if [[ -n "$modified" ]]; then
                local count
                count="$(echo "$modified" | wc -l | tr -d ' ')"
                printf "    ${_C_YELLOW}Modified:  %d file(s)${_C_RESET}\n" "$count"
            fi
            if [[ -n "$untracked" ]]; then
                local count
                count="$(echo "$untracked" | wc -l | tr -d ' ')"
                printf "    ${_C_DIM}Untracked: %d file(s)${_C_RESET}\n" "$count"
            fi
        fi

        # Show how far ahead/behind the default branch this is
        local default_branch
        default_branch="$(sg_default_branch)"
        if [[ "$wt_branch" != "$default_branch" ]] && [[ "$wt_branch" != "(detached)" ]]; then
            local ahead behind
            ahead="$(git -C "$wt_path" rev-list --count "${default_branch}..${wt_branch}" 2>/dev/null || echo 0)"
            behind="$(git -C "$wt_path" rev-list --count "${wt_branch}..${default_branch}" 2>/dev/null || echo 0)"
            if (( ahead > 0 || behind > 0 )); then
                printf "    ${_C_CYAN}vs %s: %d ahead, %d behind${_C_RESET}\n" "$default_branch" "$ahead" "$behind"
            fi
        fi
    done < <(_parse_worktrees)

    echo
}

op_prune() {
    sg_header "Prune Stale Worktrees"

    sg_info "Checking for worktrees with missing directories..."
    echo

    local prunable
    prunable="$(git worktree list --porcelain 2>/dev/null | grep -A1 'prunable' || true)"

    # Also check for directories that no longer exist
    local stale_count=0

    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue
        [[ "$wt_path" == "$_REPO_ROOT" ]] && continue

        if [[ ! -d "$wt_path" ]]; then
            printf "  ${_C_RED}Missing${_C_RESET}: %s [%s]\n" "$wt_path" "$wt_branch"
            (( stale_count++ )) || true
        fi
    done < <(_parse_worktrees)

    # Check worktree base for orphaned directories
    if [[ -d "$_WORKTREE_BASE" ]]; then
        local known_paths=()
        while IFS='|' read -r wt_path _ _; do
            [[ -n "$wt_path" ]] && known_paths+=("$wt_path")
        done < <(_parse_worktrees)

        for dir in "$_WORKTREE_BASE"/*/; do
            [[ ! -d "$dir" ]] && continue
            dir="${dir%/}"  # Remove trailing slash

            local is_known=false
            for kp in "${known_paths[@]}"; do
                if [[ "$dir" == "$kp" ]]; then
                    is_known=true
                    break
                fi
            done

            if [[ "$is_known" == "false" ]] && [[ ! -f "$dir/.git" ]]; then
                printf "  ${_C_YELLOW}Orphaned${_C_RESET}: %s (not a registered worktree)\n" "$dir"
                (( stale_count++ )) || true
            fi
        done
    fi

    echo
    if (( stale_count == 0 )); then
        sg_success "No stale worktrees found."
        return 0
    fi

    sg_info "Found $stale_count stale entry/entries."

    if sg_confirm "Prune stale worktree references?"; then
        git worktree prune -v 2>&1 | while IFS= read -r line; do
            printf "    ${_C_DIM}%s${_C_RESET}\n" "$line"
        done
        sg_success "Worktree references pruned."
    fi

    # Offer to clean orphaned directories
    if [[ -d "$_WORKTREE_BASE" ]]; then
        local orphaned_dirs=()
        local known_paths=()
        while IFS='|' read -r wt_path _ _; do
            [[ -n "$wt_path" ]] && known_paths+=("$wt_path")
        done < <(_parse_worktrees)

        for dir in "$_WORKTREE_BASE"/*/; do
            [[ ! -d "$dir" ]] && continue
            dir="${dir%/}"

            local is_known=false
            for kp in "${known_paths[@]}"; do
                [[ "$dir" == "$kp" ]] && is_known=true && break
            done

            if [[ "$is_known" == "false" ]] && [[ ! -f "$dir/.git" ]]; then
                orphaned_dirs+=("$dir")
            fi
        done

        if (( ${#orphaned_dirs[@]} > 0 )); then
            sg_warn "Orphaned directories in $_WORKTREE_BASE:"
            for d in "${orphaned_dirs[@]}"; do
                sg_info "  $d"
            done

            if sg_confirm "Remove orphaned directories?" "n"; then
                for d in "${orphaned_dirs[@]}"; do
                    rm -rf "$d"
                    sg_success "  Removed: $d"
                done
            fi
        fi
    fi
}

op_changes() {
    sg_header "Changes Across All Worktrees"

    local has_changes=false

    while IFS='|' read -r wt_path wt_commit wt_branch; do
        [[ -z "$wt_path" ]] && continue
        [[ ! -d "$wt_path" ]] && continue

        local status
        status="$(git -C "$wt_path" status --porcelain 2>/dev/null || echo "")"

        if [[ -n "$status" ]]; then
            has_changes=true

            local display_path="$wt_path"
            if [[ "$wt_path" == "$_REPO_ROOT" ]]; then
                display_path="${wt_path} (main)"
            fi

            printf "\n  ${_C_BOLD}${_C_BLUE}%s${_C_RESET} ${_C_DIM}[%s]${_C_RESET}\n" "$display_path" "$wt_branch"

            echo "$status" | while IFS= read -r line; do
                local file_status="${line:0:2}"
                local file_name="${line:3}"
                case "$file_status" in
                    "??") printf "    ${_C_DIM}?  %s${_C_RESET}\n" "$file_name" ;;
                    " M") printf "    ${_C_YELLOW}M  %s${_C_RESET}\n" "$file_name" ;;
                    "M "| "A ") printf "    ${_C_GREEN}%s %s${_C_RESET}\n" "$file_status" "$file_name" ;;
                    "D "| " D") printf "    ${_C_RED}%s %s${_C_RESET}\n" "$file_status" "$file_name" ;;
                    *)    printf "    %s %s\n" "$file_status" "$file_name" ;;
                esac
            done
        fi
    done < <(_parse_worktrees)

    echo
    if [[ "$has_changes" == "false" ]]; then
        sg_success "All worktrees are clean."
    fi
}

# ─── CLI Shortcut Handling ───────────────────────────────────────────────────

case "${1:-}" in
    list)    op_list; exit 0 ;;
    create)  shift; op_create "${1:-}"; exit 0 ;;
    remove)  shift; op_remove; exit 0 ;;
    status)  op_status; exit 0 ;;
    "")      ;; # fall through to interactive menu
    *)       sg_die "Unknown subcommand: $1" ;;
esac

# ─── Interactive Menu Loop ───────────────────────────────────────────────────

while true; do
    choice="$(sg_menu "SecureGit Worktree Manager" \
        "List worktrees" \
        "Create worktree" \
        "Remove worktree" \
        "Switch worktree" \
        "Cross-worktree status" \
        "Show changes across worktrees" \
        "Prune stale worktrees" \
        "Quit"
    )"

    case "$choice" in
        1) op_list ;;
        2) op_create ;;
        3) op_remove ;;
        4) op_switch ;;
        5) op_status ;;
        6) op_changes ;;
        7) op_prune ;;
        8) sg_info "Goodbye."; exit 0 ;;
    esac

    echo
    sg_divider
done
