#!/usr/bin/env bash
# Tests for the oo script — focus on 3-level dotted method dispatch
# Tests: mode, mode.list, mode.base.get, mode.base.set, mode.base.get persistence

level=$1
if [ -z "$level" ]; then
  level=1
else
  shift
fi
echo "starting: ${BASH_SOURCE[@]##*/} <LOG_LEVEL=$level>"

source this
source test.suite
source oo

log.level $level

# ============================================================================
# T1: oo.mode.base.get returns a valid directory (3-level dotted method)
# ============================================================================
test.oo.t1() {
  local base
  base=$(oo.mode.base.get)
  if [ -d "$base" ]; then
    create.result 0 "$base"
  else
    create.result 1 "not a directory: $base"
  fi
}
test.case - "T1: oo.mode.base.get returns a directory path" \
  test.oo.t1
expect 0 "*" "oo.mode.base.get returns existing directory"

# ============================================================================
# T2: oo.mode.list runs without error (2-level dotted method)
# ============================================================================
test.case - "T2: oo.mode.list executes successfully" \
  oo.mode.list

create.result $? "mode.list ran"
expect 0 "mode.list ran" "oo.mode.list executes without error"

# ============================================================================
# T3: oo.mode shows current mode (1-level method via dispatcher)
# ============================================================================
test.case - "T3: oo.mode shows current mode" \
  oo.mode

create.result $? "mode ran"
expect 0 "mode ran" "oo.mode shows current mode without hanging"

# ============================================================================
# T4: oo.mode.base.set validates missing argument
# ============================================================================
test.oo.t4() {
  oo.mode.base.set
}
expect.error 1
test.case - "T4: oo.mode.base.set rejects missing argument" \
  test.oo.t4
expect 1 "*" "oo.mode.base.set requires path argument"

# ============================================================================
# T5: oo.mode.base.set validates non-existent directory
# ============================================================================
test.oo.t5() {
  oo.mode.base.set /nonexistent/path/$$
}
expect.error 1
test.case - "T5: oo.mode.base.set rejects non-existent directory" \
  test.oo.t5
expect 1 "*" "oo.mode.base.set rejects missing directory"

# ============================================================================
# T6: oo.mode.base.set accepts valid directory and persists
# ============================================================================
ORIGINAL_BASE=$(oo.mode.base.get)
TEST_DIR="${TMPDIR:-/tmp}/test.oo.$$"
mkdir -p "$TEST_DIR"

test.case - "T6: oo.mode.base.set accepts valid directory" \
  oo.mode.base.set "$TEST_DIR"

create.result $? "set to $TEST_DIR"
expect 0 "set to $TEST_DIR" "oo.mode.base.set accepts valid directory"

# ============================================================================
# T6b: oo.mode.base.set persists OOSH_COMPONENTS_DIR to oosh.env
# ============================================================================
OOSH_ENV="${CONFIG_PATH:-$HOME/config}/oosh.env"

test.case $level "T6b: mode.base.set persists OOSH_COMPONENTS_DIR to oosh.env" \
  echo "checking oosh.env"
if [ -f "$OOSH_ENV" ]; then
  T6B_LINE=$(grep "OOSH_COMPONENTS_DIR" "$OOSH_ENV")
  if echo "$T6B_LINE" | grep -q "$TEST_DIR"; then
    expect.pass "oosh.env has OOSH_COMPONENTS_DIR=$TEST_DIR"
  else
    expect.fail "oosh.env should have OOSH_COMPONENTS_DIR=$TEST_DIR; got: $T6B_LINE"
  fi
else
  expect.fail "oosh.env should exist after mode.base.set"
fi

# ============================================================================
# T7: oo.mode.base.get returns the value set in T6
# ============================================================================
test.oo.t7() {
  local base
  base=$(oo.mode.base.get)
  if [ "$base" = "$TEST_DIR" ]; then
    create.result 0 "$base"
  else
    create.result 1 "expected=$TEST_DIR got=$base"
  fi
}
test.case - "T7: oo.mode.base.get returns persisted value" \
  test.oo.t7
expect 0 "$TEST_DIR" "oo.mode.base.get returns value set by mode.base.set"

# ============================================================================
# T6c: mode.base.get returns value from env even when oosh.env cleared
# ============================================================================
test.case $level "T6c: mode.base.get returns value from env when file cleared" \
  echo "testing env persistence"
if [ -f "$OOSH_ENV" ]; then
  grep -v "OOSH_COMPONENTS_DIR" "$OOSH_ENV" > "${OOSH_ENV}.t6c" 2>/dev/null && mv "${OOSH_ENV}.t6c" "$OOSH_ENV"
fi
T6C_VAL=$(oo.mode.base.get 2>/dev/null)
if [ -n "$T6C_VAL" ] && [ -d "$T6C_VAL" ]; then
  expect.pass "get returns $T6C_VAL from env (even after oosh.env cleared)"
else
  expect.fail "mode.base.get should return value from env: $T6C_VAL"
fi

# Cleanup: restore original base
if [ -n "$ORIGINAL_BASE" ] && [ -d "$ORIGINAL_BASE" ]; then
  oo.mode.base.set "$ORIGINAL_BASE" 2>/dev/null
fi
rm -rf "$TEST_DIR"

# ============================================================================
# T8: oo.mode with non-existent branch shows error
# ============================================================================
test.oo.t8() {
  oo.mode "nonexistent_branch_$$"
}
expect.error 1
test.case - "T8: oo.mode rejects non-existent branch" \
  test.oo.t8
expect 1 "*" "oo.mode rejects non-existent branch"

# ============================================================================
# oo mode: symlink switch is sufficient — PATH contains ~/oosh which follows
# the symlink automatically. No config save needed.
# ============================================================================

# --- T-MODE-PATH-1: oo mode updates OOSH_DIR export ---
test.case - "T-MODE-PATH-1: oo.mode sets OOSH_DIR" \
  echo "checking OOSH_DIR after mode"
if [ -n "$OOSH_DIR" ]; then
  expect.pass "OOSH_DIR is set: $OOSH_DIR"
else
  expect.fail "OOSH_DIR should be set after oo.mode"
fi

# --- T-MODE-PATH-2: ~/oosh is a symlink (not hardcoded dir on PATH) ---
test.case - "T-MODE-PATH-2: ~/oosh is a symlink" \
  echo "checking symlink"
if [ -L "$HOME/oosh" ]; then
  expect.pass "~/oosh is a symlink → $(readlink "$HOME/oosh")"
else
  expect.fail "~/oosh should be a symlink, not a real directory"
fi

# --- T-MODE-PATH-3: oo mode updates OOSH_MODE ---
OO_SRC="$OOSH_DIR/oo"
OO_MODE_BODY=$(sed -n '/^oo\.mode()/,/^}/p' "$OO_SRC")
test.case - "T-MODE-PATH-3: oo.mode exports OOSH_MODE" \
  echo "checking OOSH_MODE export"
if echo "$OO_MODE_BODY" | grep -q 'OOSH_MODE'; then
  expect.pass "oo.mode sets OOSH_MODE"
else
  expect.fail "oo.mode should export OOSH_MODE"
fi

# ============================================================================
# Cleanup
# ============================================================================
# Restore original base dir
ORIGINAL_BASE="/Users/Shared/Workspaces/AI/Claude/components/OOSH"
if [ -d "$ORIGINAL_BASE" ]; then
  oo.mode.base.set "$ORIGINAL_BASE"
fi
rm -rf "$TEST_DIR"
