#!/bin/bash
set -euo pipefail

KUGETSU_DIR="${KUGETSU_DIR:-$HOME/.kugetsu}"
SESSIONS_DIR="$KUGETSU_DIR/sessions"
WORKTREES_DIR="$KUGETSU_DIR/worktrees"
REPOS_CONFIG="$KUGETSU_DIR/repos.json"
INDEX_FILE="$KUGETSU_DIR/index.json"

usage() {
    cat << 'EOF'
kugetsu - OpenCode Session Manager (Issue-Driven)

Usage:
    kugetsu init [--force]                            Initialize base + pm-agent sessions (requires TTY)
    kugetsu start <issue-ref> <message> [--debug]    Start task for issue (forks base session)
    kugetsu continue <issue-ref> [message] [--debug] Continue existing task for issue
    kugetsu list                                     List all tracked sessions
    kugetsu prune [--force]                          Remove orphaned sessions (keeps base + pm-agent)
    kugetsu destroy <issue-ref> [-y]                  Delete session for issue
    kugetsu destroy --pm-agent [-y]                   Delete pm-agent session
    kugetsu destroy --base [-y]                       Delete base session
    kugetsu help                                     Show this help

Issue Ref Format:
    instance/user/repo#number
    Example: github.com/shoko/kugetsu#14

Commands:
    init        Create base + pm-agent sessions via TUI. Requires terminal access.
                Use --force to reinitialize if sessions exist.
    start       Fork new session from base for specific issue.
                Requires pm-agent to be running (created by init).
    continue    Continue work on existing issue session.
    list        Show all sessions (base + pm-agent + forked issues).
    prune       Remove sessions not in index (orphaned from opencode).
                Use --force to skip confirmation.
    destroy     Delete specific issue, pm-agent, or base session.

Options:
    --debug   Show real-time debug output and capture to debug.log

Examples:
    kugetsu init
    kugetsu start github.com/shoko/kugetsu#14 "fix bug"
    kugetsu continue github.com/shoko/kugetsu#14 "add tests"
    kugetsu list
    kugetsu prune
    kugetsu prune --force
    kugetsu destroy github.com/shoko/kugetsu#14
EOF
}

ensure_dirs() {
    mkdir -p "$SESSIONS_DIR"
}

ensure_worktree_dir() {
    mkdir -p "$WORKTREES_DIR"
}

issue_ref_to_worktree_name() {
    local issue_ref="$1"
    echo "$issue_ref" | sed 's/[\/:]/-/g' | sed 's/#/--/'
}

issue_ref_to_worktree_path() {
    local issue_ref="$1"
    local worktree_name=$(issue_ref_to_worktree_name "$issue_ref")
    echo "$WORKTREES_DIR/$worktree_name"
}

issue_ref_to_branch_name() {
    local issue_ref="$1"
    local number_part=$(echo "$issue_ref" | grep -oE '#[0-9]+$' || echo "")
    if [ -n "$number_part" ]; then
        echo "fix/issue-${number_part#\#}"
    else
        local identifier=$(echo "$issue_ref" | grep -oE '#[^-]+$' || echo "")
        if [ -n "$identifier" ]; then
            local clean_id=$(echo "$identifier" | sed 's/^#//' | sed 's/-/_/g')
            echo "fix/${clean_id}"
        else
            echo "fix/issue-temp"
        fi
    fi
}

get_repo_url() {
    local issue_ref="$1"
    if [ -f "$REPOS_CONFIG" ]; then
        local url=$(python3 -c "import json, sys; d=json.load(open('$REPOS_CONFIG')); print(d.get('$issue_ref', ''))" 2>/dev/null || echo "")
        if [ -n "$url" ]; then
            echo "$url"
            return
        fi
    fi
    local instance=$(echo "$issue_ref" | cut -d'/' -f1 | cut -d'#' -f1)
    local rest=$(echo "$issue_ref" | sed 's/.*\///' | sed 's/#.*//')
    echo "https://${instance}/${rest}.git"
}

worktree_exists() {
    local issue_ref="$1"
    local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
    [ -d "$worktree_path" ]
}

create_worktree() {
    local issue_ref="$1"
    local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
    local branch_name=$(issue_ref_to_branch_name "$issue_ref")
    local repo_url=$(get_repo_url "$issue_ref")
    
    if [ -z "$repo_url" ]; then
        echo "Error: Cannot determine repo URL for '$issue_ref'" >&2
        echo "Please add to $REPOS_CONFIG or ensure worktree exists" >&2
        exit 1
    fi
    
    ensure_worktree_dir
    
    if worktree_exists "$issue_ref"; then
        echo "Removing existing worktree at '$worktree_path'..."
        git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path"
    fi
    
    echo "Creating worktree at '$worktree_path'..."
    git clone --bare "$repo_url" "$worktree_path" 2>/dev/null || {
        echo "Error: Failed to clone repository" >&2
        exit 1
    }
    
    echo "Creating branch '$branch_name'..."
    (cd "$worktree_path" && git checkout -b "$branch_name" origin/main 2>/dev/null || git checkout -b "$branch_name" main 2>/dev/null) || {
        echo "Warning: Could not checkout branch (may need to run from within worktree after session)" >&2
    }
    
    echo "Worktree created at: $worktree_path"
}

remove_worktree_for_issue() {
    local issue_ref="$1"
    local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
    
    if worktree_exists "$issue_ref"; then
        echo "Removing worktree at '$worktree_path'..."
        git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path"
    fi
}

get_worktree_path_for_session() {
    local session_file="$1"
    if [ -f "$session_file" ]; then
        python3 -c "import json; print(json.load(open('$session_file')).get('worktree_path', ''))" 2>/dev/null || echo ""
    else
        echo ""
    fi
}

issue_ref_to_filename() {
    local issue_ref="$1"
    echo "$issue_ref" | sed 's/[\/:]/-/g' | sed 's/#/-/'
}

filename_to_issue_ref() {
    local filename="$1"
    local name="${filename%.json}"
    echo "$name" | sed 's/-\([0-9]*\)$/#\1' | sed 's/-/\//g'
}

read_index() {
    if [ -f "$INDEX_FILE" ]; then
        cat "$INDEX_FILE"
    else
        echo '{"base": null, "pm_agent": null, "issues": {}}'
    fi
}

write_index() {
    local base="$1"
    local pm_agent="$2"
    local issues_json="$3"
    local temp_file="$INDEX_FILE.tmp.$$"
    printf '{"base": %s, "pm_agent": %s, "issues": %s}\n' "$base" "$pm_agent" "$issues_json" > "$temp_file"
    mv "$temp_file" "$INDEX_FILE"
}

get_base_session_id() {
    local index=$(read_index)
    echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('base') or '')"
}

get_pm_agent_session_id() {
    local index=$(read_index)
    echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('pm_agent') or '')"
}

get_session_for_issue() {
    local issue_ref="$1"
    local index=$(read_index)
    echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['issues'].get('$issue_ref') or '')"
}

set_base_in_index() {
    local base_session_id="$1"
    local pm_agent=$(get_pm_agent_session_id)
    local issues_json=$(read_index | python3 -c "import sys, json; d=json.load(sys.stdin); print(json.dumps(d['issues']))")
    if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ]; then
        write_index "\"$base_session_id\"" "null" "$issues_json"
    else
        write_index "\"$base_session_id\"" "\"$pm_agent\"" "$issues_json"
    fi
}

set_pm_agent_in_index() {
    local pm_agent_session_id="$1"
    local base=$(get_base_session_id)
    local issues_json=$(read_index | python3 -c "import sys, json; d=json.load(sys.stdin); print(json.dumps(d['issues']))")
    if [ -z "$base" ] || [ "$base" = "null" ]; then
        write_index "null" "\"$pm_agent_session_id\"" "$issues_json"
    else
        write_index "\"$base\"" "\"$pm_agent_session_id\"" "$issues_json"
    fi
}

add_issue_to_index() {
    local issue_ref="$1"
    local session_file="$2"
    local index=$(read_index)
    local base=$(get_base_session_id)
    local pm_agent=$(get_pm_agent_session_id)
    local issues=$(echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); print(json.dumps(d['issues']))")
    local new_issues=$(echo "$issues" | python3 -c "import sys, json; d=json.load(sys.stdin); d['$issue_ref']='$session_file'; print(json.dumps(d))")
    if [ -z "$base" ] || [ "$base" = "null" ]; then
        if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ]; then
            write_index "null" "null" "$new_issues"
        else
            write_index "null" "\"$pm_agent\"" "$new_issues"
        fi
    else
        if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ]; then
            write_index "\"$base\"" "null" "$new_issues"
        else
            write_index "\"$base\"" "\"$pm_agent\"" "$new_issues"
        fi
    fi
}

remove_issue_from_index() {
    local issue_ref="$1"
    local index=$(read_index)
    local base=$(get_base_session_id)
    local pm_agent=$(get_pm_agent_session_id)
    local new_issues=$(echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); d['issues'].pop('$issue_ref', None); print(json.dumps(d['issues']))")
    if [ -z "$base" ] || [ "$base" = "null" ]; then
        if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ]; then
            write_index "null" "null" "$new_issues"
        else
            write_index "null" "\"$pm_agent\"" "$new_issues"
        fi
    else
        if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ]; then
            write_index "\"$base\"" "null" "$new_issues"
        else
            write_index "\"$base\"" "\"$pm_agent\"" "$new_issues"
        fi
    fi
}

validate_issue_ref() {
    local issue_ref="$1"
    if [[ ! "$issue_ref" =~ ^[^/]+/[^/]+/[^#]+#[0-9]+$ ]]; then
        echo "Error: invalid issue ref format" >&2
        echo "Expected: instance/user/repo#number" >&2
        echo "Example: github.com/shoko/kugetsu#14" >&2
        exit 1
    fi
}

check_opencode_session_exists() {
    local session_id="$1"
    opencode session list 2>/dev/null | grep -q "^$session_id"
}

DEBUG_MODE=false

set_debug_mode() {
    DEBUG_MODE=false
    local filtered_args=()
    while [ $# -gt 0 ]; do
        case "$1" in
            --debug)
                DEBUG_MODE=true
                ;;
            *)
                filtered_args+=("$1")
                ;;
        esac
        shift
    done
    echo "${filtered_args[@]}"
}

cmd_init() {
    local force=false

    while [ $# -gt 0 ]; do
        case "$1" in
            --force)
                force=true
                ;;
            *)
                ;;
        esac
        shift
    done

    ensure_dirs

    local existing_base=$(get_base_session_id)
    local existing_pm=$(get_pm_agent_session_id)
    
    if [ -n "$existing_base" ] && [ "$existing_base" != "null" ]; then
        if [ "$force" = true ]; then
            echo "Warning: Reinitializing sessions (force mode)" >&2
        else
            echo "Error: Base session already exists: $existing_base" >&2
            echo "Use --force to reinitialize" >&2
            exit 1
        fi
    fi

    if ! test -t 0; then
        echo "Error: init requires a terminal (TTY)" >&2
        echo "Please run this command in an interactive shell" >&2
        exit 1
    fi

    echo "Starting TUI to create base session..."
    echo "Press Ctrl+C to cancel or wait for session to be created"
    sleep 2

    opencode

    local session_ids=$(opencode session list 2>/dev/null | grep -E '^ses_' | awk '{print $1}' | tail -1)
    if [ -z "$session_ids" ]; then
        echo "Error: Could not find newly created session" >&2
        exit 1
    fi

    local new_session_id=$(echo "$session_ids" | tail -1)
    local session_file="base.json"

    printf '{"type": "base", "opencode_session_id": "%s", "created_at": "%s", "state": "idle"}\n' \
        "$new_session_id" "$(date -Iseconds)" > "$SESSIONS_DIR/$session_file"

    set_base_in_index "$new_session_id"
    echo "Base session initialized: $new_session_id"

    echo ""
    echo "Creating PM agent session..."
    sleep 1
    
    local before_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort)
    local before_set="${before_sessions//$'\n'/|}"
    
    opencode run --fork --session "$new_session_id" "You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. Wait for instructions." 2>&1 || true
    
    local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort)
    local new_pm_session_id=""
    while IFS= read -r sess; do
        if [[ ! "$before_set" =~ \|${sess}\| ]] && [[ "$sess" != "$new_session_id" ]]; then
            new_pm_session_id="$sess"
            break
        fi
    done <<< "$after_sessions"
    
    if [ -z "$new_pm_session_id" ]; then
        echo "Warning: Could not detect PM agent session ID. It may still have been created." >&2
    else
        local pm_session_file="pm-agent.json"
        printf '{"type": "pm_agent", "opencode_session_id": "%s", "created_at": "%s", "state": "idle"}\n' \
            "$new_pm_session_id" "$(date -Iseconds)" > "$SESSIONS_DIR/$pm_session_file"
        set_pm_agent_in_index "$new_pm_session_id"
        echo "PM agent session initialized: $new_pm_session_id"
    fi
    
    echo ""
    echo "Initialization complete!"
    echo "- Base session: $new_session_id"
    echo "- PM agent: ${new_pm_session_id:-created by hermes}"
}

cmd_start() {
    local issue_ref=""
    local message=""
    local args=("$@")

    args=$(set_debug_mode "${args[@]}")

    for arg in $args; do
        if [ -z "$issue_ref" ]; then
            issue_ref="$arg"
        elif [ -z "$message" ]; then
            message="$arg"
        fi
    done

    if [ -z "$issue_ref" ] || [ -z "$message" ]; then
        echo "Error: start requires <issue-ref> and <message>" >&2
        exit 1
    fi

    validate_issue_ref "$issue_ref"
    ensure_dirs

    local base_session_id=$(get_base_session_id)
    if [ -z "$base_session_id" ] || [ "$base_session_id" = "null" ]; then
        echo "Error: No base session. Run 'kugetsu init' first." >&2
        exit 1
    fi

    local pm_agent_session_id=$(get_pm_agent_session_id)
    if [ -z "$pm_agent_session_id" ] || [ "$pm_agent_session_id" = "null" ]; then
        echo "Error: No PM agent session. Run 'kugetsu init' first to create it." >&2
        exit 1
    fi

    local existing_session=$(get_session_for_issue "$issue_ref")
    if [ -n "$existing_session" ] && [ "$existing_session" != "null" ]; then
        echo "Error: Session for '$issue_ref' already exists" >&2
        echo "Use 'kugetsu continue $issue_ref <message>' instead" >&2
        exit 1
    fi

    local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
    create_worktree "$issue_ref"

    local session_file="$(issue_ref_to_filename "$issue_ref").json"

    local before_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort)
    local before_set="${before_sessions//$'\n'/|}"

    echo "Forking session for '$issue_ref'..."
    if [ "$DEBUG_MODE" = true ]; then
        opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1 | tee "$SESSIONS_DIR/$session_file.debug.log"
    else
        opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1
    fi

    local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort)
    local new_session_id=""
    while IFS= read -r sess; do
        if [[ ! "$before_set" =~ \|${sess}\| ]] && [[ "$sess" != "$base_session_id" ]]; then
            new_session_id="$sess"
            break
        fi
    done <<< "$after_sessions"

    if [ -z "$new_session_id" ]; then
        echo "Error: Could not find newly created session" >&2
        remove_worktree_for_issue "$issue_ref"
        exit 1
    fi

    printf '{"type": "forked", "issue_ref": "%s", "opencode_session_id": "%s", "worktree_path": "%s", "created_at": "%s", "state": "idle"}\n' \
        "$issue_ref" "$new_session_id" "$worktree_path" "$(date -Iseconds)" > "$SESSIONS_DIR/$session_file"

    add_issue_to_index "$issue_ref" "$session_file"

    echo "Session started for '$issue_ref': $new_session_id"
    echo "Worktree: $worktree_path"
}

cmd_continue() {
    local issue_ref=""
    local message=""
    local args=("$@")

    args=$(set_debug_mode "${args[@]}")

    for arg in $args; do
        if [ -z "$issue_ref" ]; then
            issue_ref="$arg"
        elif [ -z "$message" ]; then
            message="$arg"
        fi
    done

    if [ -z "$issue_ref" ]; then
        echo "Error: continue requires <issue-ref>" >&2
        exit 1
    fi

    if [ -z "$message" ]; then
        echo "Error: continue requires <message>" >&2
        exit 1
    fi

    validate_issue_ref "$issue_ref"

    local session_file=$(get_session_for_issue "$issue_ref")
    if [ -z "$session_file" ] || [ "$session_file" = "null" ]; then
        echo "Error: No session found for '$issue_ref'" >&2
        echo "Use 'kugetsu start $issue_ref <message>' to create one" >&2
        exit 1
    fi

    local session_path="$SESSIONS_DIR/$session_file"
    if [ ! -f "$session_path" ]; then
        echo "Error: Session file missing: $session_path" >&2
        echo "Run 'kugetsu start $issue_ref <message>' to recreate" >&2
        exit 1
    fi

    local opencode_session_id=$(python3 -c "import json; print(json.load(open('$session_path'))['opencode_session_id'])")
    local worktree_path=$(python3 -c "import json; print(json.load(open('$session_path')).get('worktree_path', ''))" 2>/dev/null || echo "")

    if ! check_opencode_session_exists "$opencode_session_id"; then
        echo "Warning: Session may have expired in opencode" >&2
        echo "Attempting to continue anyway..." >&2
    fi

    echo "Continuing session for '$issue_ref'..."
    if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then
        echo "Using worktree: $worktree_path"
        if [ "$DEBUG_MODE" = true ]; then
            opencode run --continue --session "$opencode_session_id" "$message" --workdir "$worktree_path" 2>&1 | tee "$session_path.debug.log"
        else
            opencode run --continue --session "$opencode_session_id" "$message" --workdir "$worktree_path"
        fi
    else
        if [ "$DEBUG_MODE" = true ]; then
            opencode run --continue --session "$opencode_session_id" "$message" 2>&1 | tee "$session_path.debug.log"
        else
            opencode run --continue --session "$opencode_session_id" "$message"
        fi
    fi
}

cmd_list() {
    ensure_dirs

    printf "%-50s %-10s %-25s %-40s\n" "ISSUE_REF" "TYPE" "SESSION_ID" "WORKTREE"
    printf "%-50s %-10s %-25s %-40s\n" "─────────" "─────" "──────────" "────────"

    local base_session_id=$(get_base_session_id)
    if [ -n "$base_session_id" ] && [ "$base_session_id" != "null" ]; then
        printf "%-50s %-10s %-25s %-40s\n" "(base)" "base" "$base_session_id" "N/A"
    fi

    local pm_agent_session_id=$(get_pm_agent_session_id)
    if [ -n "$pm_agent_session_id" ] && [ "$pm_agent_session_id" != "null" ]; then
        local pm_created="N/A"
        if [ -f "$SESSIONS_DIR/pm-agent.json" ]; then
            pm_created=$(python3 -c "import json; print(json.load(open('$SESSIONS_DIR/pm-agent.json'))['created_at'])" 2>/dev/null || echo "N/A")
        fi
        printf "%-50s %-10s %-25s %-40s\n" "(pm-agent)" "pm_agent" "$pm_agent_session_id" "N/A"
    fi

    local index=$(read_index)
    local issue_refs=$(echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); print('\n'.join(d['issues'].keys()))" 2>/dev/null || true)

    for session_file in "$SESSIONS_DIR"/*.json; do
        if [ -f "$session_file" ]; then
            local filename=$(basename "$session_file" .json)
            if [ "$filename" = "base" ] || [ "$filename" = "pm-agent" ]; then
                continue
            fi

            local issue_ref=$(python3 -c "import json; print(json.load(open('$session_file'))['issue_ref'])" 2>/dev/null || echo "$filename")
            local sess_id=$(python3 -c "import json; print(json.load(open('$session_file'))['opencode_session_id'])" 2>/dev/null || echo "unknown")
            local created=$(python3 -c "import json; print(json.load(open('$session_file'))['created_at'])" 2>/dev/null || echo "unknown")
            local worktree=$(python3 -c "import json; print(json.load(open('$session_file')).get('worktree_path', 'N/A'))" 2>/dev/null || echo "N/A")

            printf "%-50s %-10s %-25s %-40s\n" "$issue_ref" "forked" "$sess_id" "$worktree"
        fi
    done
}

cmd_prune() {
    local force=false

    while [ $# -gt 0 ]; do
        case "$1" in
            --force)
                force=true
                ;;
        esac
        shift
    done

    ensure_dirs
    ensure_worktree_dir

    local index=$(read_index)
    local index_session_files=$(echo "$index" | python3 -c "import sys, json; d=json.load(sys.stdin); sessions=set(d['issues'].values()); sessions.add('base.json'); sessions.add('pm-agent.json'); print('\n'.join(sessions))" 2>/dev/null || echo -e "base.json\npm-agent.json")

    local orphaned=()
    for session_file in "$SESSIONS_DIR"/*.json; do
        if [ -f "$session_file" ]; then
            local filename=$(basename "$session_file")
            if ! echo "$index_session_files" | grep -q "^$filename$"; then
                orphaned+=("$session_file")
            fi
        fi
    done

    local orphaned_worktrees=()
    if [ -d "$WORKTREES_DIR" ]; then
        for worktree_path in "$WORKTREES_DIR"/*; do
            if [ -d "$worktree_path" ]; then
                local worktree_name=$(basename "$worktree_path")
                local session_name="${worktree_name}.json"
                if ! echo "$index_session_files" | grep -q "^${session_name}$"; then
                    orphaned_worktrees+=("$worktree_path")
                fi
            fi
        done
    fi

    if [ ${#orphaned[@]} -eq 0 ] && [ ${#orphaned_worktrees[@]} -eq 0 ]; then
        echo "No orphaned sessions or worktrees found"
        return
    fi

    if [ ${#orphaned[@]} -gt 0 ]; then
        echo "Found ${#orphaned[@]} orphaned session(s):"
        for f in "${orphaned[@]}"; do
            echo "  - $(basename "$f")"
        done
    fi

    if [ ${#orphaned_worktrees[@]} -gt 0 ]; then
        echo "Found ${#orphaned_worktrees[@]} orphaned worktree(s):"
        for wt in "${orphaned_worktrees[@]}"; do
            echo "  - $(basename "$wt")"
        done
    fi

    if [ "$force" = true ]; then
        echo "Removing orphaned items (force mode)..."
        for f in "${orphaned[@]}"; do
            rm -f "$f"
            echo "Removed session: $(basename "$f")"
        done
        for wt in "${orphaned_worktrees[@]}"; do
            git worktree remove "$wt" 2>/dev/null || rm -rf "$wt"
            echo "Removed worktree: $(basename "$wt")"
        done
    else
        echo "Run with --force to remove"
    fi
}

cmd_destroy() {
    local target=""
    local force=false

    while [ $# -gt 0 ]; do
        case "$1" in
            --base)
                target="base"
                ;;
            --pm-agent)
                target="pm-agent"
                ;;
            -y|--yes)
                force=true
                ;;
            *)
                if [ -z "$target" ]; then
                    target="$1"
                fi
                ;;
        esac
        shift
    done

    if [ -z "$target" ]; then
        echo "Error: destroy requires <issue-ref>, --base, or --pm-agent" >&2
        exit 1
    fi

    if [ "$target" = "base" ]; then
        if [ "$force" = true ]; then
            rm -f "$SESSIONS_DIR/base.json"
            local pm_agent=$(get_pm_agent_session_id)
            if [ -n "$pm_agent" ] && [ "$pm_agent" != "null" ]; then
                rm -f "$SESSIONS_DIR/pm-agent.json"
                echo '{"base": null, "pm_agent": null, "issues": {}}' > "$INDEX_FILE"
            else
                echo '{"base": null, "pm_agent": null, "issues": {}}' > "$INDEX_FILE"
            fi
            echo "Base session destroyed"
        else
            echo "Error: destroying base session requires --base -y" >&2
            exit 1
        fi
        return
    fi

    if [ "$target" = "pm-agent" ]; then
        if [ "$force" = true ]; then
            rm -f "$SESSIONS_DIR/pm-agent.json"
            local base=$(get_base_session_id)
            if [ -n "$base" ] && [ "$base" != "null" ]; then
                write_index "\"$base\"" "null" "{}"
            else
                write_index "null" "null" "{}"
            fi
            echo "PM agent session destroyed"
        else
            echo "Error: destroying pm-agent session requires --pm-agent -y" >&2
            exit 1
        fi
        return
    fi

    validate_issue_ref "$target"

    local session_file=$(get_session_for_issue "$target")
    if [ -z "$session_file" ] || [ "$session_file" = "null" ]; then
        echo "Error: No session found for '$target'" >&2
        exit 1
    fi

    local session_path="$SESSIONS_DIR/$session_file"

    if [ "$force" = true ]; then
        remove_worktree_for_issue "$target"
        rm -f "$session_path"
        remove_issue_from_index "$target"
        echo "Session for '$target' destroyed"
    else
        echo "Delete session and worktree for '$target'? [y/N] "
        local reply
        read reply
        if [ "$reply" = "y" ] || [ "$reply" = "Y" ]; then
            remove_worktree_for_issue "$target"
            rm -f "$session_path"
            remove_issue_from_index "$target"
            echo "Session for '$target' destroyed"
        else
            echo "Aborted"
        fi
    fi
}

main() {
    if [ $# -eq 0 ]; then
        usage
        exit 1
    fi

    local command="$1"
    shift

    case "$command" in
        help|--help|-h)
            usage
            ;;
        init)
            cmd_init "$@"
            ;;
        start)
            cmd_start "$@"
            ;;
        continue)
            cmd_continue "$@"
            ;;
        list)
            cmd_list "$@"
            ;;
        prune)
            cmd_prune "$@"
            ;;
        destroy)
            cmd_destroy "$@"
            ;;
        *)
            echo "Error: unknown command '$command'" >&2
            usage
            exit 1
            ;;
    esac
}

main "$@"