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

usage() {
    cat <<'EOF'
Usage: ralph.sh <run-directory> [options]

Arguments:
  run-directory            Path to the Ralph run directory (must contain instructions.md)

Options:
  -n, --max-iterations N   Maximum iterations (default: 20)
  -m, --model MODEL        Claude model to use (default: opus)
  -t, --tools TOOLS        Allowed tools, quoted (default: "Read Edit Write")
  -h, --help               Show this help message

Examples:
  ./ralph.sh .ralph/my-run
  ./ralph.sh .ralph/my-run -n 10 -m sonnet
  ./ralph.sh .ralph/my-run -n 30 -t "Read Edit Write Bash Glob Grep"
EOF
    exit 0
}

# Defaults
MAX_ITERATIONS=20
MODEL="opus"
TOOLS="Read Edit Write"
RUN_DIR=""

# Parse args
while [[ $# -gt 0 ]]; do
    case $1 in
        -n|--max-iterations) MAX_ITERATIONS="$2"; shift 2 ;;
        -m|--model) MODEL="$2"; shift 2 ;;
        -t|--tools) TOOLS="$2"; shift 2 ;;
        -h|--help) usage ;;
        -*) echo "Error: Unknown option: $1" >&2; exit 1 ;;
        *) RUN_DIR="$1"; shift ;;
    esac
done

if [[ -z "$RUN_DIR" ]]; then
    echo "Error: No run directory specified." >&2
    echo "Run './ralph.sh --help' for usage." >&2
    exit 1
fi

if [[ ! -d "$RUN_DIR" ]]; then
    echo "Error: Run directory '$RUN_DIR' does not exist." >&2
    exit 1
fi

if [[ ! -f "$RUN_DIR/instructions.md" ]]; then
    echo "Error: '$RUN_DIR/instructions.md' not found." >&2
    echo "Create an instructions.md in the run directory before starting." >&2
    exit 1
fi

# Auto-create template files if they don't exist
RUN_NAME=$(basename "$RUN_DIR")
TODAY=$(date +%Y-%m-%d)

if [[ ! -f "$RUN_DIR/meta.md" ]]; then
    cat > "$RUN_DIR/meta.md" <<EOF
# Run: $RUN_NAME

- **Created**: $TODAY
- **Description**: (add description here)
- **Model**: $MODEL
- **Max iterations**: $MAX_ITERATIONS
EOF
    echo "Created $RUN_DIR/meta.md"
fi

if [[ ! -f "$RUN_DIR/chief-wiggum.md" ]]; then
    cat > "$RUN_DIR/chief-wiggum.md" <<'EOF'
# Chief Wiggum's Notes

<!-- This file is written by the Chief Wiggum session. Ralph reads it but never modifies it. -->

## Action Required

(No action items.)

## Observations

(No observations.)
EOF
    echo "Created $RUN_DIR/chief-wiggum.md"
fi

if [[ ! -f "$RUN_DIR/answers.md" ]]; then
    cat > "$RUN_DIR/answers.md" <<'EOF'
# Answers

<!-- Human answers to open questions. Ralph processes these one per iteration. -->
EOF
    echo "Created $RUN_DIR/answers.md"
fi

if [[ ! -f "$RUN_DIR/questions.md" ]]; then
    cat > "$RUN_DIR/questions.md" <<'EOF'
# Questions

## Open

(No open questions.)

## Resolved

(No resolved questions.)
EOF
    echo "Created $RUN_DIR/questions.md"
fi

if [[ ! -f "$RUN_DIR/progress.txt" ]]; then
    cat > "$RUN_DIR/progress.txt" <<'EOF'
# Ralph Loop Progress Log
# Each iteration appends its findings and decisions here.
EOF
    echo "Created $RUN_DIR/progress.txt"
fi

# Prepare prompt with {{RUN_DIR}} substitution
PROMPT=$(sed "s|{{RUN_DIR}}|$RUN_DIR|g" "$RUN_DIR/instructions.md")

COMPLETION_SIGNAL="<promise>COMPLETE</promise>"
TIMESTAMP=$(date +%Y-%m-%dT%H:%M:%S)

# Append to run.log
echo "" >> "$RUN_DIR/run.log"
echo "=== Run started: $TIMESTAMP | model=$MODEL | max=$MAX_ITERATIONS ===" >> "$RUN_DIR/run.log"

echo "=== Ralph Loop ==="
echo "Run dir:    $RUN_DIR"
echo "Model:      $MODEL"
echo "Max iter:   $MAX_ITERATIONS"
echo "Tools:      $TOOLS"
echo ""

for ((i = 1; i <= MAX_ITERATIONS; i++)); do
    echo ""
    echo "━━━ Iteration $i/$MAX_ITERATIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    ITER_START=$(date +%H:%M:%S)
    echo "Started: $ITER_START"
    echo ""

    ITER_LOG="$RUN_DIR/iteration-${i}.jsonl"

    echo "$PROMPT" | claude --print --model "$MODEL" --allowedTools "$TOOLS" --verbose --output-format stream-json > "$ITER_LOG" 2>&1

    ITER_TIME=$(date +%H:%M:%S)

    # Extract tool uses for a compact summary
    TOOL_SUMMARY=$(jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | "  -> \(.name): \(.input.file_path // .input.pattern // .input.command // .input.content[0:80] // "" | tostring | .[0:100])"' "$ITER_LOG" 2>/dev/null) || true

    if [[ -n "$TOOL_SUMMARY" ]]; then
        echo "Tools used:"
        echo "$TOOL_SUMMARY"
        echo ""
    fi

    # Extract assistant text messages
    ASSISTANT_TEXT=$(jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "text") | .text' "$ITER_LOG" 2>/dev/null) || true

    if [[ -n "$ASSISTANT_TEXT" ]]; then
        echo "Ralph says:"
        echo "$ASSISTANT_TEXT" | sed 's/^/  /'
        echo ""
    fi

    # Check for errors
    ERROR_TEXT=$(jq -r 'select(.type == "result") | select(.subtype == "error") | .result' "$ITER_LOG" 2>/dev/null) || true
    if [[ -n "$ERROR_TEXT" ]]; then
        echo "[ERROR] $ERROR_TEXT"
    fi

    # Check for completion signal
    if grep -q "$COMPLETION_SIGNAL" "$ITER_LOG" 2>/dev/null; then
        echo "[$ITER_TIME] COMPLETE after $i iteration(s)" >> "$RUN_DIR/run.log"
        echo "━━━ Loop complete after $i iteration(s). ━━━"
        exit 0
    fi

    echo "[$ITER_TIME] Iteration $i done" >> "$RUN_DIR/run.log"
    echo "--- Done at $ITER_TIME ---"
    sleep 2
done

ITER_TIME=$(date +%H:%M:%S)
echo "[$ITER_TIME] WARNING: Max iterations ($MAX_ITERATIONS) reached without completion" >> "$RUN_DIR/run.log"
echo "WARNING: Max iterations ($MAX_ITERATIONS) reached without completion."
exit 1
