#!/usr/bin/env bash
#
# Main test runner: verifies that the iteras plugin emits the correct cache-busting
# signals on paywalled responses and leaves cacheable responses alone.
#
# Usage:  bash tests/test-cache-busting.sh
# Env:    see tests/lib.sh for required variables.

DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck disable=SC1091
source "$DIR/lib.sh"

trap teardown_state EXIT

setup_state

URL_A=$(post_permalink "$(cat "$POST_A_FILE")")
URL_B=$(post_permalink "$(cat "$POST_B_FILE")")
URL_C=$(post_permalink "$(cat "$POST_C_FILE")")
URL_FEED="${SITE_URL%/}/?feed=rss2"
URL_FEED_SINGLE_B="${SITE_URL%/}/?p=$(cat "$POST_B_FILE")&feed=rss2"

info "Site: $SITE_URL"
info "Post A (unpaywalled):       $URL_A"
info "Post B (paywalled):         $URL_B"
info "Post C (override-off):      $URL_C"
info "Feed:                       $URL_FEED"

# -------------------------------------------------------------------
echo
info "1. Unpaywalled post is cacheable"
H=$(fetch_headers "$URL_A")
assert_headers_not_match "$H" "$CACHE_BUST_REGEX" "Post A: no no-cache/no-store/private Cache-Control"
assert_headers_not_match "$H" "x-litespeed-cache-control" "Post A: no X-LiteSpeed-Cache-Control header"

# -------------------------------------------------------------------
echo
info "2. Paywalled post, anonymous visitor: uncacheable"
H=$(fetch_headers "$URL_B")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Post B: Cache-Control has no-store/no-cache/private"
assert_headers_match "$H" "pragma: no-cache" "Post B: Pragma: no-cache"
assert_headers_match "$H" "vary:.*cookie" "Post B: Vary includes Cookie"
assert_headers_match "$H" "x-litespeed-cache-control: no-cache" "Post B: X-LiteSpeed-Cache-Control: no-cache"
assert_headers_match "$H" "x-accel-expires: 0" "Post B: X-Accel-Expires: 0"

# -------------------------------------------------------------------
echo
info "3. Paywalled post, valid iteraspass cookie: still uncacheable"
COOKIE=$(gen_iteraspass sub "$PAYWALL_ID" 3600)
H=$(fetch_headers "$URL_B" "$COOKIE")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Post B (auth): Cache-Control still set"

# -------------------------------------------------------------------
echo
info "4. Paywalled post, expired iteraspass cookie: uncacheable"
COOKIE_EXP=$(gen_iteraspass sub "$PAYWALL_ID" -10)
H=$(fetch_headers "$URL_B" "$COOKIE_EXP")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Post B (expired): Cache-Control still set"

# -------------------------------------------------------------------
echo
info "5. Paywalled post, wrong-key signature: uncacheable + truncated"
COOKIE_BAD=$(gen_iteraspass sub "$PAYWALL_ID" 3600 "${SIGNING_KEY}-tampered")
H=$(fetch_headers "$URL_B" "$COOKIE_BAD")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Post B (bad sig): Cache-Control still set"
B=$(fetch_body "$URL_B" "$COOKIE_BAD")
assert_body_contains "$B" "iteras-content-truncated" "Post B (bad sig): body truncated"

# -------------------------------------------------------------------
echo
info "6. Paywalled post overridden off by filter: cacheable"
H=$(fetch_headers "$URL_C")
assert_headers_not_match "$H" "$CACHE_BUST_REGEX" "Post C: cacheable (override returned false)"

# -------------------------------------------------------------------
echo
info "7a. Feed containing a paywalled post: uncacheable"
H=$(fetch_headers "$URL_FEED")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Feed: Cache-Control set when feed contains paywalled item"

echo
info "7b. Feed with no paywalled posts: cacheable"
# Fetch a search-results feed that only matches Post D (unpaywalled), so the feed
# query contains no paywalled posts even if the site has other paywalled content.
URL_FEED_CLEAN="${SITE_URL%/}/?s=UNIQUE_MARKER_ITERAS_CLEAN_FEED_SENTINEL&feed=rss2"
H=$(fetch_headers "$URL_FEED_CLEAN")
assert_headers_not_match "$H" "$CACHE_BUST_REGEX" "Feed (clean, search-only Post D): no Cache-Control busting"

echo
info "7c. Single-post comments feed for paywalled post: uncacheable"
H=$(fetch_headers "$URL_FEED_SINGLE_B")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Single-post feed for B: Cache-Control set"

# -------------------------------------------------------------------
echo
info "8. Toggle paywall_prevent_caching off: headers absent"
wph patch-option-json iteras_settings paywall_prevent_caching false > /dev/null
H=$(fetch_headers "$URL_B")
assert_headers_not_match "$H" "$CACHE_BUST_REGEX" "Post B with prevent_caching off: no Cache-Control busting"
# Re-enable
wph patch-option-json iteras_settings paywall_prevent_caching true > /dev/null

# -------------------------------------------------------------------
echo
info "9. Toggle server-side validation off: headers absent, body not truncated"
wph patch-option-json iteras_settings paywall_server_side_validation false > /dev/null
H=$(fetch_headers "$URL_B")
B=$(fetch_body "$URL_B")
assert_headers_not_match "$H" "$CACHE_BUST_REGEX" "Post B with SSV off: no Cache-Control busting"
assert_body_not_contains "$B" "iteras-content-truncated" "Post B with SSV off: body NOT truncated"
# Re-enable
wph patch-option-json iteras_settings paywall_server_side_validation true > /dev/null

# -------------------------------------------------------------------
echo
info "10. Empty signing_key, no cookie: paywalled post is uncacheable and truncated"
# (With empty signing_key + a well-formed cookie, pass_authorized() intentionally
#  skips signature verification - that is the existing JS-only-ish fallback. The
#  meaningful regression case is an anonymous visitor with no cookie.)
wph patch-option-json iteras_settings signing_key '""' > /dev/null
H=$(fetch_headers "$URL_B")
B=$(fetch_body "$URL_B")
assert_headers_match "$H" "$CACHE_BUST_REGEX" "Post B with no signing_key (anon): Cache-Control set"
assert_body_contains "$B" "iteras-content-truncated" "Post B with no signing_key (anon): body truncated"
# Restore
wph patch-option-json iteras_settings signing_key "\"$SIGNING_KEY\"" > /dev/null

# -------------------------------------------------------------------
echo
info "11. Override filter is invoked exactly once per post per request"
reset_filter_counter
fetch_body "$URL_B" > /dev/null
COUNT_AFTER_GET=$(read_filter_counter)
if [ "$COUNT_AFTER_GET" -eq 1 ]; then
  pass "Override filter invoked exactly 1 time per GET (per-request state cache memoises template_redirect + the_content)"
else
  fail "Override filter invocation count" "expected 1, got $COUNT_AFTER_GET"
fi

# -------------------------------------------------------------------
echo
info "12. Authorized visitor sees full body (sanity)"
B=$(fetch_body "$URL_B" "$(gen_iteraspass sub "$PAYWALL_ID" 3600)")
assert_body_not_contains "$B" "iteras-content-truncated" "Post B (auth): body NOT truncated"
assert_body_contains "$B" "ITERAS_FULL_BODY_B" "Post B (auth): full body marker present"

# -------------------------------------------------------------------
print_summary
[ "$FAILED" -eq 0 ]
