#!/usr/bin/env bash
#
# This is a simple test file that checks the behaviour
# of a DSL specification from ./examples directory.
#
# The main source of truce is DSL specification.
#
# This file is auto generated by AI and should be updated after specs changed
#
set -euo pipefail

BASE_URL="http://localhost:8228"
PASS=0
FAIL=0
TOTAL=0

pass() {
    PASS=$((PASS + 1))
    TOTAL=$((TOTAL + 1))
    echo "  PASS: $1"
}

fail() {
    FAIL=$((FAIL + 1))
    TOTAL=$((TOTAL + 1))
    echo "  FAIL: $1"
}

check_status() {
    local desc="$1"
    local expected_code="$2"
    shift 2
    local actual_code
    actual_code=$(curl -s -o /dev/null -w "%{http_code}" "$@")
    if [ "$actual_code" = "$expected_code" ]; then
        pass "$desc (HTTP $actual_code)"
    else
        fail "$desc (expected HTTP $expected_code, got HTTP $actual_code)"
    fi
}

check_body_contains() {
    local desc="$1"
    local expected="$2"
    shift 2
    local actual
    actual=$(curl -s "$@")
    if echo "$actual" | grep -qF "$expected"; then
        pass "$desc"
    else
        fail "$desc (body does not contain: $expected)"
    fi
}

check_body_not_contains() {
    local desc="$1"
    local unexpected="$2"
    shift 2
    local actual
    actual=$(curl -s "$@")
    if ! echo "$actual" | grep -qF "$unexpected"; then
        pass "$desc"
    else
        fail "$desc (body should not contain: $unexpected)"
    fi
}

check_header() {
    local desc="$1"
    local header_name="$2"
    local expected_value="$3"
    shift 3
    local url="$@"
    # curl -sI returns lowercase headers, so normalize for matching and comparison
    local lower_header="${header_name,,}"
    local actual_value
    actual_value=$(curl -sI "$url" | grep -i "^${lower_header}:" | head -1 | sed "s/^${lower_header}: *//" | tr -d '\r')
    if [ "${actual_value,,}" = "${expected_value,,}" ]; then
        pass "$desc (Header: $header_name=$actual_value)"
    else
        fail "$desc (expected Header: $header_name=$expected_value, got $header_name=$actual_value)"
    fi
}

echo "=========================================="
echo " Apate Examples Spec Tests"
echo "=========================================="
echo ""

# ==========================================
# apate-specs.toml — matchers, jinja, multi-response
# ==========================================
echo "--- apate-specs.toml ---"

# GET /user/list with name=Ivan -> 200, body contains Ivan
check_status "GET /user/list?name=Ivan -> 200" "200" "$BASE_URL/user/list?name=Ivan"
check_body_contains "body contains Ivan" '"name":"Ivan"' "$BASE_URL/user/list?name=Ivan"

# GET /user/list with name=Adolph -> 200, body contains Adolph
check_status "GET /user/list?name=Adolph -> 200" "200" "$BASE_URL/user/list?name=Adolph"
check_body_contains "body contains Adolph" '"name":"Adolph"' "$BASE_URL/user/list?name=Adolph"

# GET /user/list with name=Rajesh -> 503
check_status "GET /user/list?name=Rajesh -> 503" "503" "$BASE_URL/user/list?name=Rajesh"
check_body_contains "body contains message" '"message": "Impossible to list them all"' "$BASE_URL/user/list?name=Rajesh"

# GET /user/list without query arg -> 200, fallback body
check_status "GET /user/list (no query) -> 200" "200" "$BASE_URL/user/list"
check_body_contains "body contains Ivan" '"name":"Ivan"' "$BASE_URL/user/list"

# POST /user/add with Rajesh name -> 416
check_status "POST /user/add (Rajesh) -> 416" "416" -X POST -H "Content-Type: application/json" -d '{"name":"Rajesh","surname":"Patel"}' "$BASE_URL/user/add"

# POST /user/add with Abhishek name -> 416
check_status "POST /user/add (Abhishek) -> 416" "416" -X POST -H "Content-Type: application/json" -d '{"name":"Abhishek","surname":"Kumar"}' "$BASE_URL/user/add"

# POST /user/add with Ram name -> 416
check_status "POST /user/add (Ram) -> 416" "416" -X POST -H "Content-Type: application/json" -d '{"name":"Ram","surname":"Sharma"}' "$BASE_URL/user/add"

# POST /user/add with Sri name -> 416
check_status "POST /user/add (Sri) -> 416" "416" -X POST -H "Content-Type: application/json" -d '{"name":"Sri","surname":"Reddy"}' "$BASE_URL/user/add"

# POST /user/add with Ramesh name -> 416
check_status "POST /user/add (Ramesh) -> 416" "416" -X POST -H "Content-Type: application/json" -d '{"name":"Ramesh","surname":"Nair"}' "$BASE_URL/user/add"

# POST /user/add with Adolph Hitler -> 406
check_status "POST /user/add (Adolph Hitler) -> 406" "406" -X POST -H "Content-Type: application/json" -d '{"name":"Adolph","surname":"Hitler"}' "$BASE_URL/user/add"

# POST /user/add with valid body -> 200, jinja output
check_status "POST /user/add (valid) -> 200" "200" -X POST -H "Content-Type: application/json" -d '{"name":"John","surname":"Doe"}' "$BASE_URL/user/add"
check_body_contains "body contains John" '"name": "John"' -X POST -H "Content-Type: application/json" -d '{"name":"John","surname":"Doe"}' "$BASE_URL/user/add"

# GET /user/740 -> 200, path arg match
check_status "GET /user/740 -> 200" "200" "$BASE_URL/user/740"
check_body_contains "body contains Adolph Greenberg" '"name":"Adolph"' "$BASE_URL/user/740"

# GET /user?id=42 -> 200, query arg match
check_status "GET /user?id=42 -> 200" "200" "$BASE_URL/user?id=42"
check_body_contains "body contains id:42" '"id":42' "$BASE_URL/user?id=42"

# GET /user without id -> 500 (no id set in jinja)
check_status "GET /user (no id) -> 500" "500" "$BASE_URL/user"

echo ""

# ==========================================
# apate-specs-bin.toml — binary responses
# ==========================================
echo "--- apate-specs-bin.toml ---"

# GET /file/base64.png -> 200, Content-Type: image/png
check_status "GET /file/base64.png -> 200" "200" "$BASE_URL/file/base64.png"
check_header "Content-Type is image/png" "Content-Type" "image/png" "$BASE_URL/file/base64.png"

# GET /file/hex.png -> 200, Content-Type: image/png
check_status "GET /file/hex.png -> 200" "200" "$BASE_URL/file/hex.png"
check_header "Content-Type is image/png (hex)" "Content-Type" "image/png" "$BASE_URL/file/hex.png"

echo ""

# ==========================================
# apate-specs-rhai.toml — Rhai matcher, output, processor
# ==========================================
echo "--- apate-specs-rhai.toml ---"

# GET /rhai/search with surname=Ivanov -> 200, filtered body
check_status "GET /rhai/search?surname=Ivanov -> 200" "200" "$BASE_URL/rhai/search?surname=Ivanov"
check_body_contains "body contains Ivanov filter" '"surname":"Ivanov"' "$BASE_URL/rhai/search?surname=Ivanov"

# GET /rhai/list with name=Ivan -> 200, filtered body
check_status "GET /rhai/list?name=Ivan -> 200" "200" "$BASE_URL/rhai/list?name=Ivan"
check_body_contains "body contains Ivan filter" '"name":"Ivan"' "$BASE_URL/rhai/list?name=Ivan"

# GET /rhai/list without filter -> 200, all records
check_status "GET /rhai/list (no filter) -> 200" "200" "$BASE_URL/rhai/list"
check_body_contains "body contains Smith" '"surname":"Smith"' "$BASE_URL/rhai/list"

# GET /rhai/match with foo=test -> 200, inline matcher passes
check_status "GET /rhai/match?foo=test -> 200" "200" "$BASE_URL/rhai/match?foo=test"
check_body_contains "body contains Rhai inline matcher is OK" '"message": "Rhai inline matcher is OK"' "$BASE_URL/rhai/match?foo=test"

# GET /rhai/match with foo=none -> 404, inline matcher fails
check_status "GET /rhai/match?foo=none -> 404" "404" "$BASE_URL/rhai/match?foo=none"

# GET /rhai/match/ref with foo=test -> 200, rhai_ref matcher passes
check_status "GET /rhai/match/ref?foo=test -> 200" "200" "$BASE_URL/rhai/match/ref?foo=test"
check_body_contains "body contains Rhai top level matcher is OK" '"message": "Rhai top level matcher is OK"' "$BASE_URL/rhai/match/ref?foo=test"

# GET /rhai/match/ref with foo=none -> 404, rhai_ref matcher fails
check_status "GET /rhai/match/ref?foo=none -> 404" "404" "$BASE_URL/rhai/match/ref?foo=none"

# GET /rhai/post -> 200, body has post and post_ref fields from processors
check_status "GET /rhai/post -> 200" "200" "$BASE_URL/rhai/post"
check_body_contains "body contains post field" '"post":"hello from script post processor"' "$BASE_URL/rhai/post"
check_body_contains "body contains post_ref field" '"post_ref":"Map len() returned' "$BASE_URL/rhai/post"

echo ""

# ==========================================
# apate-specs-app.toml — stateful storage, rhai_ref output
# ==========================================
echo "--- apate-specs-app.toml ---"

# POST /app/user/add -> 200, returns created user with id (stateful)
check_status "POST /app/user/add -> 200" "200" -X POST -H "Content-Type: application/json" -d '{"name":"Alice","surname":"Wonder"}' "$BASE_URL/app/user/add"

# GET /app/user/list -> 200, returns users list
check_status "GET /app/user/list -> 200" "200" "$BASE_URL/app/user/list"
check_body_contains "body contains Alice Wonder" '"name":"Alice"' "$BASE_URL/app/user/list"

# GET /app/output/ref -> 200, rhai_ref output with random values and args
check_status "GET /app/output/ref -> 200" "200" "$BASE_URL/app/output/ref"
check_body_contains "body contains message Success" '"message":"Success"' "$BASE_URL/app/output/ref"
check_body_contains "body contains custom_arg1" '"custom_arg1"' "$BASE_URL/app/output/ref"

echo ""

# ==========================================
# apate-template-specs.toml — Jinja templates, ctx, functions
# ==========================================
echo "--- apate-template-specs.toml ---"

# GET /tpl/fn -> 200, Content-Type: text/markdown
check_status "GET /tpl/fn -> 200" "200" "$BASE_URL/tpl/fn"
check_header "Content-Type is text/markdown" "Content-Type" "text/markdown" "$BASE_URL/tpl/fn"

# GET /tpl/ctx/hello -> 200, path arg echoed in body
check_status "GET /tpl/ctx/hello -> 200" "200" "$BASE_URL/tpl/ctx/hello"
check_body_contains "body contains hello" "hello" "$BASE_URL/tpl/ctx/hello"

# GET /tpl/ctx without path arg -> 200, default value shown
check_status "GET /tpl/ctx -> 200" "200" "$BASE_URL/tpl/ctx"
check_body_contains "body contains DOES_NOT_EXIST" "DOES_NOT_EXIST" "$BASE_URL/tpl/ctx"

echo ""

# ==========================================
# Summary
# ==========================================
echo "=========================================="
echo " Results: $PASS passed, $FAIL failed (total: $TOTAL)"
echo "=========================================="

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