#!/usr/bin/env bash
# osh: interactive chat interface for ollie AI agents.
set -o history

MOUNT=${OLLIE_9MOUNT:-$HOME/mnt/ollie}
LAST=$HOME/.config/ollie/last-session

# load_session <dir>  → prints session ID for that dir, or nothing
load_session() {
    awk -F'\t' -v d="$1" 'NF==2 && $1==d {print $2; exit}' "$LAST" 2>/dev/null
}

# save_session <dir> <id>  → upserts {dir}\t{id} in $LAST
save_session() {
    local dir="$1" id="$2" tmp
    mkdir -p "$(dirname "$LAST")"
    tmp=$(mktemp)
    awk -F'\t' -v d="$dir" 'NF==2 && $1!=d' "$LAST" 2>/dev/null > "$tmp" || true
    printf '%s\t%s\n' "$dir" "$id" >> "$tmp"
    mv "$tmp" "$LAST"
}

die()     { printf 'error: %s\n' "$*" >&2; exit 1; }
is_idle() { [ "$(tr -d '[:space:]' < "$S/state" 2>/dev/null)" = "idle" ]; }
drain() {
    local n
    n=$(wc -c < "$S/chat" 2>/dev/null || echo 0)
    [ "$n" -gt "$chat_off" ] && tail -c "+$((chat_off+1))" "$S/chat" | head -c "$((n-chat_off))"
    chat_off=$n
}

# Parse flags
new=0; resume=0; id_flag=; name=
backend=; model=; agent=; cwd=
while [ $# -gt 0 ]; do
    case $1 in
        -new)      new=1 ;;
        -resume)   resume=1 ;;
        -session)  id_flag=$2; shift ;;
        -name)     name=$2;    shift ;;
        -backend)  backend=$2; shift ;;
        -model)    model=$2;   shift ;;
        -agent)    agent=$2;   shift ;;
        -cwd)      cwd=$2;     shift ;;
        *) die "unknown flag: $1" ;;
    esac
    shift
done

# Write spec to s/new
write_new() {
    {
        [ -n "$name"    ] && printf 'name=%s\n'    "$name"
        printf 'cwd=%s\n' "${cwd:-$(pwd)}"
        [ -n "$backend" ] && printf 'backend=%s\n' "$backend"
        [ -n "$model"   ] && printf 'model=%s\n'   "$model"
        [ -n "$agent"   ] && printf 'agent=%s\n'   "$agent"
        true
    } > "$MOUNT/s/new" || die "write s/new"
}

# Create a fresh session, sets $id
create_session() {
    local before d deadline
    if [ -n "$name" ]; then
        write_new
        id=$name
    else
        before=$(ls "$MOUNT/s" 2>/dev/null)
        write_new
        deadline=$(($(date +%s) + 5))
        while [ "$(date +%s)" -lt "$deadline" ]; do
            for d in $(ls "$MOUNT/s" 2>/dev/null); do
                printf '%s\n' "$before" | grep -qxF "$d" || { id=$d; return; }
            done
            sleep 0.05
        done
        die "timeout waiting for new session"
    fi
}

# Resolve session
_dir=${cwd:-$(pwd)}
if   [ -n "$id_flag" ]; then
    [ -d "$MOUNT/s/$id_flag" ] || die "session not found: $id_flag"
    id=$id_flag; printf 'session: %s (resumed)\n' "$id" >&2
elif [ "$resume" = 1 ]; then
    id=$(load_session "$_dir")
    [ -n "$id" ] && [ -d "$MOUNT/s/$id" ] || die "no resumable session for $_dir"
    printf 'session: %s (resumed)\n' "$id" >&2
elif [ "$new" = 1 ]; then
    create_session
    save_session "$_dir" "$id"
    printf 'session: %s\n' "$id" >&2
else
    id=$(load_session "$_dir")
    if [ -n "$id" ] && [ -d "$MOUNT/s/$id" ]; then
        printf 'session: %s (resumed)\n' "$id" >&2
    else
        create_session
        save_session "$_dir" "$id"
        printf 'session: %s\n' "$id" >&2
    fi
fi

S=$MOUNT/s/$id
chat_off=$(wc -c < "$S/chat" 2>/dev/null || echo 0)

trap '
    [ "$(tr -d "[:space:]" < "$S/state" 2>/dev/null)" = "idle" ] && exit
    printf "\n" >&2; printf "stop\n" > "$S/ctl"
' INT

while true; do
    printf '> '
    IFS= read -re input || break
    [ -z "$input" ] && continue
    history -s "$input"
    case "$input" in
        /kill)  printf 'kill\n' > "$S/ctl"; break ;;
        "/q "*)  printf '%s\n' "${input#/q }" > "$S/enqueue"
                printf 'queued\n' >&2; continue ;;
        /*)     printf '%s\n' "$input" > "$S/ctl" ;;
        *)      printf '%s' "$input" > "$S/prompt" || { printf 'submit failed\n' >&2; continue; } ;;
    esac
    sleep 0.15
    while true; do
        drain
        is_idle && { drain; printf '\n'; break; }
        sleep 0.05
    done
done
