#!/bin/bash
# BUD-08 NIP-94 File Metadata Tags Test Suite
# This test is created FIRST (TDD) and will FAIL until implementation is added to src/main.c.
#
# Expected procedures to be implemented in src/main.c (BUD-08 section):
# - nip94_is_enabled()                  -> Read server_config.nip94_enabled (default true)
# - nip94_get_origin()                  -> Read server_config.cdn_origin (default http://localhost:9001)
# - mime_to_extension()                 -> Centralize MIME to extension mapping
# - nip94_build_blob_url()              -> Build canonical blob URL from origin + sha256 + extension
# - get_file_dimensions()               -> Detect WxH for PNG, JPEG, WebP (parse headers only)
# - nip94_build_tags()                  -> Build tags: ["url",...], ["m",...], ["x",...], ["size",...], optional ["dim","WxH"]
# - nip94_attach_to_descriptor()        -> Attach nip94 array to JSON response in /upload and /mirror
#
# Integration points expected:
# - PUT /upload success JSON includes "nip94" array
# - PUT /mirror success JSON includes "nip94" array
#
# Requirements:
# - curl, jq, sqlite3 must be available
# - Server should be running at http://localhost:9001 (restart-all.sh)

set -e

SERVER_URL="http://localhost:9001"
UPLOAD_ENDPOINT="${SERVER_URL}/upload"
MIRROR_ENDPOINT="${SERVER_URL}/mirror"
DB_PATH="db/ginxsom.db"

echo "=== BUD-08 NIP-94 File Metadata Tags Test Suite ==="

# Prereq checks
if ! command -v curl >/dev/null 2>&1; then
  echo "ERROR: curl not found"
  exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
  echo "ERROR: jq not found (required for JSON parsing)"
  exit 1
fi
if ! command -v sqlite3 >/dev/null 2>&1; then
  echo "ERROR: sqlite3 not found"
  exit 1
fi

# Helpers
die() {
  echo "FATAL: $*" 1>&2
  exit 1
}

json_has_nip94() {
  local json="$1"
  echo "$json" | jq -e '.nip94 and ( .nip94 | type == "array" )' >/dev/null 2>&1
}

nip94_get_tag() {
  local json="$1"
  local key="$2"
  echo "$json" | jq -r --arg k "$key" '.nip94 | map(select(.[0]==$k)) | if length>0 then .[0][1] else empty end'
}

reset_config_defaults() {
  # Restore defaults used by implementation
  sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO server_config (key, value) VALUES ('nip94_enabled','true');" || true
  sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO server_config (key, value) VALUES ('cdn_origin','http://localhost:9001');" || true
}

set_config_key() {
  local key="$1"
  local value="$2"
  sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO server_config (key, value) VALUES ('$key','$value');"
}

# Create temporary working directory
WORKDIR="tests/tmp_bud08"
mkdir -p "$WORKDIR"

# Create a tiny 1x1 PNG (base64)
TINY_PNG_B64="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO0RzjoAAAAASUVORK5CYII="
PNG_FILE="$WORKDIR/one_by_one.png"
echo "$TINY_PNG_B64" | base64 -d > "$PNG_FILE"

# Compute expected values
CONTENT_TYPE="image/png"
FILE_SIZE=$(wc -c < "$PNG_FILE" | tr -d ' ')
SHA256_HEX=$(sha256sum "$PNG_FILE" | awk '{print $1}')

echo ""
echo "Test artifact:"
echo "  File: $PNG_FILE"
echo "  Size: $FILE_SIZE"
echo "  SHA256: $SHA256_HEX"
echo ""

# Ensure defaults
reset_config_defaults

# --- Test 1: PUT /upload returns nip94 with minimal required tags
echo "=== Test 1: PUT /upload returns nip94 minimal tags ==="
UPLOAD_JSON=$(curl -s -X PUT "$UPLOAD_ENDPOINT" \
  -H "Content-Type: $CONTENT_TYPE" \
  --data-binary @"$PNG_FILE")

echo "Response:"
echo "$UPLOAD_JSON"
echo ""

if json_has_nip94 "$UPLOAD_JSON"; then
  URL_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.url')
  TYPE_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.type')
  SIZE_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.size')
  SHA256_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.sha256')

  TAG_URL=$(nip94_get_tag "$UPLOAD_JSON" "url")
  TAG_M=$(nip94_get_tag "$UPLOAD_JSON" "m")
  TAG_X=$(nip94_get_tag "$UPLOAD_JSON" "x")
  TAG_SIZE=$(nip94_get_tag "$UPLOAD_JSON" "size")

  PASS=1
  [ -n "$TAG_URL" ] || { echo "FAIL: nip94 missing url tag"; PASS=0; }
  [ -n "$TAG_M" ] || { echo "FAIL: nip94 missing m tag"; PASS=0; }
  [ -n "$TAG_X" ] || { echo "FAIL: nip94 missing x tag"; PASS=0; }
  [ -n "$TAG_SIZE" ] || { echo "FAIL: nip94 missing size tag"; PASS=0; }

  # Validate tag values match descriptor
  [ "$TAG_URL" = "$URL_FIELD" ] || { echo "FAIL: nip94 url tag != descriptor url"; PASS=0; }
  [ "$TAG_M" = "$TYPE_FIELD" ] || { echo "FAIL: nip94 m tag != descriptor type"; PASS=0; }
  [ "$TAG_X" = "$SHA256_FIELD" ] || { echo "FAIL: nip94 x tag != descriptor sha256"; PASS=0; }
  [ "$TAG_SIZE" = "$SIZE_FIELD" ] || { echo "FAIL: nip94 size tag != descriptor size"; PASS=0; }

  if [ "$PASS" = "1" ]; then
    echo "✅ Test 1 PASSED: nip94 minimal tags present and correct"
  else
    echo "❌ Test 1 FAILED"
  fi
else
  echo "❌ Test 1 FAILED: Response missing nip94 array"
fi

# --- Test 2: dim present and equals 1x1 for PNG
echo ""
echo "=== Test 2: dim tag for 1x1 PNG ==="
TAG_DIM=$(nip94_get_tag "$UPLOAD_JSON" "dim" || true)
if [ -n "$TAG_DIM" ]; then
  if [ "$TAG_DIM" = "1x1" ]; then
    echo "✅ Test 2 PASSED: dim tag present and equals 1x1"
  else
    echo "❌ Test 2 FAILED: dim tag expected 1x1, got '$TAG_DIM'"
  fi
else
  echo "❌ Test 2 FAILED: dim tag not present"
fi

# --- Test 3: nip94 disabled via config should omit nip94 field
echo ""
echo "=== Test 3: nip94 disabled via server_config ==="
set_config_key "nip94_enabled" "false"

UPLOAD_JSON_DISABLED=$(curl -s -X PUT "$UPLOAD_ENDPOINT" \
  -H "Content-Type: $CONTENT_TYPE" \
  --data-binary @"$PNG_FILE")

echo "Response:"
echo "$UPLOAD_JSON_DISABLED"
echo ""

if json_has_nip94 "$UPLOAD_JSON_DISABLED"; then
  echo "❌ Test 3 FAILED: nip94 present despite nip94_enabled=false"
else
  echo "✅ Test 3 PASSED: nip94 omitted when nip94_enabled=false"
fi

# Restore true for next tests
set_config_key "nip94_enabled" "true"

# --- Test 4: cdn_origin config changes nip94 url (and descriptor url)
echo ""
echo "=== Test 4: cdn_origin origin override ==="
CUSTOM_ORIGIN="http://example-cdn.local"
set_config_key "cdn_origin" "$CUSTOM_ORIGIN"

UPLOAD_JSON_ORIGIN=$(curl -s -X PUT "$UPLOAD_ENDPOINT" \
  -H "Content-Type: $CONTENT_TYPE" \
  --data-binary @"$PNG_FILE")

echo "Response:"
echo "$UPLOAD_JSON_ORIGIN"
echo ""

if json_has_nip94 "$UPLOAD_JSON_ORIGIN"; then
  URL_FIELD2=$(echo "$UPLOAD_JSON_ORIGIN" | jq -r '.url')
  TAG_URL2=$(nip94_get_tag "$UPLOAD_JSON_ORIGIN" "url")
  if [[ "$URL_FIELD2" == $CUSTOM_ORIGIN/* ]] && [[ "$TAG_URL2" == $CUSTOM_ORIGIN/* ]]; then
    echo "✅ Test 4 PASSED: nip94 url and descriptor url use configured origin"
  else
    echo "❌ Test 4 FAILED: origin not applied to urls"
  fi
else
  echo "❌ Test 4 FAILED: Response missing nip94 array"
fi

# Restore default origin
set_config_key "cdn_origin" "http://localhost:9001"

# --- Test 5: PUT /mirror returns nip94 minimal tags (best effort, network dependent)
echo ""
echo "=== Test 5: PUT /mirror returns nip94 minimal tags (network dependent) ==="
# Use a public small PNG; if network/policy blocks, mark INFO instead of failure.
REMOTE_URL="https://upload.wikimedia.org/wikipedia/commons/3/3c/Shaki_waterfall.jpg"
MIRROR_JSON=$(curl -s -X PUT "$MIRROR_ENDPOINT" \
  -H "Content-Type: application/json" \
  --data "{\"url\":\"$REMOTE_URL\"}")

HTTP_OK=$(echo "$MIRROR_JSON" | jq -e '.sha256 and .type and .size' >/dev/null 2>&1; echo $?)
if [ "$HTTP_OK" = "0" ]; then
  if json_has_nip94 "$MIRROR_JSON"; then
    TAG_URL_M=$(nip94_get_tag "$MIRROR_JSON" "url")
    TAG_M_M=$(nip94_get_tag "$MIRROR_JSON" "m")
    TAG_X_M=$(nip94_get_tag "$MIRROR_JSON" "x")
    TAG_SIZE_M=$(nip94_get_tag "$MIRROR_JSON" "size")
    if [ -n "$TAG_URL_M" ] && [ -n "$TAG_M_M" ] && [ -n "$TAG_X_M" ] && [ -n "$TAG_SIZE_M" ]; then
      echo "✅ Test 5 PASSED: nip94 minimal tags present for mirror"
    else
      echo "❌ Test 5 FAILED: nip94 minimal tags missing for mirror response"
    fi
  else
    echo "❌ Test 5 FAILED: mirror response missing nip94 array"
  fi
else
  echo "ℹ️  Test 5 INFO: mirror request did not return a blob descriptor (network or policy); skipping strict check"
fi

# Cleanup and restore defaults
reset_config_defaults
rm -rf "$WORKDIR"

echo ""
echo "=== End of BUD-08 NIP-94 Test Suite ==="