#!/bin/bash
# kugetsu - OpenCode Session Manager
# Main dispatcher - sources all modules

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

source "$SCRIPT_DIR/kugetsu-config.sh"
source "$SCRIPT_DIR/kugetsu-index.sh"
source "$SCRIPT_DIR/kugetsu-worktree.sh"
source "$SCRIPT_DIR/kugetsu-log.sh"
source "$SCRIPT_DIR/kugetsu-session.sh"

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

Usage:
    kugetsu <command> [subcommand] [options]

Commands:
    init [--force]                                    Initialize base + pm-agent sessions (requires TTY)
    start <issue-ref> <message> [--debug]            Start task for issue (forks base session)
    continue <issue-ref> [message] [--debug]          Continue existing task for issue
    delegate <message>                                Send message to PM agent (fire-and-forget)
    logs [n]                                          Show recent delegation logs (default: 10)
    status                                            Check kugetsu initialization status
    doctor [--fix]                                    Diagnose and fix kugetsu issues
    notify [list|clear]                               Show or clear notifications
    list                                              List all tracked sessions
    prune [--force]                                  Remove orphaned sessions
    destroy <target> [-y]                             Delete session (issue, pm-agent, or base)
    set-pr <issue-ref> <pr-url>                       Set PR URL for session
    context <issue-ref>                               Show context for issue
    queue [subcommand]                                Queue management
    queue-daemon [subcommand]                         Queue daemon management
    env [subcommand]                                  Environment variable management
    server [subcommand]                                Git server configuration
    help [command]                                   Show help for a command

Use 'kugetsu <command> help' for subcommand help.
Example: kugetsu queue help, kugetsu queue-daemon help

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

usage_queue() {
    cat << 'EOF'
kugetsu queue - Queue management

Usage:
    kugetsu queue [subcommand]

Subcommands:
    list                                               Show pending tasks (default)
    stats                                              Show queue statistics
    clear                                              Clear all queue items
    enqueue <issue-ref> <message>                      Enqueue a task
    help                                               Show this help

Examples:
    kugetsu queue list
    kugetsu queue stats
    kugetsu queue clear
    kugetsu queue enqueue github.com/shoko/kugetsu#14 "fix bug"
EOF
}

usage_queue_daemon() {
    cat << 'EOF'
kugetsu queue-daemon - Queue daemon management

Usage:
    kugetsu queue-daemon [subcommand]

Subcommands:
    start                                              Start the queue daemon
    stop                                               Stop the queue daemon
    restart                                            Restart the queue daemon
    status                                             Check daemon status
    logs                                               Show recent daemon logs
    help                                               Show this help

Examples:
    kugetsu queue-daemon start
    kugetsu queue-daemon status
    kugetsu queue-daemon logs
EOF
}

usage_env() {
    cat << 'EOF'
kugetsu env - Environment variable management

Usage:
    kugetsu env [subcommand]

Subcommands:
    list                                               List all environment variables
    get <key>                                          Get a specific variable
    set <key> <value>                                  Set a variable
    rm <key>                                           Remove a variable
    help                                               Show this help

Examples:
    kugetsu env list
    kugetsu env get GITEA_TOKEN
    kugetsu env set CUSTOM_VAR "value"
    kugetsu env rm CUSTOM_VAR
EOF
}

usage_server() {
    cat << 'EOF'
kugetsu server - Git server configuration

Usage:
    kugetsu server [subcommand]

Subcommands:
    list                                               List all configured servers (default)
    add <name> <url>                                   Add a new server
    remove <name>                                      Remove a server
    default [<name>]                                   Get or set default server
    get [<name>]                                       Get server URL
    help                                               Show this help

Examples:
    kugetsu server list
    kugetsu server add github.com https://github.com
    kugetsu server default github.com
EOF
}

ensure_dirs() {
    mkdir -p "$SESSIONS_DIR"
    mkdir -p "$LOGS_DIR"
    mkdir -p "$WORKTREES_DIR"
    mkdir -p "$QUEUE_DIR"
    mkdir -p "$QUEUE_ITEMS_DIR"
}

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

issue_ref_to_context_file() {
    local issue_ref="$1"
    local context_filename=$(issue_ref_to_filename "$issue_ref")
    echo "$CONTEXT_DIR/${context_filename}.json"
}

kugetsu_context_load() {
    local issue_ref="$1"
    
    if [ "$ENABLE_CONTEXT_DUMP" != "true" ]; then
        echo ""
        return
    fi
    
    local context_file=$(issue_ref_to_context_file "$issue_ref")
    
    if [ ! -f "$context_file" ]; then
        echo ""
        return
    fi
    
    python3 << PYEOF
import json
import sys

context_file = "$context_file"

try:
    with open(context_file, 'r') as f:
        ctx = json.load(f)
    
    lines = []
    lines.append("## PREVIOUS CONTEXT")
    lines.append(f"Issue: {ctx.get('issue_ref', 'unknown')}")
    lines.append(f"Last updated: {ctx.get('updated_at', 'unknown')}")
    lines.append(f"Current branch: {ctx.get('current_branch', 'unknown')}")
    lines.append("")
    lines.append("### Previous work summary:")
    lines.append(ctx.get('last_message', '(no previous message)'))
    lines.append("")
    
    history = ctx.get('conversation_history', [])
    if history:
        lines.append("### Conversation history:")
        for msg in history[-5:]:
            role = msg.get('role', 'unknown')
            content = msg.get('content', '')
            ts = msg.get('timestamp', '')
            lines.append(f"- [{ts}] {role}: {content[:200]}...")
    
    print('\n'.join(lines))
    
except Exception as e:
    print(f"Warning: Failed to load context: {e}", file=sys.stderr)
    print("", file=sys.stderr)
PYEOF
}

kugetsu_context_dump() {
    local issue_ref="$1"
    local message="$2"
    local branch_name="${3:-}"
    
    if [ "$ENABLE_CONTEXT_DUMP" != "true" ]; then
        return
    fi
    
    local context_file=$(issue_ref_to_context_file "$issue_ref")
    mkdir -p "$CONTEXT_DIR"
    
    python3 << PYEOF
import json
import os
from datetime import datetime

context_file = "$context_file"
issue_ref = "$issue_ref"
message = """$message"""
branch_name = "$branch_name"

context = {
    "issue_ref": issue_ref,
    "current_branch": branch_name,
    "updated_at": datetime.now().isoformat() + "Z",
    "last_message": message[:500] if message else "",
    "conversation_history": []
}

if os.path.exists(context_file):
    try:
        with open(context_file, 'r') as f:
            existing = json.load(f)
        
        history = existing.get('conversation_history', [])
        history.append({
            "role": "user",
            "content": message[:1000] if message else "",
            "timestamp": datetime.now().isoformat() + "Z"
        })
        history = history[-20:]
        
        context["conversation_history"] = history
        context["created_at"] = existing.get("created_at", context["updated_at"])
    except:
        context["created_at"] = datetime.now().isoformat() + "Z"
else:
    context["created_at"] = datetime.now().isoformat() + "Z"

with open(context_file, 'w') as f:
    json.dump(context, f, indent=2)
PYEOF
}

kugetsu_context_update_message() {
    local issue_ref="$1"
    local message="$2"
    
    if [ "$ENABLE_CONTEXT_DUMP" != "true" ]; then
        return
    fi
    
    local context_file=$(issue_ref_to_context_file "$issue_ref")
    
    if [ ! -f "$context_file" ]; then
        return
    fi
    
    python3 << PYEOF
import json
from datetime import datetime

context_file = "$context_file"
message = """$message"""

try:
    with open(context_file, 'r') as f:
        ctx = json.load(f)
    
    history = ctx.get('conversation_history', [])
    history.append({
        "role": "assistant",
        "content": message[:1000] if message else "",
        "timestamp": datetime.now().isoformat() + "Z"
    })
    history = history[-20:]
    
    ctx["conversation_history"] = history
    ctx["last_message"] = message[:500] if message else ""
    ctx["updated_at"] = datetime.now().isoformat() + "Z"
    
    with open(context_file, 'w') as f:
        json.dump(ctx, f, indent=2)
except Exception as e:
    pass
PYEOF
}

ensure_queue_dirs() {
    mkdir -p "$QUEUE_DIR"
    mkdir -p "$QUEUE_ITEMS_DIR"
    mkdir -p "$LOGS_DIR"
}

generate_queue_id() {
    echo "q_$(date +%s)_$$_$RANDOM"
}

enqueue_task() {
    local issue_ref="$1"
    local message="$2"
    
    if [ -z "$issue_ref" ] || [ -z "$message" ]; then
        echo "Error: enqueue_task requires <issue-ref> and <message>" >&2
        return 1
    fi
    
    validate_issue_ref "$issue_ref"
    ensure_queue_dirs
    
    local queue_id=$(generate_queue_id)
    local pending_since=$(date -Iseconds)
    
    python3 << PYEOF
import json

queue_item = {
    "id": "$queue_id",
    "issue_ref": "$issue_ref",
    "message": """$message""",
    "state": "pending",
    "pending_since": "$pending_since",
    "notified_at": None,
    "completed_at": None,
    "error": None
}

with open("$QUEUE_ITEMS_DIR/${queue_id}.json", "w") as f:
    json.dump(queue_item, f, indent=2)

print(f"Enqueued: $queue_id")
PYEOF

    kugetsu_add_notification "task_queued" "Task queued: $issue_ref" "$issue_ref"
}

get_pending_tasks() {
    local limit="${1:-10}"
    
    if [ ! -d "$QUEUE_ITEMS_DIR" ]; then
        echo "[]"
        return
    fi
    
    python3 -c "
import json
import os
import sys

queue_dir = os.environ.get('QUEUE_ITEMS_DIR', '')
limit = int(sys.argv[1]) if len(sys.argv) > 1 else 10

items = []
if os.path.isdir(queue_dir):
    for filename in os.listdir(queue_dir):
        if filename.endswith('.json'):
            filepath = os.path.join(queue_dir, filename)
            try:
                with open(filepath) as f:
                    data = json.load(f)
                    if data.get('state') == 'pending':
                        items.append(data)
                        if len(items) >= limit:
                            break
            except:
                pass

print(json.dumps(items))
" "$limit"
}

get_queue_stats() {
    local total=0
    local pending=0
    local notified=0
    local completed=0
    local error=0
    
    if [ -d "$QUEUE_ITEMS_DIR" ]; then
        for file in "$QUEUE_ITEMS_DIR"/*.json; do
            [ -f "$file" ] || continue
            total=$((total + 1))
            local state=$(python3 -c "import json; print(json.load(open('$file')).get('state', ''))" 2>/dev/null || echo "")
            case "$state" in
                pending) pending=$((pending + 1)) ;;
                notified) notified=$((notified + 1)) ;;
                completed) completed=$((completed + 1)) ;;
                error) error=$((error + 1)) ;;
            esac
        done
    fi
    
    echo "{\"total\": $total, \"pending\": $pending, \"notified\": $notified, \"completed\": $completed, \"error\": $error}"
}

check_task_timeouts() {
    if [ ! -d "$QUEUE_ITEMS_DIR" ]; then
        return
    fi
    
    local timeout_hours="${TASK_TIMEOUT_HOURS:-1}"
    
    for item in "$QUEUE_ITEMS_DIR"/*.json; do
        [ -f "$item" ] || continue
        
        local state=$(python3 -c "import json; print(json.load(open('$item')).get('state', ''))" 2>/dev/null)
        if [ "$state" != "notified" ]; then
            continue
        fi
        
        local notified_at=$(python3 -c "import json; print(json.load(open('$item')).get('notified_at', ''))" 2>/dev/null)
        if [ -z "$notified_at" ]; then
            continue
        fi
        
        local queue_id=$(basename "$item" .json)
        local pid=$(python3 -c "import json; print(json.load(open('$item')).get('pid', ''))" 2>/dev/null)
        local session_id=$(python3 -c "import json; print(json.load(open('$item')).get('opencode_session_id', ''))" 2>/dev/null)
        local issue_ref=$(python3 -c "import json; print(json.load(open('$item')).get('issue_ref', ''))" 2>/dev/null)
        
        local notified_epoch=$(date -d "$notified_at" +%s 2>/dev/null || echo "0")
        local now_epoch=$(date +%s)
        local hours_elapsed=$(( (now_epoch - notified_epoch) / 3600 ))
        
        if [ "$hours_elapsed" -ge "$timeout_hours" ]; then
            echo "Task $queue_id ($issue_ref) timed out after ${hours_elapsed}h"
            
            if [ -n "$session_id" ]; then
                opencode session stop "$session_id" 2>/dev/null || true
            fi
            
            if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
                kill "$pid" 2>/dev/null || true
            fi
            
            update_queue_item_state "$queue_id" "error"
        fi
    done
}

cleanup_old_queue_items() {
    local days="${QUEUE_CLEANUP_AGE_DAYS:-7}"
    
    if [ ! -d "$QUEUE_ITEMS_DIR" ]; then
        return
    fi
    
    find "$QUEUE_ITEMS_DIR" -name "*.json" -type f -mtime "+$days" 2>/dev/null | while read -r file; do
        local state=$(python3 -c "import json; print(json.load(open('$file')).get('state', ''))" 2>/dev/null || echo "")
        if [ "$state" = "completed" ] || [ "$state" = "error" ]; then
            rm -f "$file"
            echo "Cleaned up: $(basename "$file")"
        fi
    done
}
update_session_pr_url() {
    local issue_ref="$1"
    local pr_url="$2"
    
    if [ -z "$issue_ref" ] || [ -z "$pr_url" ]; then
        echo "Error: update_session_pr_url requires <issue-ref> and <pr-url>" >&2
        return 1
    fi
    
    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
        return 1
    fi
    
    local session_path="$SESSIONS_DIR/$session_file"
    
    if [ ! -f "$session_path" ]; then
        echo "Error: Session file not found: $session_path" >&2
        return 1
    fi
    
    python3 << PYEOF
import json

session_path = "$session_path"
pr_url = "$pr_url"

with open(session_path, 'r') as f:
    session = json.load(f)

session['pr_url'] = pr_url

with open(session_path, 'w') as f:
    json.dump(session, f, indent=2)

print(f"Updated pr_url to: {pr_url}")
PYEOF
}

read_index() {
    if [ -f "$INDEX_FILE" ]; then
        cat "$INDEX_FILE"
    else
        echo '{"base": null, "pm_agent": null, "issues": {}}'
    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 --format json 2>/dev/null | grep -q "\"$session_id\""
}

kugetsu_get_pm_context() {
    local user_pm_context="${KUGETSU_DIR}/pm-agent.md"
    local skill_pm_context="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../pm/SKILL.md"
    
    if [ -f "$user_pm_context" ]; then
        cat "$user_pm_context"
    elif [ -f "$skill_pm_context" ]; then
        cat "$skill_pm_context"
    else
        echo ""
    fi
}

kugetsu_get_fork_context() {
    local issue_ref="$1"
    local context=""
    
    context="## IMPORTANT WORKING RULES

1. You are working on issue: $issue_ref
2. If you encounter ANY error, blocker, or cannot complete the task:
   - STOP immediately
   - Log what happened and why you cannot proceed
   - Do NOT switch to other work or try alternative approaches
3. Do NOT work on other issues or PRs unless explicitly asked
4. Environment variables are available in ~/.kugetsu/env/

"
    
    if [ -f "$REPOS_CONFIG" ]; then
        context="${context}
## REPOSITORIES CONFIG
$(cat "$REPOS_CONFIG")

"
    fi
    
    if [ -f "$ENV_DIR/default.env" ]; then
        context="${context}
## ENVIRONMENT (available at ~/.kugetsu/env/)
Environment file exists at: $ENV_DIR/default.env
Source it with: source ~/.kugetsu/env/default.env
"
    fi
    
    echo "$context"
}

kugetsu_add_notification() {
    local type="$1"
    local message="$2"
    local issue_ref="${3:-}"
    local gitea_url="${4:-}"
    
    mkdir -p "$(dirname "$NOTIFICATIONS_FILE")"
    
    local notification=$(python3 << PYEOF
import json
import os
from datetime import datetime

notification = {
    "type": "$type",
    "message": "$message",
    "issue_ref": "$issue_ref" if "$issue_ref" else None,
    "gitea_url": "$gitea_url" if "$gitea_url" else None,
    "timestamp": datetime.now().isoformat(),
    "read": False
}

file_path = os.path.expanduser("$NOTIFICATIONS_FILE")
notifications = []

if os.path.exists(file_path):
    try:
        with open(file_path, 'r') as f:
            notifications = json.load(f)
    except:
        notifications = []

notifications.append(notification)

with open(file_path, 'w') as f:
    json.dump(notifications, f, indent=2)

print("Notification added")
PYEOF
)
    echo "$notification"
}

kugetsu_get_notifications() {
    local limit="${1:-10}"
    
    if [ ! -f "$NOTIFICATIONS_FILE" ]; then
        echo "[]"
        return
    fi
    
    python3 << PYEOF
import json
import os
from datetime import datetime

file_path = os.path.expanduser("$NOTIFICATIONS_FILE")

if not os.path.exists(file_path):
    print("[]")
    exit(0)

try:
    with open(file_path, 'r') as f:
        notifications = json.load(f)
    
    unread = [n for n in notifications if not n.get("read", False)]
    unread.sort(key=lambda x: x.get("timestamp", ""), reverse=True)
    
    for n in unread[:$limit]:
        ts = n.get("timestamp", "unknown")
        ntype = n.get("type", "info")
        msg = n.get("message", "")
        issue = n.get("issue_ref", "")
        gitea = n.get("gitea_url", "")
        
        print(f"[{ts}] {ntype}: {msg}")
        if issue:
            print(f"  Issue: {issue}")
        if gitea:
            print(f"  Link: {gitea}")
        print()
    
    if not unread:
        print("No unread notifications.")
    
except Exception as e:
    print(f"Error reading notifications: {e}")
PYEOF
}

kugetsu_clear_notifications() {
    if [ ! -f "$NOTIFICATIONS_FILE" ]; then
        return
    fi
    
    python3 << PYEOF
import json
import os

file_path = os.path.expanduser("$NOTIFICATIONS_FILE")

if not os.path.exists(file_path):
    exit(0)

try:
    with open(file_path, 'r') as f:
        notifications = json.load(f)
    
    for n in notifications:
        n["read"] = True
    
    with open(file_path, 'w') as f:
        json.dump(notifications, f, indent=2)
    
    print("Notifications marked as read")
except Exception as e:
    print(f"Error: {e}")
PYEOF
}

cmd_notify() {
    local action="${1:-}"
    
    case "$action" in
        ""|"list"|"show")
            kugetsu_get_notifications 10
            ;;
        "clear")
            kugetsu_clear_notifications
            ;;
        *)
            echo "Usage: kugetsu notify [list|clear]"
            ;;
    esac
}

cmd_status() {
    if [ ! -f "$INDEX_FILE" ]; then
        echo "kugetsu_not_initialized"
        return
    fi
    
    local base=$(get_base_session_id)
    local pm_agent=$(get_pm_agent_session_id)
    
    if [ -z "$base" ] || [ "$base" = "null" ]; then
        echo "base_session_missing"
        return
    fi
    
    if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ] || [ "$pm_agent" = "None" ]; then
        echo "pm_agent_missing"
        return
    fi
    
    local opencode_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' || true)
    
    if ! echo "$opencode_sessions" | grep -q "^${base}$"; then
        echo "error: base session '$base' not found in opencode"
        return
    fi
    
    if ! echo "$opencode_sessions" | grep -q "^${pm_agent}$"; then
        echo "error: pm_agent session '$pm_agent' not found in opencode"
        return
    fi
    
    echo "ok"
}

get_verbosity_context() {
    local verbosity="${KUGETSU_VERBOSITY:-default}"
    local verbosity_file="$VERBOSITY_DIR/${verbosity}.md"
    
    if [ -f "$verbosity_file" ]; then
        cat "$verbosity_file"
    else
        echo "## Verbosity: $verbosity"
    fi
}

init_verbosity_templates() {
    mkdir -p "$VERBOSITY_DIR"
    
    if [ ! -f "$VERBOSITY_DIR/verbose.md" ]; then
        cat > "$VERBOSITY_DIR/verbose.md" << 'EOF'
## Verbosity: Verbose

You are operating in HIGH verbosity mode. Include ALL available context:
- Full command outputs and their results
- Detailed reasoning and thinking process
- All file changes with diffs when relevant
- Complete log excerpts
- Comprehensive status updates
- Ask clarifying questions when uncertain
EOF
    fi
    
    if [ ! -f "$VERBOSITY_DIR/default.md" ]; then
        cat > "$VERBOSITY_DIR/default.md" << 'EOF'
## Verbosity: Default

You are operating in NORMAL verbosity mode. Provide balanced output:
- Standard command outputs and key results
- Moderate reasoning detail
- Important file changes summarized
- Regular status updates
EOF
    fi
    
    if [ ! -f "$VERBOSITY_DIR/quiet.md" ]; then
        cat > "$VERBOSITY_DIR/quiet.md" << 'EOF'
## Verbosity: Quiet

You are operating in QUIET verbosity mode. Keep output minimal:
- Only essential information
- Brief status updates (1-2 sentences)
- Final decisions only
- Yes/No answers when appropriate
EOF
    fi
}

parse_issue_ref_from_message() {
    # DEPRECATED: This function is not called anywhere.
    # The active implementation is extract_issue_ref_from_message()
    # in kugetsu-session.sh which is used by cmd_delegate.
    # This function is kept for backwards compatibility and will
    # be removed in a future release.
    local message="$1"
    
    local gitserver=""
    local owner=""
    local repo=""
    local issue_number=""
    
    if [[ "$message" =~ (https?://)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)/(issues|pull)/([0-9]+) ]]; then
        gitserver="${BASH_REMATCH[2]}"
        owner="${BASH_REMATCH[3]}"
        repo="${BASH_REMATCH[4]}"
        issue_number="${BASH_REMATCH[6]}"
    elif [[ "$message" =~ (https?://)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)#([0-9]+) ]]; then
        gitserver="${BASH_REMATCH[2]}"
        owner="${BASH_REMATCH[3]}"
        repo="${BASH_REMATCH[4]}"
        issue_number="${BASH_REMATCH[5]}"
    elif [[ "$message" =~ ([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)#([0-9]+) ]]; then
        owner="${BASH_REMATCH[1]}"
        repo="${BASH_REMATCH[2]}"
        issue_number="${BASH_REMATCH[3]}"
    fi
    
    echo "${gitserver}|${owner}|${repo}|${issue_number}"
}

get_missing_info() {
    local parsed="$1"
    local gitserver=$(echo "$parsed" | cut -d'|' -f1)
    local owner=$(echo "$parsed" | cut -d'|' -f2)
    local repo=$(echo "$parsed" | cut -d'|' -f3)
    local issue_number=$(echo "$parsed" | cut -d'|' -f4)
    
    local missing=""
    [ -z "$gitserver" ] && missing="${missing}git server, "
    [ -z "$owner" ] && missing="${missing}owner, "
    [ -z "$repo" ] && missing="${missing}repository, "
    [ -z "$issue_number" ] && missing="${missing}issue number, "
    
    echo "$missing" | sed 's/, $//'
}

build_missing_info_context() {
    local missing="$1"
    if [ -n "$missing" ]; then
        echo ""
        echo "NOTE: This task delegation has no information about: ${missing}."
        echo "We need them if user wants to work on a specific issue. Otherwise we don't need it."
    fi
}

find_worktrees_by_issue_number() {
    local issue_number="$1"
    local results=""
    
    if [ ! -d "$WORKTREES_DIR/.kugetsu-worktrees" ]; then
        echo ""
        return
    fi
    
    for wt in "$WORKTREES_DIR/.kugetsu-worktrees"/*; do
        if [ -d "$wt" ]; then
            local wt_issue_number=$(echo "$wt" | grep -oE '#?[0-9]+$' | grep -oE '[0-9]+' | head -1)
            if [ "$wt_issue_number" = "$issue_number" ]; then
                results="${results}${wt}:worktree
"
            fi
        fi
    done
    
    echo "$results"
}

find_sessions_by_issue_number() {
    local issue_number="$1"
    local results=""
    
    if [ ! -d "$SESSIONS_DIR" ]; then
        echo ""
        return
    fi
    
    for session_file in "$SESSIONS_DIR"/*.json; do
        if [ -f "$session_file" ]; then
            local session_issue_ref=$(basename "$session_file" .json | sed 's/_/\//g')
            local session_issue_number=$(echo "$session_issue_ref" | grep -oE '#?[0-9]+$' | grep -oE '[0-9]+' | head -1)
            if [ "$session_issue_number" = "$issue_number" ]; then
                results="${results}${session_file}:session
"
            fi
        fi
    done
    
    echo "$results"
}

cmd_queue() {
    local action="${1:-}"
    
    case "$action" in
        ""|help|--help|-h)
            usage_queue
            ;;
        help|--help|-h)
            usage_queue
            ;;
        list)
            local pending_tasks=$(get_pending_tasks 10)
            if [ "$pending_tasks" = "[]" ]; then
                echo "No pending tasks in queue."
            else
                echo "Pending tasks:"
                echo "$pending_tasks" | python3 -c "import sys, json; [print(f\"  {t.get('id')}: {t.get('issue_ref')} - {t.get('message', '')[:50]}...\") for t in json.load(sys.stdin)]"
            fi
            ;;
        stats)
            local stats=$(get_queue_stats)
            echo "Queue statistics:"
            echo "$stats" | python3 -c "import sys, json; d=json.load(sys.stdin); print(f\"  Total: {d.get('total', 0)}\n  Pending: {d.get('pending', 0)}\n  Notified: {d.get('notified', 0)}\n  Completed: {d.get('completed', 0)}\n  Error: {d.get('error', 0)}\")"
            ;;
        clear)
            if [ ! -d "$QUEUE_ITEMS_DIR" ]; then
                echo "Queue is already empty."
                return
            fi
            local count=$(ls -1 "$QUEUE_ITEMS_DIR"/*.json 2>/dev/null | wc -l)
            if [ "$count" -eq 0 ]; then
                echo "Queue is already empty."
                return
            fi
            echo "Clearing $count queue items..."
            rm -f "$QUEUE_ITEMS_DIR"/*.json
            echo "Queue cleared."
            ;;
        enqueue)
            local issue_ref="${2:-}"
            local message="${3:-}"
            if [ -z "$issue_ref" ] || [ -z "$message" ]; then
                echo "Usage: kugetsu queue enqueue <issue-ref> <message>" >&2
                exit 1
            fi
            enqueue_task "$issue_ref" "$message"
            ;;
        check-timeouts)
            check_task_timeouts
            ;;
        *)
            echo "Unknown queue subcommand: $action" >&2
            usage_queue
            exit 1
            ;;
    esac
}

cmd_queue_daemon() {
    local action="${1:-}"
    
    case "$action" in
        ""|help|--help|-h)
            usage_queue_daemon
            ;;
        start)
            if [ -f "$QUEUE_DAEMON_PID_FILE" ]; then
                local old_pid=$(cat "$QUEUE_DAEMON_PID_FILE")
                if kill -0 "$old_pid" 2>/dev/null; then
                    echo "Queue daemon is already running (PID: $old_pid)"
                    return
                fi
                rm -f "$QUEUE_DAEMON_PID_FILE"
            fi
            
            ensure_queue_dirs
            
            nohup bash "$SCRIPT_DIR/kugetsu-queue-daemon.sh" >> "$QUEUE_DAEMON_LOG_FILE" 2>&1 &
            
            echo $! > "$QUEUE_DAEMON_PID_FILE"
            echo "Queue daemon started (PID: $(cat "$QUEUE_DAEMON_PID_FILE"))"
            ;;
        stop)
            if [ ! -f "$QUEUE_DAEMON_PID_FILE" ]; then
                echo "Queue daemon is not running."
                return
            fi
            local pid=$(cat "$QUEUE_DAEMON_PID_FILE")
            if kill -0 "$pid" 2>/dev/null; then
                kill "$pid"
                rm -f "$QUEUE_DAEMON_PID_FILE"
                echo "Queue daemon stopped."
            else
                echo "Queue daemon is not running (stale PID file)."
                rm -f "$QUEUE_DAEMON_PID_FILE"
            fi
            ;;
        restart)
            cmd_queue_daemon stop
            sleep 1
            cmd_queue_daemon start
            ;;
        status)
            if [ ! -f "$QUEUE_DAEMON_PID_FILE" ]; then
                echo "Queue daemon is not running."
                return
            fi
            local pid=$(cat "$QUEUE_DAEMON_PID_FILE")
            if kill -0 "$pid" 2>/dev/null; then
                echo "Queue daemon is running (PID: $pid)"
            else
                echo "Queue daemon is not running (stale PID file)."
                rm -f "$QUEUE_DAEMON_PID_FILE"
            fi
            ;;
        logs)
            if [ -f "$QUEUE_DAEMON_LOG_FILE" ]; then
                tail -50 "$QUEUE_DAEMON_LOG_FILE"
            else
                echo "No daemon logs found."
            fi
            ;;
        *)
            echo "Unknown queue-daemon subcommand: $action" >&2
            usage_queue_daemon
            exit 1
            ;;
    esac
}

get_verbosity_context() {
    local issue_ref="$1"
    local context_file="$VERBOSITY_DIR/${issue_ref##*/}.context"
    
    if [ ! -f "$context_file" ]; then
        echo "{}"
        return
    fi
    
    cat "$context_file"
}

get_missing_info() {
    local issue_ref="$1"
    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
        return
    fi
    
    local session_path="$SESSIONS_DIR/$session_file"
    
    if [ ! -f "$session_path" ]; then
        echo "Error: Session file not found: $session_path" >&2
        return
    fi
    
    python3 << PYEOF
import json

session_path = "$session_path"

with open(session_path, 'r') as f:
    session = json.load(f)

missing = []

if not session.get('pr_url'):
    missing.append('pr_url')

if not session.get('last_activity'):
    missing.append('last_activity')

if missing:
    print("Missing info:", ', '.join(missing))
else:
    print("Session info complete")
PYEOF
}

set_debug_mode() {
    local filtered_args=()
    local debug_mode=false
    
    for arg in "$@"; do
        case "$arg" in
            --debug)
                debug_mode=true
                ;;
            *)
                filtered_args+=("$arg")
                ;;
        esac
    done
    
    if [ "$debug_mode" = true ]; then
        export KUGETSU_VERBOSITY="debug"
        echo "[DEBUG] Debug mode enabled" >&2
    fi
    
    echo "${filtered_args[@]}"
}

cmd_env() {
    local action="${1:-}"
    
    case "$action" in
        ""|help|--help|-h)
            usage_env
            ;;
        list)
            echo "Agent environment variables:"
            if [ -d "$ENV_DIR" ]; then
                for env_file in "$ENV_DIR"/*.env; do
                    if [ -f "$env_file" ]; then
                        echo ""
                        echo "=== $(basename "$env_file") ==="
                        while IFS= read -r line; do
                            echo "  $(mask_sensitive_vars "$line")"
                        done < "$env_file"
                    fi
                done
            else
                echo "  No env files found in $ENV_DIR"
            fi
            ;;
        get)
            local key="${2:-}"
            if [ -z "$key" ]; then
                echo "Usage: kugetsu env get <key>" >&2
                exit 1
            fi
            load_agent_env "default"
            local value="${!key:-}"
            if [ -n "$value" ]; then
                echo "$value"
            else
                echo "Variable '$key' is not set" >&2
                exit 1
            fi
            ;;
        set)
            local key="${2:-}"
            local value="${3:-}"
            if [ -z "$key" ] || [ -z "$value" ]; then
                echo "Usage: kugetsu env set <key> <value>" >&2
                exit 1
            fi
            mkdir -p "$ENV_DIR"
            echo "${key}=${value}" >> "$ENV_DIR/default.env"
            echo "Set $key in $ENV_DIR/default.env"
            ;;
        rm|remove)
            local key="${2:-}"
            if [ -z "$key" ]; then
                echo "Usage: kugetsu env rm <key>" >&2
                exit 1
            fi
            if [ -f "$ENV_DIR/default.env" ]; then
                sed -i "/^${key}=/d" "$ENV_DIR/default.env"
                echo "Removed $key from $ENV_DIR/default.env"
            fi
            ;;
        *)
            echo "Unknown env subcommand: $action" >&2
            usage_env
            exit 1
            ;;
    esac
}

cmd_server() {
    local action="${1:-}"
    
    case "$action" in
        ""|help|--help|-h)
            usage_server
            ;;
        "list")
            if [ -z "${GIT_SERVERS+x}" ]; then
                echo "No git servers configured"
                return
            fi
            echo "Git servers:"
            for key in "${!GIT_SERVERS[@]}"; do
                local marker=""
                if [ "$key" = "$DEFAULT_GIT_SERVER" ]; then
                    marker=" (default)"
                fi
                echo "  $key -> ${GIT_SERVERS[$key]}$marker"
            done
            ;;
        add)
            local name="${2:-}"
            local url="${3:-}"
            if [ -z "$name" ] || [ -z "$url" ]; then
                echo "Usage: kugetsu server add <name> <url>" >&2
                exit 1
            fi
            if grep -q "^GIT_SERVERS\[" "$KUGETSU_DIR/config" 2>/dev/null; then
                sed -i "s|^GIT_SERVERS\[\"$name\"\]=.*|GIT_SERVERS[\"$name\"]=\"$url\"|" "$KUGETSU_DIR/config"
                if ! grep -q "GIT_SERVERS\[\"$name\"\]" "$KUGETSU_DIR/config" 2>/dev/null; then
                    sed -i "/^declare -A GIT_SERVERS/a GIT_SERVERS[\"$name\"]=\"$url\"" "$KUGETSU_DIR/config"
                fi
            else
                echo "declare -A GIT_SERVERS" >> "$KUGETSU_DIR/config"
                echo "GIT_SERVERS[\"$name\"]=\"$url\"" >> "$KUGETSU_DIR/config"
            fi
            source "$KUGETSU_DIR/config"
            echo "Added git server: $name -> $url"
            ;;
        remove|rm|delete)
            local name="${2:-}"
            if [ -z "$name" ]; then
                echo "Usage: kugetsu server remove <name>" >&2
                exit 1
            fi
            if [ -n "${GIT_SERVERS[$name]:-}" ]; then
                if [ "$name" = "$DEFAULT_GIT_SERVER" ]; then
                    echo "Error: Cannot remove default server. Set a new default first." >&2
                    exit 1
                fi
                sed -i "/GIT_SERVERS\[\"$name\"\]/d" "$KUGETSU_DIR/config" 2>/dev/null
                source "$KUGETSU_DIR/config"
                echo "Removed git server: $name"
            else
                echo "Error: Server '$name' not found" >&2
                exit 1
            fi
            ;;
        default)
            local name="${2:-}"
            if [ -z "$name" ]; then
                echo "Current default: $DEFAULT_GIT_SERVER"
                return
            fi
            if [ -n "${GIT_SERVERS[$name]:-}" ]; then
                sed -i "s/^DEFAULT_GIT_SERVER=.*/DEFAULT_GIT_SERVER=\"$name\"/" "$KUGETSU_DIR/config"
                source "$KUGETSU_DIR/config"
                echo "Set default git server to: $name"
            else
                echo "Error: Server '$name' not found" >&2
                exit 1
            fi
            ;;
        get)
            local name="${2:-$DEFAULT_GIT_SERVER}"
            if [ -n "${GIT_SERVERS[$name]:-}" ]; then
                echo "${GIT_SERVERS[$name]}"
            else
                echo "Error: Server '$name' not found" >&2
                exit 1
            fi
            ;;
        *)
            echo "Unknown server subcommand: $action" >&2
            usage_server
            exit 1
            ;;
    esac
}

cmd_doctor() {
    local fix=false
    
    while [ $# -gt 0 ]; do
        case "$1" in
            --fix)
                fix=true
                ;;
            *)
                ;;
        esac
        shift
    done
    
    echo "=== kugetsu doctor ==="
    echo ""
    
    echo "Checking directories..."
    for dir in "$KUGETSU_DIR" "$SESSIONS_DIR" "$WORKTREES_DIR"; do
        if [ -d "$dir" ]; then
            echo "  [OK] $dir exists"
        else
            echo "  [MISSING] $dir"
            if [ "$fix" = true ]; then
                mkdir -p "$dir"
                echo "        Created $dir"
            fi
        fi
    done
    
    echo ""
    echo "Checking sessions..."
    local base_id=$(get_base_session_id)
    local pm_id=$(get_pm_agent_session_id)
    
    if [ -n "$base_id" ] && [ "$base_id" != "null" ]; then
        echo "  [OK] Base session: $base_id"
    else
        echo "  [MISSING] Base session not initialized"
    fi
    
    if [ -n "$pm_id" ] && [ "$pm_id" != "null" ]; then
        echo "  [OK] PM agent: $pm_id"
    else
        echo "  [WARNING] PM agent not initialized"
    fi
    
    echo ""
    echo "Checking opencode..."
    if command -v opencode &> /dev/null; then
        echo "  [OK] opencode command available"
        local sessions=$(opencode session list 2>/dev/null | grep -c "^ses_" || echo "0")
        echo "  [OK] $sessions opencode sessions found"
    else
        echo "  [MISSING] opencode command not found"
    fi
    
    echo ""
    echo "Checking index..."
    if [ -f "$INDEX_FILE" ]; then
        echo "  [OK] Index file exists"
    else
        echo "  [WARNING] Index file not found"
    fi
    
    echo ""
    echo "Doctor check complete."
}

mark_orphan() {
    local session_file="$1"
    local session_path="$SESSIONS_DIR/$session_file"
    
    if [ ! -f "$session_path" ]; then
        return
    fi
    
    python3 << PYEOF
import json

session_path = "$session_path"

with open(session_path, 'r') as f:
    session = json.load(f)

session['state'] = 'orphan'
session['orphaned_at'] = '$(date -Iseconds)'

with open(session_path, 'w') as f:
    json.dump(session, f, indent=2)
PYEOF
}

main() {
    if [ $# -eq 0 ]; then
        usage
        exit 1
    fi
    
    local command="$1"
    shift
    
    case "$command" in
        help|--help|-h)
            local subcommand="${1:-}"
            case "$subcommand" in
                queue|"")
                    usage_queue
                    ;;
                queue-daemon)
                    usage_queue_daemon
                    ;;
                env)
                    usage_env
                    ;;
                server)
                    usage_server
                    ;;
                "")
                    usage
                    ;;
                *)
                    echo "Help not available for '$subcommand'" >&2
                    usage
                    exit 1
                    ;;
            esac
            ;;
        init)
            cmd_init "$@"
            ;;
        start)
            cmd_start "$@"
            ;;
        continue)
            cmd_continue "$@"
            ;;
        delegate)
            cmd_delegate "$@"
            ;;
        logs)
            cmd_logs "$@"
            ;;
        status)
            cmd_status
            ;;
        doctor)
            cmd_doctor "$@"
            ;;
        notify)
            cmd_notify "$@"
            ;;
        list)
            cmd_list "$@"
            ;;
        prune)
            cmd_prune "$@"
            ;;
        destroy)
            cmd_destroy "$@"
            ;;
        set-pr)
            local issue_ref="${1:-}"
            local pr_url="${2:-}"
            if [ -z "$issue_ref" ] || [ -z "$pr_url" ]; then
                echo "Usage: kugetsu set-pr <issue-ref> <pr-url>" >&2
                echo "Example: kugetsu set-pr github.com/shoko/kugetsu#14 https://github.com/shoko/kugetsu/pulls/123" >&2
                exit 1
            fi
            validate_issue_ref "$issue_ref"
            update_session_pr_url "$issue_ref" "$pr_url"
            ;;
        context)
            local issue_ref="${1:-}"
            if [ -z "$issue_ref" ]; then
                echo "Usage: kugetsu context <issue-ref>" >&2
                echo "Show context for an issue" >&2
                exit 1
            fi
            validate_issue_ref "$issue_ref"
            local context_file=$(issue_ref_to_context_file "$issue_ref")
            if [ -f "$context_file" ]; then
                cat "$context_file"
            else
                echo "No context found for '$issue_ref'" >&2
                exit 1
            fi
            ;;
        queue)
            local action="${1:-list}"
            shift
            cmd_queue "$action" "$@"
            ;;
        queue-daemon)
            local action="${1:-status}"
            shift
            cmd_queue_daemon "$action" "$@"
            ;;
        env)
            cmd_env "$@"
            ;;
        server)
            cmd_server "$@"
            ;;
        *)
            echo "Error: unknown command '$command'" >&2
            usage
            exit 1
            ;;
    esac
}

main "$@"
