# Justfile for Migrate Database Changes Workflow
# Docs: https://just.systems/man/en/

# ------------------------------------------------------------------------------
#  Global settings
# ------------------------------------------------------------------------------

# Load Env
set dotenv-load
set dotenv-required := true

# Use zsh
set shell := ["bash", "-cu"]

BATTLESNAKE_CLI_DIR := ".tools/battlesnake-cli"
BATTLESNAKE_CLI_BIN := ".tools/battlesnake-cli/battlesnake"

# ------------------------------------------------------------------------------
#  Default
# ------------------------------------------------------------------------------

# List all Available recipes
[private]
default:
  @just --list --unsorted

# ------------------------------------------------------------------------------
#  Snake Script helpers
# ------------------------------------------------------------------------------

run:
  "{{justfile_directory()}}/main.py"

run-snake port="8000" snake="BestBattleSnake":
  HOST="127.0.0.1" PORT="{{port}}" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py"

run-4-snakes base_port="9101" snake="BestBattleSnake":
  #!/usr/bin/env bash
  set -euo pipefail

  pids=()
  for i in 0 1 2 3; do
    port="$(({{base_port}} + i))"
    echo "Starting snake on :$port"
    HOST="127.0.0.1" PORT="$port" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py" &
    pids[$i]="$!"
  done

  cleanup() {
    for pid in "${pids[@]}"; do
      kill "$pid" 2>/dev/null || true
    done
    wait || true
  }
  trap cleanup EXIT INT TERM

  wait

bench-best-snake iterations="1000":
  #!/usr/bin/env bash
  set -euo pipefail

  PYTHONPATH="{{justfile_directory()}}" python "{{justfile_directory()}}/tests/bench_best_battle_snake.py" --iterations "{{iterations}}"

build-battlesnake-cli:
  #!/usr/bin/env bash
  set -euo pipefail

  install_dir="{{justfile_directory()}}/{{BATTLESNAKE_CLI_DIR}}"
  bin_path="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}"
  mkdir -p "$install_dir"

  if [ ! -f "{{justfile_directory()}}/local-client/go.mod" ]; then
    echo "Missing local-client source. Run: git submodule update --init --recursive"
    exit 1
  fi

  (
    cd "{{justfile_directory()}}/local-client"
    go build -o "$bin_path" ./cli/battlesnake/main.go
  )

  "$bin_path" --help > /dev/null
  echo "Built Battlesnake CLI at $bin_path"

battlesnake-cli-version:
  #!/usr/bin/env bash
  set -euo pipefail

  "{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" --help

# ------------------------------------------------------------------------------
#  Testing helpers
# ------------------------------------------------------------------------------

test-constrictor: build-battlesnake-cli
  #!/usr/bin/env bash
  set -euo pipefail

  BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}"
  "$BATTLESNAKE_CLI" play -W 11 -H 11 --name 'Python Starter Project' --url http://localhost:8000 -g constrictor --browser --minimumFood 0

test-seed: build-battlesnake-cli
  #!/usr/bin/env bash
  set -euo pipefail

  BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}"
  "$BATTLESNAKE_CLI" play -W 11 -H 11 --name 'Python Starter Project' --url http://localhost:8000 -g solo --browser --seed 1713099635738952360

test-local-4 mode="standard" map="standard" base_port="9101" snake="BestBattleSnake" seed="1713099635738952360" browser="true": build-battlesnake-cli
  #!/usr/bin/env bash
  set -euo pipefail

  BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}"
  LOG_DIR="{{justfile_directory()}}/.tools/snake-logs"
  mkdir -p "$LOG_DIR"

  pids=()
  for i in 0 1 2 3; do
    port="$(({{base_port}} + i))"
    log_file="$LOG_DIR/snake-$((i+1)).log"
    echo "Starting snake-$((i+1)) on :$port (log: $log_file)"
    HOST="127.0.0.1" PORT="$port" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py" > >(tee "$log_file") 2>&1 &
    pids[$i]="$!"
  done

  cleanup() {
    for pid in "${pids[@]}"; do
      kill "$pid" 2>/dev/null || true
    done
    wait || true
  }
  trap cleanup EXIT INT TERM

  for i in 0 1 2 3; do
    port="$(({{base_port}} + i))"
    for _ in $(seq 1 30); do
      if curl -fsS "http://127.0.0.1:$port" >/dev/null 2>&1; then
        break
      fi
      sleep 0.2
    done
    if ! curl -fsS "http://127.0.0.1:$port" >/dev/null 2>&1; then
      echo "Snake on :$port did not start correctly. Check logs in $LOG_DIR"
      exit 1
    fi
  done

  BROWSER_FLAG=""
  if [ "{{browser}}" = "true" ]; then
    BROWSER_FLAG="--browser"
  fi

  "$BATTLESNAKE_CLI" play -W 11 -H 11 \
    --name "Snake 1" --url "http://127.0.0.1:{{base_port}}" \
    --name "Snake 2" --url "http://127.0.0.1:$(({{base_port}} + 1))" \
    --name "Snake 3" --url "http://127.0.0.1:$(({{base_port}} + 2))" \
    --name "Snake 4" --url "http://127.0.0.1:$(({{base_port}} + 3))" \
    -g "{{mode}}" --map "{{map}}" --seed "{{seed}}" $BROWSER_FLAG

# ------------------------------------------------------------------------------
#  Fataset helpers
# ------------------------------------------------------------------------------

export-dataset input="data" output="data/dataset/good_moves.jsonl":
  python -m server.DatasetExporter --input "{{input}}" --output "{{output}}"

curate-dataset input="good_moves-*.jsonl" output="data/dataset/best_moves.jsonl" min_turn="6" late_turn="20" max_safe_options="2" min_score="3" append="false" archive="false" archive_dir="":
  FLAGS=""; if [ "{{append}}" = "true" ]; then FLAGS="$FLAGS --append"; fi; if [ "{{archive}}" = "true" ]; then FLAGS="$FLAGS --archive-input"; fi; if [ -n "{{archive_dir}}" ]; then FLAGS="$FLAGS --archive-dir {{archive_dir}}"; fi; python -m server.DatasetCurator --input "{{input}}" --output "{{output}}" --min-turn "{{min_turn}}" --late-turn "{{late_turn}}" --max-safe-options "{{max_safe_options}}" --min-score "{{min_score}}" $FLAGS

analyze-dataset input="good_moves-*.jsonl" output="":
  if [ -n "{{output}}" ]; then python -m server.DatasetStats --input "{{input}}" --output "{{output}}"; else python -m server.DatasetStats --input "{{input}}"; fi
