#!/usr/bin/env bash
# gsl — Goose Session Launcher (fzf TUI, external executable)
# Usage: gsl [limit]
# Requires: goose, fzf, jq

set -euo pipefail

# Prefer the VERSION file next to the script (repo checkout, script-copy install);
# fall back to the packaged path, then to the hardcoded constant.
VERSION=$(cat "$(dirname "$0")/VERSION" 2>/dev/null || cat /usr/share/gsl/VERSION 2>/dev/null || echo 0.1.0)

usage() {
    cat <<'EOF'
gsl — Goose Session Launcher

Usage:
  gsl [limit]

Fuzzy-search and resume goose sessions from the terminal.

  limit   number of most recent sessions to load (default: 30)

Keybindings:
  Enter   resume the selected session
  Ctrl-R  refresh the session list
  Ctrl-L  load all sessions (500)
  Esc     cancel

Requires: goose, fzf, jq
EOF
}

for dep in goose fzf jq; do
    if ! command -v "$dep" >/dev/null 2>&1; then
        printf '\033[1;31m%s not found.\033[0m gsl requires %s (e.g. "apt install %s" / "zypper install %s")\n' "$dep" "$dep" "$dep" "$dep" >&2
        exit 1
    fi
done

case "${1:-}" in
    -h|--help)
        usage
        exit 0
        ;;
    --version)
        echo "$VERSION"
        exit 0
        ;;
    "")
        LIMIT=30
        ;;
    *)
        if ! [[ "$1" =~ ^[0-9]+$ ]] || [ "$1" -lt 1 ]; then
            printf '\033[1;31mInvalid limit: %s\033[0m (expected a positive integer)\n' "$1" >&2
            exit 1
        fi
        LIMIT="$1"
        ;;
esac

if ! sessions_json=$(goose session list --format json -l "$LIMIT" 2>&1); then
    printf '\033[1;31mgoose session list failed:\033[0m\n%s\n' "$sessions_json" >&2
    exit 1
fi

if [ -z "$sessions_json" ] || [ "$sessions_json" = "[]" ]; then
    printf '\033[1;31mNo sessions found.\033[0m\n' >&2
    exit 1
fi

build_fzf_input() {
    local json="$1"
    echo "$json" | jq -c '.[]' | while IFS= read -r row; do
        local id name msgs date dir
        id=$(echo "$row" | jq -r '.id')
        name=$(echo "$row" | jq -r '.name // "Unnamed"')
        msgs=$(echo "$row" | jq -r '.message_count // 0')
        date=$(echo "$row" | jq -r '.updated_at // ""' | sed 's/T/ /;s/Z//')
        dir=$(echo "$row" | jq -r '.working_dir // ""' | sed "s|$HOME|~|")

        if [ "$msgs" -gt 0 ]; then
            printf "%s  \033[32m%-35s\033[0m  %4s msgs  \033[2m%-16s  %s\033[0m\n" "$id" "$name" "$msgs" "$date" "$dir"
        else
            printf "%s  \033[2m%-35s\033[0m     msgs  \033[2m%-16s  %s\033[0m\n" "$id" "$name" "$date" "$dir"
        fi
    done
}

# fzf reload command (plain output, no ANSI) for the current limit.
reload_cmd() {
    printf '%s\n' "goose session list --format json -l $1 | jq -c '.[]' | while IFS= read -r row; do id=\$(echo \"\$row\" | jq -r '.id'); name=\$(echo \"\$row\" | jq -r '.name // \"Unnamed\"'); msgs=\$(echo \"\$row\" | jq -r '.message_count // 0'); date=\$(echo \"\$row\" | jq -r '.updated_at // \"\"' | sed 's/T/ /;s/Z//'); dir=\$(echo \"\$row\" | jq -r '.working_dir // \"\"' | sed \"s|\$HOME|~|\"); if [ \"\$msgs\" -gt 0 ]; then printf '%s  %-35s  %4s msgs  %-16s  %s\n' \"\$id\" \"\$name\" \"\$msgs\" \"\$date\" \"\$dir\"; else printf '%s  %-35s     msgs  %-16s  %s\n' \"\$id\" \"\$name\" \"\$date\" \"\$dir\"; fi; done"
}

RELOAD_ALL=$(reload_cmd 500)
RELOAD_CURRENT=$(reload_cmd "$LIMIT")

selected=$(build_fzf_input "$sessions_json" | fzf \
    --prompt=" sessions > " \
    --ansi \
    --height=40 \
    --reverse \
    --border=rounded \
    --margin=0,1 \
    --info=inline \
    --header="Enter: resume │ Ctrl-L: load all │ Ctrl-R: refresh" \
    --preview="gsl-preview {}" \
    --preview-window=right:50%:wrap \
    --bind="ctrl-l:reload($RELOAD_ALL)" \
    --bind="ctrl-r:reload($RELOAD_CURRENT)" \
    --color="bg+:#1a1b26,fg+:#c0caf5,hl+:#ff9e64,info:#7aa2f7,prompt:#7aa2f7,pointer:#ff9e64,marker:#9ece6a,spinner:#9ece6a,header:#565f89" \
    2>/dev/null || true)

if [ -z "$selected" ]; then
    exit 0
fi

selected_id=$(echo "$selected" | awk '{print $1}')

printf '\n  \033[1;32mResuming:\033[0m \033[2m%s\033[0m\n\n' "$selected_id"

exec goose session --resume --history --session-id "$selected_id"
