#!/usr/bin/env bash
# Tests for otest: run, completion, newTest, mapName, testExists

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

source this
source test.suite
source otest

log.level $level

# ============================================================================
# Save original state
# ============================================================================
# Auto-discover OTEST_DIR if not already set
if [ -z "$OTEST_DIR" ]; then
  private.ensureDir 2>/dev/null
fi
ORIGINAL_OTEST_DIR=$OTEST_DIR
ORIGINAL_DIR=$(pwd)
ORIGINAL_PATH=$PATH

# Test directory for isolation
TEST_TMP="/tmp/test.otest.$$"
mkdir -p "$TEST_TMP"

# Cleanup function
cleanup_test() {
  rm -rf "$TEST_TMP" 2>/dev/null
  export OTEST_DIR=$ORIGINAL_OTEST_DIR
  export PATH=$ORIGINAL_PATH
  cd "$ORIGINAL_DIR"
}

# ============================================================================
# Build fake EAMD.ucp tree for isolation
# ============================================================================
setup_fakeEamd() {
  local fakeEamd="$TEST_TMP/EAMD.ucp"
  local fakeSuite="$fakeEamd/Components/me/hannesnortje/TestSuite/2.0.0"
  local fakeComp="$fakeEamd/Components/com/test/SampleWidget/1.0.0/test/2.0.0"

  mkdir -p "$fakeSuite"
  mkdir -p "$fakeComp/golden"

  # Symlink venv from real TestSuite so Python works
  if [ -d "$ORIGINAL_OTEST_DIR/venv" ]; then
    ln -s "$ORIGINAL_OTEST_DIR/venv" "$fakeSuite/venv"
  fi

  # Copy run_tests.py and utils from real TestSuite
  if [ -f "$ORIGINAL_OTEST_DIR/run_tests.py" ]; then
    cp "$ORIGINAL_OTEST_DIR/run_tests.py" "$fakeSuite/"
  fi
  if [ -d "$ORIGINAL_OTEST_DIR/utils" ]; then
    cp -r "$ORIGINAL_OTEST_DIR/utils" "$fakeSuite/"
  fi
  if [ -f "$ORIGINAL_OTEST_DIR/requirements.txt" ]; then
    cp "$ORIGINAL_OTEST_DIR/requirements.txt" "$fakeSuite/"
  fi

  # Create a sample pre-existing test
  cat > "$fakeComp/otest.yaml" << 'EOF'
description: "Sample Widget test"

url: "https://localhost:8443/EAMD.ucp/Components/com/test/SampleWidget/1.0.0"

xpaths: {}

settings:
  wait_time: 10
EOF

  cat > "$fakeComp/SampleWidget.py" << 'PYEOF'
import os
import sys
import argparse

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

def perform_sample_widget_test(headless=False):
    print("SampleWidget test stub")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Run SampleWidget test')
    parser.add_argument('--headless', action='store_true')
    args, _extra = parser.parse_known_args()
    perform_sample_widget_test(args.headless)
PYEOF

  touch "$fakeComp/golden/.gitkeep"

  # Point OTEST_DIR to fake TestSuite
  export OTEST_DIR="$fakeSuite"
}

setup_fakeEamd

# Check if Python venv is available for testExists/completion tests
VENV_AVAILABLE=0
if [ -d "$OTEST_DIR/venv" ] && [ -f "$OTEST_DIR/venv/bin/python" ]; then
  VENV_AVAILABLE=1
fi

# ============================================================================
# T1: private.mapName — basic camelCase to snake_case
# ============================================================================
test.case - "T1: mapName converts camelCase to snake_case" \
  echo "checking"

RESULT=$(private.mapName "canvasGauges")
if [ "$RESULT" = "canvas_gauges" ]; then
  create.result 0 "canvas_gauges"
else
  create.result 1 "got: $RESULT"
fi
expect 0 "canvas_gauges" "mapName: canvasGauges -> canvas_gauges"

# ============================================================================
# T2: private.mapName — already snake_case passthrough
# ============================================================================
test.case - "T2: mapName passes through snake_case unchanged" \
  echo "checking"

RESULT=$(private.mapName "already_snake")
if [ "$RESULT" = "already_snake" ]; then
  create.result 0 "already_snake"
else
  create.result 1 "got: $RESULT"
fi
expect 0 "already_snake" "mapName: already_snake unchanged"

# ============================================================================
# T3: private.mapName — single word
# ============================================================================
test.case - "T3: mapName single word unchanged" \
  echo "checking"

RESULT=$(private.mapName "simple")
if [ "$RESULT" = "simple" ]; then
  create.result 0 "simple"
else
  create.result 1 "got: $RESULT"
fi
expect 0 "simple" "mapName: simple unchanged"

# ============================================================================
# T4: private.mapName — multi-hump camelCase
# ============================================================================
test.case - "T4: mapName multi-hump camelCase" \
  echo "checking"

RESULT=$(private.mapName "dialogManagerOnline")
if [ "$RESULT" = "dialog_manager_online" ]; then
  create.result 0 "dialog_manager_online"
else
  create.result 1 "got: $RESULT"
fi
expect 0 "dialog_manager_online" "mapName: dialogManagerOnline -> dialog_manager_online"

# ============================================================================
# T5: private.testExists — finds pre-existing sample test
# ============================================================================
test.case - "T5: testExists finds sample_widget" \
  private.testExists "sample_widget"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "testExists skipped (venv not available)"
elif [ "$RETURN_VALUE" -eq 0 ]; then
  create.result 0 "found"
  expect 0 "found" "testExists finds sample_widget"
else
  create.result 1 "not found"
  expect 0 "found" "testExists finds sample_widget"
fi

# ============================================================================
# T6: private.testExists — rejects non-existent test
# ============================================================================
test.case - "T6: testExists rejects nonexistent_test" \
  echo "checking"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "testExists skipped (venv not available)"
else
  private.testExists "nonexistent_test"
  local_rv=$?
  if [ "$local_rv" -ne 0 ]; then
    create.result 0 "rejected"
  else
    create.result 1 "should not have found it"
  fi
  expect 0 "rejected" "testExists rejects nonexistent_test"
fi

# ============================================================================
# T7: otest.run — rejects empty test name
# ============================================================================
test.case - "T7: otest.run rejects empty test name" \
  echo "checking"

otest.run 2>/dev/null
local_rv=$?
if [ "$local_rv" -ne 0 ]; then
  create.result 0 "rejected"
else
  create.result 1 "should have rejected"
fi
expect 0 "rejected" "otest.run rejects empty test name"

# ============================================================================
# T8: otest.run.completion.testName — returns camelCase names
# ============================================================================
test.case - "T8: run.completion.testName returns camelCase names" \
  echo "checking"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "run.completion.testName skipped (venv not available)"
else
  COMPLETION_OUTPUT=$(otest.run.completion.testName 2>/dev/null)
  if echo "$COMPLETION_OUTPUT" | grep -q "sampleWidget" && \
     echo "$COMPLETION_OUTPUT" | grep -q "all"; then
    create.result 0 "camelCase found"
  else
    create.result 1 "output: $COMPLETION_OUTPUT"
  fi
  expect 0 "camelCase found" "run.completion.testName returns camelCase names with 'all'"
fi

# ============================================================================
# T9: otest.parameter.completion.headless — returns flag names
# ============================================================================
test.case - "T9: parameter.completion.headless returns flag names" \
  echo "checking"

FLAGS_OUTPUT=$(otest.parameter.completion.headless)
if echo "$FLAGS_OUTPUT" | grep -q "headless" && \
   echo "$FLAGS_OUTPUT" | grep -q "updateGolden" && \
   echo "$FLAGS_OUTPUT" | grep -q "keepScreenshots"; then
  create.result 0 "flags found"
else
  create.result 1 "output: $FLAGS_OUTPUT"
fi
expect 0 "flags found" "parameter.completion.headless returns headless, updateGolden, keepScreenshots"

# ============================================================================
# T10: otest.newTest — scaffolds files from component version dir
# ============================================================================
NEWCOMP_DIR="$TEST_TMP/EAMD.ucp/Components/com/test/NewComp/1.0.0"
mkdir -p "$NEWCOMP_DIR"

test.case - "T10: newTest scaffolds test files" \
  echo "checking"

cd "$NEWCOMP_DIR"
otest.newTest "FreshTest" "https://localhost:8443/EAMD.ucp/Components/com/test/NewComp/1.0.0" 2>/dev/null
local_rv=$?
cd "$ORIGINAL_DIR"

if [ "$local_rv" -eq 0 ] && \
   [ -f "$NEWCOMP_DIR/test/2.0.0/FreshTest.py" ] && \
   [ -f "$NEWCOMP_DIR/test/2.0.0/otest.yaml" ] && \
   [ -d "$NEWCOMP_DIR/test/2.0.0/golden" ]; then
  create.result 0 "scaffolded"
else
  create.result 1 "rv=$local_rv py=$(test -f "$NEWCOMP_DIR/test/2.0.0/FreshTest.py" && echo y || echo n) yaml=$(test -f "$NEWCOMP_DIR/test/2.0.0/otest.yaml" && echo y || echo n)"
fi
expect 0 "scaffolded" "newTest creates .py, otest.yaml, golden/"

# ============================================================================
# T11: otest.newTest — generated .py has correct function name
# ============================================================================
test.case - "T11: newTest .py has correct function name" \
  echo "checking"

if grep -q "def perform_fresh_test_test" "$NEWCOMP_DIR/test/2.0.0/FreshTest.py"; then
  create.result 0 "function found"
else
  create.result 1 "function not found"
fi
expect 0 "function found" "newTest .py has perform_fresh_test_test()"

# ============================================================================
# T12: otest.newTest — generated otest.yaml has correct URL
# ============================================================================
test.case - "T12: newTest otest.yaml has correct URL" \
  echo "checking"

if grep -q "https://localhost:8443/EAMD.ucp/Components/com/test/NewComp/1.0.0" "$NEWCOMP_DIR/test/2.0.0/otest.yaml"; then
  create.result 0 "url found"
else
  create.result 1 "url missing"
fi
expect 0 "url found" "newTest otest.yaml has correct URL"

# ============================================================================
# T13: otest.newTest — rejects non-PascalCase name
# ============================================================================
test.case - "T13: newTest rejects non-PascalCase name" \
  echo "checking"

cd "$NEWCOMP_DIR"
otest.newTest "badname" 2>/dev/null
local_rv=$?
cd "$ORIGINAL_DIR"

if [ "$local_rv" -ne 0 ]; then
  create.result 0 "rejected"
else
  create.result 1 "should have rejected"
fi
expect 0 "rejected" "newTest rejects lowercase name"

# ============================================================================
# T14: otest.newTest — rejects duplicate test name
# ============================================================================
test.case - "T14: newTest rejects duplicate test" \
  echo "checking"

cd "$NEWCOMP_DIR"
otest.newTest "FreshTest" "https://localhost:8443/test" 2>/dev/null
local_rv=$?
cd "$ORIGINAL_DIR"

if [ "$local_rv" -ne 0 ]; then
  create.result 0 "rejected"
else
  create.result 1 "should have rejected duplicate"
fi
expect 0 "rejected" "newTest rejects duplicate test name"

# ============================================================================
# T15: private.testExists — finds newly scaffolded test
# ============================================================================
test.case - "T15: testExists finds fresh_test after scaffold" \
  private.testExists "fresh_test"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "testExists skipped (venv not available)"
elif [ "$RETURN_VALUE" -eq 0 ]; then
  create.result 0 "found"
  expect 0 "found" "testExists finds fresh_test"
else
  create.result 1 "not found"
  expect 0 "found" "testExists finds fresh_test"
fi

# ============================================================================
# T16: otest.run.completion.testName — picks up scaffolded test dynamically
# ============================================================================
test.case - "T16: completion picks up scaffolded test dynamically" \
  echo "checking"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "completion skipped (venv not available)"
else
  COMPLETION_OUTPUT=$(otest.run.completion.testName 2>/dev/null)
  if echo "$COMPLETION_OUTPUT" | grep -q "freshTest"; then
    create.result 0 "found"
  else
    create.result 1 "freshTest not in completion: $COMPLETION_OUTPUT"
  fi
  expect 0 "found" "run.completion.testName dynamically includes freshTest"
fi

# ============================================================================
# T17: otest.newTest — derives URL from cwd when not given
# ============================================================================
AUTOURL_DIR="$TEST_TMP/EAMD.ucp/Components/com/test/AutoUrl/1.0.0"
mkdir -p "$AUTOURL_DIR"

test.case - "T17: newTest derives URL from cwd" \
  echo "checking"

cd "$AUTOURL_DIR"
otest.newTest "AutoUrlTest" 2>/dev/null
local_rv=$?
cd "$ORIGINAL_DIR"

if [ "$local_rv" -eq 0 ] && \
   grep -q "https://localhost:8443/EAMD.ucp/Components/com/test/AutoUrl/1.0.0" "$AUTOURL_DIR/test/2.0.0/otest.yaml"; then
  create.result 0 "url derived"
else
  create.result 1 "rv=$local_rv url=$(grep 'url:' "$AUTOURL_DIR/test/2.0.0/otest.yaml" 2>/dev/null)"
fi
expect 0 "url derived" "newTest derives URL from cwd"

# ============================================================================
# T18: otest.newTest — works from test/2.0.0 dir directly
# ============================================================================
TESTDIR_COMP="$TEST_TMP/EAMD.ucp/Components/com/test/DirTest/1.0.0/test/2.0.0"
mkdir -p "$TESTDIR_COMP"

test.case - "T18: newTest works from test/2.0.0 dir" \
  echo "checking"

cd "$TESTDIR_COMP"
otest.newTest "DirTest" "https://localhost:8443/test" 2>/dev/null
local_rv=$?
cd "$ORIGINAL_DIR"

if [ "$local_rv" -eq 0 ] && [ -f "$TESTDIR_COMP/DirTest.py" ]; then
  create.result 0 "created"
else
  create.result 1 "rv=$local_rv"
fi
expect 0 "created" "newTest works from test/2.0.0 dir"

# ============================================================================
# T19: private.testNames.camel — does not include snake_case names
# ============================================================================
test.case - "T19: testNames.camel outputs camelCase not snake_case" \
  echo "checking"

if [ "$VENV_AVAILABLE" -eq 0 ]; then
  expect.pass "testNames.camel skipped (venv not available)"
else
  CAMEL_OUTPUT=$(private.testNames.camel 2>/dev/null)
  if echo "$CAMEL_OUTPUT" | grep -q "sampleWidget" && \
     ! echo "$CAMEL_OUTPUT" | grep -q "sample_widget"; then
    create.result 0 "camelCase only"
  else
    create.result 1 "output: $CAMEL_OUTPUT"
  fi
  expect 0 "camelCase only" "testNames.camel outputs camelCase, not snake_case"
fi

# ============================================================================
# T20: webkit arg maps to --browser webkit in translation loop
# ============================================================================
test.case - "T20: webkit arg maps to --browser webkit" \
  echo "checking"

TRANSLATED=""
for arg in headless webkit keepScreenshots; do
  case "$arg" in
    headless)        TRANSLATED+="--headless " ;;
    updateGolden)    TRANSLATED+="--update-golden " ;;
    keepScreenshots) TRANSLATED+="--keep-screenshots " ;;
    webkit)          TRANSLATED+="--browser webkit " ;;
    *)               TRANSLATED+="$arg " ;;
  esac
done

if echo "$TRANSLATED" | grep -q "\-\-browser webkit"; then
  create.result 0 "translated"
else
  create.result 1 "got: $TRANSLATED"
fi
expect 0 "translated" "webkit maps to --browser webkit"

# ============================================================================
# T21: parameter completion includes webkit
# ============================================================================
test.case - "T21: parameter.completion includes webkit" \
  echo "checking"

FLAGS_OUTPUT=$(otest.parameter.completion.webkit)
if echo "$FLAGS_OUTPUT" | grep -q "webkit"; then
  create.result 0 "webkit found"
else
  create.result 1 "output: $FLAGS_OUTPUT"
fi
expect 0 "webkit found" "parameter.completion includes webkit"

### test.method

# ============================================================================
# Cleanup
# ============================================================================
cleanup_test

# ============================================================================
# Save results
# ============================================================================
test.suite.save.results
