#!/usr/bin/env bash
# Tests for scrumMaster PDCA state machine implementation
# Tests actual scrumMaster commands and PDCA cycle behavior

#export PS4='\e[90m+${LINENO} in ${#BASH_SOURCE[@]}>${FUNCNAME[0]}:${BASH_SOURCE[@]##*/} \e[0m'
#set -x

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

source this
source test.suite
source state
source scrumMaster

log.level $level

# Test machine name for isolation
TEST_PDCA="PDCA_SCRUMTEST_$$"

# Save existing PDCA machine (if any) so we can restore it after tests
_PDCA_BACKUP=""
_PDCA_ENV_BACKUP=""
if [ -f "$CONFIG_PATH/stateMachines/PDCA.states.env" ]; then
  _PDCA_BACKUP=$(cat "$CONFIG_PATH/stateMachines/PDCA.states.env")
fi
if [ -f "$CONFIG_PATH/stateMachines/PDCA.pdca.env" ]; then
  _PDCA_ENV_BACKUP=$(cat "$CONFIG_PATH/stateMachines/PDCA.pdca.env")
fi

# Cleanup function — removes test artifacts and real PDCA (restored at end)
cleanupPdca() {
  rm -f "$CONFIG_PATH/stateMachines/${TEST_PDCA}.states.env" 2>/dev/null
  rm -f "$CONFIG_PATH/stateMachines/${TEST_PDCA}.pdca.env" 2>/dev/null
  rm -f "$CONFIG_PATH/stateMachines/PDCA.states.env" 2>/dev/null
  rm -f "$CONFIG_PATH/stateMachines/PDCA.pdca.env" 2>/dev/null
}

# Restore PDCA machine from backup
restorePdca() {
  if [ -n "$_PDCA_BACKUP" ]; then
    echo "$_PDCA_BACKUP" > "$CONFIG_PATH/stateMachines/PDCA.states.env"
  fi
  if [ -n "$_PDCA_ENV_BACKUP" ]; then
    echo "$_PDCA_ENV_BACKUP" > "$CONFIG_PATH/stateMachines/PDCA.pdca.env"
  fi
}

# Cleanup before tests
cleanupPdca

# Ensure stateMachines directory exists
mkdir -p "$CONFIG_PATH/stateMachines" 2>/dev/null

# Check if PDCA prerequisites are available
PDCA_AVAILABLE=0
if ./scrumMaster pdca.start __PDCA_PREREQ_TEST 0 >/dev/null 2>&1; then
  if state machine.exists __PDCA_PREREQ_TEST 2>/dev/null; then
    PDCA_AVAILABLE=1
  fi
  rm -f "$CONFIG_PATH/stateMachines/__PDCA_PREREQ_TEST"*.env 2>/dev/null
fi

# ============================================================================
# T1: Test pdca.start creates machine
# ============================================================================
test.case - "T1: pdca.start creates PDCA machine" \
  ./scrumMaster pdca.start PDCA 0

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T1 skipped (PDCA prerequisites not met)"
else
  if state machine.exists PDCA 2>/dev/null; then
    create.result 0 "PLANNING"
  else
    create.result 1 "Machine not created"
  fi
  expect 0 "PLANNING" "scrumMaster pdca.start creates machine"
fi

# ============================================================================
# T2: Test pdca.state shows current state
# ============================================================================
test.case - "T2: pdca.state shows PLANNING" \
  ./scrumMaster pdca.state PDCA

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T2 skipped (PDCA prerequisites not met)"
else
  # Current state should be planning after start
  CURRENT=$(./scrumMaster pdca.state PDCA 2>/dev/null | tail -1)
  if [ "$CURRENT" = "PLANNING" ]; then
    create.result 0 "PLANNING"
  else
    create.result 1 "Got $CURRENT instead of PLANNING"
  fi
  expect 0 "PLANNING" "pdca.state returns correct state"
fi

# ============================================================================
# T3: Test pdca.next advances state
# ============================================================================
test.case - "T3: pdca.next advances from PLANNING to DOING" \
  ./scrumMaster pdca.next PDCA

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T3 skipped (PDCA prerequisites not met)"
else
  # Note: test.case already called pdca.next once, so we're now at DOING
  CURRENT=$(./scrumMaster pdca.state PDCA 2>/dev/null | grep -E "^[A-Z_]+$" | tail -1)
  if [ "$CURRENT" = "DOING" ]; then
    create.result 0 "DOING"
  else
    create.result 1 "Got $CURRENT instead of DOING"
  fi
  expect 0 "DOING" "pdca.next advances state correctly"
fi

# ============================================================================
# T4: Test pdca.reset clears machine
# ============================================================================
test.case - "T4: pdca.reset clears machine" \
  ./scrumMaster pdca.reset PDCA

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T4 skipped (PDCA prerequisites not met)"
else
  ./scrumMaster pdca.reset PDCA >/dev/null 2>&1
  if ! state machine.exists PDCA 2>/dev/null; then
    create.result 0 "RESET"
  else
    create.result 1 "Machine still exists"
  fi
  expect 0 "RESET" "pdca.reset removes machine"
fi

# ============================================================================
# T5: Test pdca.run happy path (0 errors) -> FINISHED
# ============================================================================
cleanupPdca
test.case - "T5: pdca.run with 0 errors -> CYCLE_COMPLETE" \
  ./scrumMaster pdca.run PDCA 0

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T5 skipped (PDCA prerequisites not met)"
else
  # Check the final state after run (test.case already ran it)
  FINAL=$(./scrumMaster pdca.state PDCA 2>/dev/null | grep -E "^[A-Z_]+$" | tail -1)
  if [ "$FINAL" = "CYCLE_COMPLETE" ]; then
    create.result 0 "CYCLE_COMPLETE"
  else
    create.result 1 "Got $FINAL instead of CYCLE_COMPLETE"
  fi
  expect 0 "CYCLE_COMPLETE" "pdca.run with 0 errors reaches cycle.complete"
fi

# ============================================================================
# T6: Test pdca.run with 2 errors (C->A loops)
# ============================================================================
cleanupPdca
test.case - "T6: pdca.run with 2 errors -> CYCLE_COMPLETE after C->A loops" \
  ./scrumMaster pdca.run PDCA 2

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T6 skipped (PDCA prerequisites not met)"
else
  FINAL=$(./scrumMaster pdca.state PDCA 2>/dev/null | grep -E "^[A-Z_]+$" | tail -1)
  if [ "$FINAL" = "CYCLE_COMPLETE" ]; then
    create.result 0 "CYCLE_COMPLETE"
  else
    create.result 1 "Got $FINAL instead of CYCLE_COMPLETE"
  fi
  expect 0 "CYCLE_COMPLETE" "pdca.run with errors loops C->A and reaches cycle.complete"
fi

# ============================================================================
# T7: Test max iterations guard (too many errors)
# ============================================================================
cleanupPdca
test.case - "T7: pdca.run with 10 errors (max 5 iterations) -> ERROR_MAX_ITERATIONS" \
  ./scrumMaster pdca.run PDCA 10

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T7 skipped (PDCA prerequisites not met)"
else
  FINAL=$(./scrumMaster pdca.state PDCA 2>/dev/null | grep -E "^[A-Z_]+$" | tail -1)
  if [ "$FINAL" = "ERROR_MAX_ITERATIONS" ]; then
    create.result 0 "ERROR_MAX_ITERATIONS"
  else
    create.result 1 "Got $FINAL instead of ERROR_MAX_ITERATIONS"
  fi
  expect 0 "ERROR_MAX_ITERATIONS" "pdca.run stops at max iterations"
fi

# ============================================================================
# T8: Test pdca.errors shows/sets error count
# ============================================================================
cleanupPdca
if [ "$PDCA_AVAILABLE" -eq 1 ]; then
  ./scrumMaster pdca.start PDCA 5 >/dev/null 2>&1
fi

test.case - "T8: pdca.errors shows error count" \
  ./scrumMaster pdca.errors PDCA

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T8 skipped (PDCA prerequisites not met)"
else
  # Source the config to check the variable
  source $CONFIG_PATH/stateMachines/PDCA.pdca.env 2>/dev/null
  if [ "$PDCA_ERROR_COUNT" = "5" ]; then
    create.result 0 "5"
  else
    create.result 1 "Got $PDCA_ERROR_COUNT instead of 5"
  fi
  expect 0 "5" "pdca.errors correctly tracks error count"
fi

# ============================================================================
# T9: Test iteration counter increments during C->A loops
# ============================================================================
cleanupPdca
if [ "$PDCA_AVAILABLE" -eq 1 ]; then
  ./scrumMaster pdca.run PDCA 3 >/dev/null 2>&1
fi

test.case - "T9: Iteration counter tracks C->A loops" \
  source $CONFIG_PATH/stateMachines/PDCA.pdca.env 2>/dev/null

if [ "$PDCA_AVAILABLE" -eq 0 ]; then
  expect.pass "T9 skipped (PDCA prerequisites not met)"
else
  source $CONFIG_PATH/stateMachines/PDCA.pdca.env 2>/dev/null
  # With 3 errors, should have 3 iterations (fixing one per iteration)
  if [ "$PDCA_ITERATION" -ge 3 ]; then
    create.result 0 "$PDCA_ITERATION iterations"
  else
    create.result 1 "Only $PDCA_ITERATION iterations, expected >= 3"
  fi
  expect 0 "$PDCA_ITERATION iterations" "Iteration counter tracks correctly"
fi

# ============================================================================
# Cleanup — restore saved PDCA machine
# ============================================================================
cleanupPdca
restorePdca

# ============================================================================
# Completion function tests
# ============================================================================

test.case $level "scrumMaster.parameter.completion.machineName exists" \
  type -t scrumMaster.parameter.completion.machineName
if type -t scrumMaster.parameter.completion.machineName &>/dev/null; then
  expect.pass "scrumMaster.parameter.completion.machineName function exists"
else
  expect.fail "scrumMaster.parameter.completion.machineName should exist"
fi

test.case $level "scrumMaster.parameter.completion.session exists" \
  type -t scrumMaster.parameter.completion.session
if type -t scrumMaster.parameter.completion.session &>/dev/null; then
  expect.pass "scrumMaster.parameter.completion.session function exists"
else
  expect.fail "scrumMaster.parameter.completion.session should exist"
fi

test.case $level "scrumMaster.pane.measure.completion.agentName exists" \
  type -t scrumMaster.pane.measure.completion.agentName
if type -t scrumMaster.pane.measure.completion.agentName &>/dev/null; then
  expect.pass "scrumMaster.pane.measure.completion.agentName function exists"
else
  expect.fail "scrumMaster.pane.measure.completion.agentName should exist"
fi

test.case $level "scrumMaster.team.measure.completion.session exists" \
  type -t scrumMaster.team.measure.completion.session
if type -t scrumMaster.team.measure.completion.session &>/dev/null; then
  expect.pass "scrumMaster.team.measure.completion.session function exists"
else
  expect.fail "scrumMaster.team.measure.completion.session should exist"
fi

test.suite.save.results

