#!/usr/bin/env bash
# Comprehensive tests for the config script
# Tests: init, file, save, list, get, set, add, update, clean, delete, discover

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

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

source this
source test.suite
source config

log.level $level

# Save original config state
ORIGINAL_CONFIG=$CONFIG
ORIGINAL_CONFIG_PATH=$CONFIG_PATH
ORIGINAL_CONFIG_FILE=$CONFIG_FILE

# Test directory for isolation
TEST_CONFIG_PATH="${TMPDIR:-/tmp}/test.config.$$"
mkdir -p "$TEST_CONFIG_PATH"

# Cleanup function
cleanup_test_config() {
  rm -rf "$TEST_CONFIG_PATH" 2>/dev/null
  export CONFIG=$ORIGINAL_CONFIG
  export CONFIG_PATH=$ORIGINAL_CONFIG_PATH
  export CONFIG_FILE=$ORIGINAL_CONFIG_FILE
}

# Setup test environment
setup_test_config() {
  export CONFIG_PATH="$TEST_CONFIG_PATH"
  export CONFIG_FILE="test.env"
  export CONFIG="$CONFIG_PATH/$CONFIG_FILE"
  touch "$CONFIG"
}

# ============================================================================
# T1: Test config.init sets up CONFIG variables
# ============================================================================
test.case - "T1: config.init creates CONFIG_PATH and sets CONFIG" \
  config.init

if [ -d "$CONFIG_PATH" ] && [ -n "$CONFIG" ]; then
  create.result 0 "CONFIG initialized"
else
  create.result 1 "CONFIG_PATH=$CONFIG_PATH CONFIG=$CONFIG"
fi
expect 0 "CONFIG initialized" "config.init sets up environment"

# Reset to test environment
setup_test_config

# ============================================================================
# T2: Test config.file without args returns current file
# ============================================================================
test.case - "T2: config.file returns current file" \
  echo "checking"

CURRENT_FILE=$(config.file)
if [ "$CURRENT_FILE" = "$CONFIG_FILE" ]; then
  create.result 0 "file returned"
else
  create.result 1 "got: $CURRENT_FILE expected: $CONFIG_FILE"
fi
expect 0 "file returned" "config.file returns current file"

# ============================================================================
# T3: Test config.file sets new file
# ============================================================================
test.case - "T3: config.file sets new file" \
  config.file newtest.env

if [ "$CONFIG_FILE" = "newtest.env" ]; then
  create.result 0 "file changed"
else
  create.result 1 "CONFIG_FILE=$CONFIG_FILE"
fi
expect 0 "file changed" "config.file sets new file"

# Reset
setup_test_config

# ============================================================================
# T4: Test config.file.check with existing file
# ============================================================================
touch "$CONFIG_PATH/exists.env"
test.case - "T4: config.file.check finds existing file" \
  config.file.check exists

if [ "$RETURN_VALUE" -eq 0 ]; then
  create.result 0 "found exists.env"
else
  create.result 1 "not found"
fi
expect 0 "found exists.env" "config.file.check finds existing file"

# ============================================================================
# T5: Test config.save creates config file
# ============================================================================
export TEST_CONFIG_VAR1="value1"
export TEST_CONFIG_VAR2="value2"
setup_test_config

test.case - "T5: config.save creates file" \
  config.save testcfg TEST_CONFIG

if [ -f "$CONFIG_PATH/testcfg.env" ]; then
  create.result 0 "testcfg.env created"
else
  create.result 1 "testcfg.env missing"
fi
expect 0 "testcfg.env created" "config.save creates file"

# ============================================================================
# T6: Test config.save captures prefixed variables
# ============================================================================
test.case - "T6: config.save captures prefixed variables" \
  echo "checking saved content"

SAVED_CONTENT=$(cat "$CONFIG_PATH/testcfg.env" 2>/dev/null)
if echo "$SAVED_CONTENT" | grep -q "TEST_CONFIG_VAR1" && \
   echo "$SAVED_CONTENT" | grep -q "TEST_CONFIG_VAR2"; then
  create.result 0 "variables saved"
else
  create.result 1 "variables missing"
fi
expect 0 "variables saved" "config.save captures prefixed variables"

# ============================================================================
# T7: Test config.list shows config content
# ============================================================================
setup_test_config
echo 'export TEST_LIST_VAR="listvalue"' > "$CONFIG_PATH/listtest.env"

test.case - "T7: config.list shows content" \
  echo "checking list"

config.file listtest.env
LIST_OUTPUT=$(config.list listtest 2>/dev/null)
if echo "$LIST_OUTPUT" | grep -q "TEST_LIST_VAR"; then
  create.result 0 "list shows content"
else
  create.result 1 "list output: $LIST_OUTPUT"
fi
expect 0 "list shows content" "config.list shows variables"

# ============================================================================
# T8: Test config.set adds new variable
# ============================================================================
setup_test_config
echo '# empty config' > "$CONFIG"

test.case - "T8: config.set adds new variable" \
  config.set NEW_VAR "newvalue"

if grep -q 'NEW_VAR="newvalue"' "$CONFIG"; then
  create.result 0 "NEW_VAR added"
else
  create.result 1 "NEW_VAR missing in $CONFIG"
fi
expect 0 "NEW_VAR added" "config.set adds new variable"

# ============================================================================
# T9: Test config.set updates existing variable
# ============================================================================
setup_test_config
echo 'export EXISTING_VAR="oldvalue"' > "$CONFIG"

test.case - "T9: config.set updates existing variable" \
  config.set EXISTING_VAR "updatedvalue"

if grep -q 'EXISTING_VAR="updatedvalue"' "$CONFIG"; then
  create.result 0 "EXISTING_VAR updated"
else
  create.result 1 "EXISTING_VAR not updated"
fi
expect 0 "EXISTING_VAR updated" "config.set updates existing variable"

# ============================================================================
# T10: Test config.get retrieves variable value
# ============================================================================
export GET_TEST_VAR="getvalue"
setup_test_config
echo 'export GET_TEST_VAR="getvalue"' > "$CONFIG"

test.case - "T10: config.get retrieves variable value" \
  echo "checking get"

GET_RESULT=$(config.get GET_TEST_VAR 2>/dev/null)
if [ "$GET_RESULT" = "getvalue" ]; then
  create.result 0 "got value"
else
  create.result 1 "got: $GET_RESULT"
fi
expect 0 "got value" "config.get retrieves correct value"

# ============================================================================
# T11: Test config.add appends source line
# ============================================================================
setup_test_config
echo '# user config' > "$CONFIG"
touch "$CONFIG_PATH/addon.env"

test.case - "T11: config.add appends source line" \
  config.add addon

# config.add calls config.clean which sorts the file
if grep -q 'source $CONFIG_PATH/addon.env' "$CONFIG"; then
  create.result 0 "source added"
else
  create.result 1 "source missing in: $(cat $CONFIG)"
fi
expect 0 "source added" "config.add appends source line"

# ============================================================================
# T12: Test config.clean removes duplicates
# ============================================================================
setup_test_config
cat > "$CONFIG" << 'EOF'
export DUP_VAR="value"
export DUP_VAR="value"
export UNIQUE_VAR="unique"
export DUP_VAR="value"
EOF

test.case - "T12: config.clean removes duplicates" \
  config.clean

LINE_COUNT=$(grep -c "DUP_VAR" "$CONFIG" 2>/dev/null || echo "0")
if [ "$LINE_COUNT" -eq 1 ]; then
  create.result 0 "duplicates removed"
else
  create.result 1 "duplicates remain: $LINE_COUNT"
fi
expect 0 "duplicates removed" "config.clean removes duplicates"

# ============================================================================
# T13: Test config.delete removes config file
# ============================================================================
setup_test_config
touch "$CONFIG_PATH/todelete.env"
config.file todelete.env

test.case - "T13: config.delete removes file" \
  config.delete todelete

if [ ! -f "$CONFIG_PATH/todelete.env" ]; then
  create.result 0 "file deleted"
else
  create.result 1 "file still exists"
fi
expect 0 "file deleted" "config.delete removes file"

# ============================================================================
# T14: Test config.discover lists config files
# ============================================================================
setup_test_config
touch "$CONFIG_PATH/discover1.env"
touch "$CONFIG_PATH/discover2.env"

test.case - "T14: config.discover lists files" \
  echo "checking discover"

DISCOVER_OUTPUT=$(config.discover 2>/dev/null)
if echo "$DISCOVER_OUTPUT" | grep -q "discover1.env"; then
  create.result 0 "discover1 found"
else
  create.result 1 "output: $DISCOVER_OUTPUT"
fi
expect 0 "discover1 found" "config.discover lists files"

# ============================================================================
# T15: Test config.string.quote handles special chars
# ============================================================================
test.case - "T15: config.string.quote returns quoted string" \
  echo "checking quote"

QUOTED=$(config.string.quote "hello world")
if [ -n "$QUOTED" ]; then
  create.result 0 "string quoted"
else
  create.result 1 "quote failed"
fi
expect 0 "string quoted" "config.string.quote returns quoted string"

# ============================================================================
# T16: Test config.file reset restores defaults
# ============================================================================
config.file someother.env

test.case - "T16: config.file reset restores user.env" \
  config.file reset

if [ "$CONFIG_FILE" = "user.env" ]; then
  create.result 0 "file reset"
else
  create.result 1 "CONFIG_FILE=$CONFIG_FILE"
fi
expect 0 "file reset" "config.file reset restores user.env"

# Reset for remaining tests
setup_test_config

# ============================================================================
# T17: Test config.update saves and adds
# ============================================================================
export TEST_UPDATE_VAR="updateval"
setup_test_config
echo '# main config' > "$CONFIG"

test.case - "T17: config.update saves and adds" \
  config.update updatetest TEST_UPDATE

# Check file was created and source line added
if [ -f "$CONFIG_PATH/updatetest.env" ] && grep -q 'source $CONFIG_PATH/updatetest.env' "$CONFIG"; then
  create.result 0 "update complete"
else
  create.result 1 "file exists: $(test -f $CONFIG_PATH/updatetest.env && echo yes || echo no) source: $(grep updatetest $CONFIG)"
fi
expect 0 "update complete" "config.update saves and adds"

# ============================================================================
# T18: Test config.get with missing variable
# ============================================================================
unset NONEXISTENT_VAR

test.case - "T18: config.get returns empty for missing var" \
  echo "checking missing"

GET_MISSING=$(config.get NONEXISTENT_VAR 2>/dev/null)
if [ -z "$GET_MISSING" ]; then
  create.result 0 "empty for missing"
else
  create.result 1 "returned: $GET_MISSING"
fi
expect 0 "empty for missing" "config.get returns empty for missing var"

# ============================================================================
# T19: Test config.set with empty value
# ============================================================================
setup_test_config
echo 'export EMPTY_TEST="hasvalue"' > "$CONFIG"

test.case - "T19: config.set allows empty value" \
  config.set EMPTY_TEST ""

if grep -q 'EMPTY_TEST=""' "$CONFIG"; then
  create.result 0 "set to empty"
else
  create.result 1 "config content: $(cat $CONFIG)"
fi
expect 0 "set to empty" "config.set allows empty value"

# ============================================================================
# T20: Test config.v returns version
# ============================================================================
test.case - "T20: config.v returns version" \
  echo "checking version"

VERSION_OUTPUT=$(config.v 2>/dev/null)
if echo "$VERSION_OUTPUT" | grep -q "version"; then
  create.result 0 "version returned"
else
  create.result 1 "output: $VERSION_OUTPUT"
fi
expect 0 "version returned" "config.v returns version string"

# ============================================================================
# Cleanup
# ============================================================================
cleanup_test_config

# Unset test variables
unset TEST_CONFIG_VAR1
unset TEST_CONFIG_VAR2
unset TEST_UPDATE_VAR

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