#!/bin/bash

set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
URL="${1:-http://127.0.0.1:7703}"

# Use test tokens from environment or defaults
TOKEN="${TEST_TOKEN1:-t570H7DmK2VBfCwUmtFaUXyzVklL90E1}"

echo "Testing input validation at $URL"
echo "======================================"

PASS_COUNT=0
FAIL_COUNT=0

# Helper function to test an upload with expected result
test_upload() {
    local test_name="$1"
    local metadata="$2"
    local expected_result="$3"  # "success" or "error"
    local file_content="${4:-test content}"
    
    echo ""
    echo "Test: $test_name"
    echo "Metadata: $metadata"
    
    # Create a temp file
    local temp_file=$(mktemp)
    echo "$file_content" > "$temp_file"
    
    # Perform upload
    local response=$(curl -s -X PUT \
        -H "Authorization: Bearer $TOKEN" \
        -F "file=@$temp_file" \
        -F "metadata=$metadata" \
        "$URL/upload" 2>/dev/null || echo '{"result":"error","error":"curl failed"}')
    
    rm -f "$temp_file"
    
    local result=$(echo "$response" | jq -r '.result' 2>/dev/null || echo "parse_error")
    
    if [ "$expected_result" = "error" ]; then
        if [ "$result" = "error" ]; then
            echo "  ✓ Correctly rejected invalid input"
            echo "  Error: $(echo "$response" | jq -r '.error' 2>/dev/null)"
            ((PASS_COUNT++))
        else
            echo "  ✗ FAILED: Expected rejection but got: $response"
            ((FAIL_COUNT++))
        fi
    else
        if [ "$result" = "success" ]; then
            echo "  ✓ Correctly accepted valid input"
            ((PASS_COUNT++))
        else
            echo "  ✗ FAILED: Expected success but got: $response"
            ((FAIL_COUNT++))
        fi
    fi
}

# Test update endpoint
test_update() {
    local test_name="$1"
    local body="$2"
    local expected_result="$3"  # "success" or "error"
    
    echo ""
    echo "Test: $test_name"
    echo "Body: $body"
    
    local response=$(curl -s -X PUT \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json" \
        -d "$body" \
        "$URL/update" 2>/dev/null || echo '{"result":"error","error":"curl failed"}')
    
    local result=$(echo "$response" | jq -r '.result' 2>/dev/null || echo "parse_error")
    
    if [ "$expected_result" = "error" ]; then
        if [ "$result" = "error" ]; then
            echo "  ✓ Correctly rejected invalid input"
            echo "  Error: $(echo "$response" | jq -r '.error' 2>/dev/null)"
            ((PASS_COUNT++))
        else
            echo "  ✗ FAILED: Expected rejection but got: $response"
            ((FAIL_COUNT++))
        fi
    else
        if [ "$result" = "success" ]; then
            echo "  ✓ Correctly accepted valid input"
            ((PASS_COUNT++))
        else
            echo "  ✗ FAILED: Expected success but got: $response"
            ((FAIL_COUNT++))
        fi
    fi
}

echo ""
echo "1. Testing Label:Tag Validation"
echo "================================"

# Valid label:tag
test_upload "Valid label:tag" '{"labeltags":["test:v1"]}' "success"

# Invalid: missing colon
test_upload "Missing colon" '{"labeltags":["testv1"]}' "error"

# Invalid: empty label
test_upload "Empty label" '{"labeltags":[":v1"]}' "error"

# Invalid: empty tag
test_upload "Empty tag" '{"labeltags":["test:"]}' "error"

# Invalid: multiple colons
test_upload "Multiple colons" '{"labeltags":["test:v1:extra"]}' "error"

# Invalid: special characters
test_upload "Invalid characters" '{"labeltags":["test@#$:v1"]}' "error"

# Invalid: starts with non-alphanumeric
test_upload "Starts with dash" '{"labeltags":["-test:v1"]}' "error"

# Valid: with allowed special chars
test_upload "Valid special chars" '{"labeltags":["test_project-1.0:v1"]}' "success"

# Invalid: too long label (>255 chars)
LONG_LABEL=""
for i in {1..256}; do LONG_LABEL="${LONG_LABEL}a"; done
test_upload "Label too long" "{\"labeltags\":[\"${LONG_LABEL}:v1\"]}" "error"

# Invalid: too long tag (>255 chars)
LONG_TAG=""
for i in {1..256}; do LONG_TAG="${LONG_TAG}a"; done
test_upload "Tag too long" "{\"labeltags\":[\"test:${LONG_TAG}\"]}" "error"

# Invalid: too many labeltags (>100)
MANY_TAGS='{"labeltags":['
for i in {1..101}; do
    if [ $i -gt 1 ]; then MANY_TAGS="${MANY_TAGS},"; fi
    MANY_TAGS="${MANY_TAGS}\"test${i}:v${i}\""
done
MANY_TAGS="${MANY_TAGS}]}"
test_upload "Too many labeltags" "$MANY_TAGS" "error"

# Invalid: duplicate labeltags
test_upload "Duplicate labeltags" '{"labeltags":["test:v1","test:v1"]}' "error"

echo ""
echo "2. Testing Metadata Validation"
echo "==============================="

# Valid metadata with various fields
test_upload "Valid metadata" '{"labeltags":["test:meta1"],"custom_field":"value","number":123,"bool":true}' "success"

# Invalid: metadata not an object
test_upload "Metadata not object" '["not","an","object"]' "error"

# Invalid: field name with invalid characters
test_upload "Invalid field name" '{"labeltags":["test:meta2"],"field-with-dash":"value"}' "error"

# Invalid: field name starting with number
test_upload "Field starts with number" '{"labeltags":["test:meta3"],"123field":"value"}' "error"

# Invalid: field value too long (>4096 chars)
LONG_VALUE=""
for i in {1..4097}; do LONG_VALUE="${LONG_VALUE}a"; done
test_upload "Field value too long" "{\"labeltags\":[\"test:meta4\"],\"field\":\"${LONG_VALUE}\"}" "error"

# Invalid: nested object too deep (>5 levels)
DEEP_NESTED='{"labeltags":["test:meta5"],"l1":{"l2":{"l3":{"l4":{"l5":{"l6":"too deep"}}}}}}'
test_upload "Nested too deep" "$DEEP_NESTED" "error"

# Valid: nested object within limit
VALID_NESTED='{"labeltags":["test:meta6"],"l1":{"l2":{"l3":{"l4":{"l5":"ok"}}}}}'
test_upload "Valid nested" "$VALID_NESTED" "success"

echo ""
echo "3. Testing Filename Validation"
echo "==============================="

# Invalid: directory traversal
test_upload "Directory traversal" '{"labeltags":["test:file1"],"filename":"../etc/passwd"}' "error"

# Invalid: null byte
test_upload "Null byte in filename" "{\"labeltags\":[\"test:file2\"],\"filename\":\"file\\u0000.txt\"}" "error"

# Invalid: path separator
test_upload "Path separator" '{"labeltags":["test:file3"],"filename":"path/to/file.txt"}' "error"

# Invalid: Windows reserved name
test_upload "Windows reserved" '{"labeltags":["test:file4"],"filename":"CON.txt"}' "error"

# Valid: normal filename
test_upload "Valid filename" '{"labeltags":["test:file5"],"filename":"valid_file-123.txt"}' "success"

echo ""
echo "4. Testing Hash Validation (via update endpoint)"
echo "================================================="

# First create a valid object to update
echo "Creating test object..."
TEMP_FILE=$(mktemp)
echo "test content for update" > "$TEMP_FILE"
CREATE_RESPONSE=$(curl -s -X PUT \
    -H "Authorization: Bearer $TOKEN" \
    -F "file=@$TEMP_FILE" \
    -F 'metadata={"labeltags":["test:update1"]}' \
    "$URL/upload")
rm -f "$TEMP_FILE"

HASH=$(echo "$CREATE_RESPONSE" | jq -r '.hash' 2>/dev/null || echo "")

if [ ! -z "$HASH" ]; then
    # Valid hash update
    test_update "Valid hash update" "{\"hash\":\"$HASH\",\"metadata\":{\"updated\":true}}" "success"
    
    # Invalid: hash wrong length
    test_update "Hash wrong length" '{"hash":"abc123","metadata":{"updated":true}}' "error"
    
    # Invalid: hash with invalid characters
    test_update "Hash invalid chars" '{"hash":"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz","metadata":{"updated":true}}' "error"
    
    # Invalid: empty hash
    test_update "Empty hash" '{"hash":"","metadata":{"updated":true}}' "error"
else
    echo "  ⚠ Skipping hash validation tests (couldn't create test object)"
fi

echo ""
echo "5. Testing Delete Endpoint Validation"
echo "======================================"

# Test delete with invalid hash
echo ""
echo "Test: Delete with invalid hash"
DELETE_RESPONSE=$(curl -s -H "Authorization: Bearer $TOKEN" \
    "$URL/deleteobject?hash=invalid" 2>/dev/null)
DELETE_RESULT=$(echo "$DELETE_RESPONSE" | jq -r '.result' 2>/dev/null || echo "parse_error")
if [ "$DELETE_RESULT" = "error" ]; then
    echo "  ✓ Correctly rejected invalid hash"
    echo "  Error: $(echo "$DELETE_RESPONSE" | jq -r '.error' 2>/dev/null)"
    ((PASS_COUNT++))
else
    echo "  ✗ FAILED: Expected rejection but got: $DELETE_RESPONSE"
    ((FAIL_COUNT++))
fi

echo ""
echo "======================================"
echo "Test Results:"
echo "  Passed: $PASS_COUNT"
echo "  Failed: $FAIL_COUNT"
echo ""

if [ $FAIL_COUNT -eq 0 ]; then
    echo "✓ All input validation tests passed!"
    exit 0
else
    echo "✗ Some tests failed"
    exit 1
fi