#!/usr/bin/env bash
# Tests for update_existing_agent_file function
# Run: bash .specify/scripts/bash/tests/test-agent-update.sh

set -uo pipefail
# Note: not using -e so we can continue after failed assertions

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PASSED=0
FAILED=0

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

# Test fixtures directory
FIXTURES_DIR="$SCRIPT_DIR/fixtures/agent-update"
mkdir -p "$FIXTURES_DIR"

# Mock logging functions (silence in tests)
log_info() { :; }
log_error() { echo "ERROR: $1" >&2; }
log_warning() { :; }
log_success() { :; }

# Extract format_technology_stack function
eval "$(sed -n '/^format_technology_stack()/,/^}/p' "$SCRIPT_DIR/../update-agent-context.sh")"

# Extract update_existing_agent_file function - use more specific pattern
# The function ends with a single } on its own line before the next function
eval "$(awk '/^update_existing_agent_file\(\)/,/^}$/ {print; if (/^}$/) exit}' "$SCRIPT_DIR/../update-agent-context.sh")"

# Test helper: compare files
assert_file_eq() {
    local description="$1"
    local expected_file="$2"
    local actual_file="$3"

    if diff -q "$expected_file" "$actual_file" > /dev/null 2>&1; then
        echo -e "${GREEN}PASS${NC}: $description"
        ((PASSED++))
    else
        echo -e "${RED}FAIL${NC}: $description"
        echo "  Expected:"
        cat "$expected_file" | sed 's/^/    /'
        echo "  Actual:"
        cat "$actual_file" | sed 's/^/    /'
        echo "  Diff:"
        diff "$expected_file" "$actual_file" | sed 's/^/    /' || true
        ((FAILED++))
    fi
}

# Test helper: check file contains pattern
assert_contains() {
    local description="$1"
    local pattern="$2"
    local file="$3"

    if grep -q "$pattern" "$file" 2>/dev/null; then
        echo -e "${GREEN}PASS${NC}: $description"
        ((PASSED++))
    else
        echo -e "${RED}FAIL${NC}: $description"
        echo "  Pattern not found: '$pattern'"
        echo "  File contents:"
        cat "$file" | sed 's/^/    /'
        ((FAILED++))
    fi
}

# Test helper: check file does NOT contain pattern
assert_not_contains() {
    local description="$1"
    local pattern="$2"
    local file="$3"

    if ! grep -q "$pattern" "$file" 2>/dev/null; then
        echo -e "${GREEN}PASS${NC}: $description"
        ((PASSED++))
    else
        echo -e "${RED}FAIL${NC}: $description"
        echo "  Pattern found but should not be: '$pattern'"
        echo "  File contents:"
        cat "$file" | sed 's/^/    /'
        ((FAILED++))
    fi
}

# Test helper: count occurrences
assert_count() {
    local description="$1"
    local expected="$2"
    local pattern="$3"
    local file="$4"

    local actual
    actual=$(grep -c "$pattern" "$file" 2>/dev/null || echo "0")

    if [[ "$actual" == "$expected" ]]; then
        echo -e "${GREEN}PASS${NC}: $description"
        ((PASSED++))
    else
        echo -e "${RED}FAIL${NC}: $description"
        echo "  Expected count: $expected"
        echo "  Actual count: $actual"
        echo "  Pattern: '$pattern'"
        ((FAILED++))
    fi
}

# Setup test file
setup_test_file() {
    local content="$1"
    local test_file
    test_file=$(mktemp)
    echo -e "$content" > "$test_file"
    echo "$test_file"
}

# Cleanup
cleanup_test_file() {
    rm -f "$1"
}

echo "=== Agent File Update Tests ==="
echo ""

# --- Basic Functionality ---
echo "## Basic Functionality"

# Test: Normal update with both sections
NEW_LANG="Python 3.11"
NEW_FRAMEWORK="FastAPI"
NEW_DB=""
CURRENT_BRANCH="feature-auth"

test_file=$(setup_test_file "# Project

## Active Technologies
- JavaScript + React (main)

## Recent Changes
- old-feature: Added logging

## Other Section
Some content")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Adds new tech entry" "Python 3.11 + FastAPI (feature-auth)" "$test_file"
assert_contains "Adds new change entry" "feature-auth: Added Python 3.11 + FastAPI" "$test_file"
assert_contains "Preserves existing tech entry" "JavaScript + React (main)" "$test_file"
assert_contains "Preserves other sections" "## Other Section" "$test_file"

cleanup_test_file "$test_file"

# --- Missing Sections ---
echo ""
echo "## Missing Sections"

# Test: Missing Active Technologies section
NEW_LANG="Rust"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="add-rust"

test_file=$(setup_test_file "# Project

## Some Other Section
Content here

## Recent Changes
- old: stuff")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Creates Active Technologies section" "## Active Technologies" "$test_file"
assert_contains "Adds tech to new section" "Rust (add-rust)" "$test_file"

cleanup_test_file "$test_file"

# Test: Missing Recent Changes section
NEW_LANG="Go"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="add-go"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Creates Recent Changes section" "## Recent Changes" "$test_file"
assert_contains "Adds change to new section" "add-go: Added Go" "$test_file"

cleanup_test_file "$test_file"

# Test: Both sections missing
NEW_LANG="TypeScript"
NEW_FRAMEWORK="Express"
NEW_DB=""
CURRENT_BRANCH="add-ts"

test_file=$(setup_test_file "# Project

Just some content here.")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Creates Active Technologies when missing" "## Active Technologies" "$test_file"
assert_contains "Creates Recent Changes when missing" "## Recent Changes" "$test_file"
assert_contains "Adds tech entry" "TypeScript + Express (add-ts)" "$test_file"
assert_contains "Adds change entry" "add-ts: Added TypeScript + Express" "$test_file"

cleanup_test_file "$test_file"

# --- Timestamp Updates ---
echo ""
echo "## Timestamp Updates"

NEW_LANG=""
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="update-test"

test_file=$(setup_test_file "# Project

**Last updated**: 2023-06-01

## Active Technologies
- Python (main)")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Updates timestamp" "2024-01-15" "$test_file"
assert_not_contains "Old timestamp removed" "2023-06-01" "$test_file"

cleanup_test_file "$test_file"

# --- Idempotency ---
echo ""
echo "## Idempotency"

# Test: Don't add duplicate tech entries
NEW_LANG="Python"
NEW_FRAMEWORK="Django"
NEW_DB=""
CURRENT_BRANCH="feature-x"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python + Django (feature-x)

## Recent Changes
- feature-x: Added Python + Django")

update_existing_agent_file "$test_file" "2024-01-15"

# Check tech section specifically - should only have one tech entry line
assert_count "No duplicate tech entry in Active Technologies" "1" "^- Python + Django (feature-x)$" "$test_file"

cleanup_test_file "$test_file"

# --- Change Entry Limits ---
echo ""
echo "## Change Entry Limits (max 2 kept)"

NEW_LANG="Rust"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="new-feature"

test_file=$(setup_test_file "# Project

## Recent Changes
- old-1: First old change
- old-2: Second old change
- old-3: Third old change
- old-4: Fourth old change

## Other Section")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "New change added first" "new-feature: Added Rust" "$test_file"
assert_contains "Keeps first old change" "old-1: First old change" "$test_file"
assert_contains "Keeps second old change" "old-2: Second old change" "$test_file"
assert_not_contains "Removes third old change" "old-3:" "$test_file"
assert_not_contains "Removes fourth old change" "old-4:" "$test_file"

cleanup_test_file "$test_file"

# --- Database Entries ---
echo ""
echo "## Database Entries"

NEW_LANG=""
NEW_FRAMEWORK=""
NEW_DB="PostgreSQL"
CURRENT_BRANCH="add-db"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)

## Recent Changes
- old: stuff")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Adds database entry to tech section" "PostgreSQL (add-db)" "$test_file"
assert_contains "Adds database to change entry" "add-db: Added PostgreSQL" "$test_file"

cleanup_test_file "$test_file"

# Test: DB with N/A value not added
NEW_LANG=""
NEW_FRAMEWORK=""
NEW_DB="N/A"
CURRENT_BRANCH="no-db"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)")

update_existing_agent_file "$test_file" "2024-01-15"

assert_not_contains "N/A database not added" "N/A (no-db)" "$test_file"

cleanup_test_file "$test_file"

# --- Tech Entry Placement ---
echo ""
echo "## Tech Entry Placement"

# Test: Tech entries added before next section header
NEW_LANG="Java"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="add-java"

test_file=$(setup_test_file "## Active Technologies
- Python (main)
## Next Section
content")

update_existing_agent_file "$test_file" "2024-01-15"

# The Java entry should appear between Python and Next Section
assert_contains "Tech entry added to section" "Java (add-java)" "$test_file"

# Verify order: Java should come after Python line
if grep -n "Python" "$test_file" | head -1 | cut -d: -f1 > /tmp/python_line && \
   grep -n "Java" "$test_file" | head -1 | cut -d: -f1 > /tmp/java_line; then
    python_line=$(cat /tmp/python_line)
    java_line=$(cat /tmp/java_line)
    if [[ "$java_line" -gt "$python_line" ]]; then
        echo -e "${GREEN}PASS${NC}: Tech entry appears after existing entries"
        ((PASSED++))
    else
        echo -e "${RED}FAIL${NC}: Tech entry appears after existing entries"
        echo "  Java at line $java_line, Python at line $python_line"
        ((FAILED++))
    fi
    rm -f /tmp/python_line /tmp/java_line
fi

cleanup_test_file "$test_file"

# Test: Tech entries added before blank line in section
NEW_LANG="Ruby"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="add-ruby"

test_file=$(setup_test_file "## Active Technologies
- Python (main)

## Other Section")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Tech entry added before blank line" "Ruby (add-ruby)" "$test_file"

cleanup_test_file "$test_file"

# --- Edge Cases ---
echo ""
echo "## Edge Cases"

# Test: Empty NEW_LANG and NEW_FRAMEWORK (no tech to add)
NEW_LANG=""
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="no-tech"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)

## Recent Changes
- old: change")

update_existing_agent_file "$test_file" "2024-01-15"

assert_not_contains "No empty tech entry added" "( no-tech)" "$test_file"

cleanup_test_file "$test_file"

# Test: NEEDS CLARIFICATION values not added
NEW_LANG="NEEDS CLARIFICATION"
NEW_FRAMEWORK=""
NEW_DB="NEEDS CLARIFICATION"
CURRENT_BRANCH="unclear"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)")

update_existing_agent_file "$test_file" "2024-01-15"

assert_not_contains "NEEDS CLARIFICATION language not added" "NEEDS CLARIFICATION" "$test_file"

cleanup_test_file "$test_file"

# Test: File ending with tech section (no next header)
NEW_LANG="Scala"
NEW_FRAMEWORK=""
NEW_DB=""
CURRENT_BRANCH="add-scala"

test_file=$(setup_test_file "# Project

## Active Technologies
- Python (main)")

update_existing_agent_file "$test_file" "2024-01-15"

assert_contains "Tech added to section at EOF" "Scala (add-scala)" "$test_file"

cleanup_test_file "$test_file"

# --- Format Technology Stack ---
echo ""
echo "## format_technology_stack Function"

result=$(format_technology_stack "Python" "Flask")
if [[ "$result" == "Python + Flask" ]]; then
    echo -e "${GREEN}PASS${NC}: format_technology_stack with lang and framework"
    ((PASSED++))
else
    echo -e "${RED}FAIL${NC}: format_technology_stack with lang and framework"
    echo "  Expected: 'Python + Flask'"
    echo "  Actual: '$result'"
    ((FAILED++))
fi

result=$(format_technology_stack "Python" "")
if [[ "$result" == "Python" ]]; then
    echo -e "${GREEN}PASS${NC}: format_technology_stack with lang only"
    ((PASSED++))
else
    echo -e "${RED}FAIL${NC}: format_technology_stack with lang only"
    echo "  Expected: 'Python'"
    echo "  Actual: '$result'"
    ((FAILED++))
fi

result=$(format_technology_stack "" "")
if [[ "$result" == "" ]]; then
    echo -e "${GREEN}PASS${NC}: format_technology_stack with nothing"
    ((PASSED++))
else
    echo -e "${RED}FAIL${NC}: format_technology_stack with nothing"
    echo "  Expected: ''"
    echo "  Actual: '$result'"
    ((FAILED++))
fi

result=$(format_technology_stack "NEEDS CLARIFICATION" "Flask")
if [[ "$result" == "Flask" ]]; then
    echo -e "${GREEN}PASS${NC}: format_technology_stack filters NEEDS CLARIFICATION"
    ((PASSED++))
else
    echo -e "${RED}FAIL${NC}: format_technology_stack filters NEEDS CLARIFICATION"
    echo "  Expected: 'Flask'"
    echo "  Actual: '$result'"
    ((FAILED++))
fi

# --- Summary ---
echo ""
echo "=== Summary ==="
echo -e "Passed: ${GREEN}$PASSED${NC}"
echo -e "Failed: ${RED}$FAILED${NC}"

# Cleanup fixtures
rm -rf "$FIXTURES_DIR"

if [[ $FAILED -gt 0 ]]; then
    exit 1
fi
