#!/bin/bash

# Ginxsom Admin API Test Script
# Tests admin API endpoints using nak (for Nostr events) and curl

set -e

# Configuration
GINXSOM_URL="http://localhost:9001"
ADMIN_PRIVKEY="${ADMIN_PRIVKEY:-}"
ADMIN_PUBKEY=""

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Helper functions
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }

check_dependencies() {
    log_info "Checking dependencies..."
    for cmd in nak curl jq; do
        if ! command -v $cmd &> /dev/null; then
            log_error "$cmd is not installed"
            echo ""
            echo "Please install missing dependencies:"
            echo "- nak: https://github.com/fiatjaf/nak"
            echo "- curl: standard HTTP client"
            echo "- jq: JSON processor (sudo apt install jq)"
            exit 1
        fi
    done
    log_success "All dependencies found"
}

load_admin_keys() {
    if [ -f ".admin_keys" ]; then
        log_info "Loading admin keys from .admin_keys file"
        source .admin_keys
    fi
    
    if [ -z "$ADMIN_PRIVKEY" ]; then
        log_error "Admin private key not found"
        echo ""
        echo "Please set ADMIN_PRIVKEY environment variable or create .admin_keys file:"
        echo "  export ADMIN_PRIVKEY='your_admin_private_key_here'"
        echo ""
        echo "Or run the setup wizard to generate keys:"
        echo "  ./scripts/setup.sh"
        exit 1
    fi
    
    ADMIN_PUBKEY=$(echo "$ADMIN_PRIVKEY" | nak key public)
    log_info "Admin public key: $ADMIN_PUBKEY"
}

create_admin_event() {
    local method="$1"
    local content="admin_request"
    local expiration=$(($(date +%s) + 3600))  # 1 hour from now
    
    # Create Nostr event with nak
    local event=$(nak event -k 24242 -c "$content" \
        --tag t="$method" \
        --tag expiration="$expiration" \
        --sec "$ADMIN_PRIVKEY")
    
    echo "$event"
}

send_admin_request() {
    local method="$1"
    local endpoint="$2"
    local data="$3"
    
    log_info "Testing $method $endpoint"
    
    # Create authenticated Nostr event
    local event=$(create_admin_event "$method")
    local auth_header="Nostr $(echo "$event" | base64 -w 0)"
    
    # Send request with curl
    local curl_args=(-s -w "%{http_code}" -H "Authorization: $auth_header")
    
    if [[ "$method" == "PUT" && -n "$data" ]]; then
        curl_args+=(-H "Content-Type: application/json" -d "$data")
    fi
    
    local response=$(curl "${curl_args[@]}" -X "$method" "$GINXSOM_URL$endpoint")
    local http_code="${response: -3}"
    local body="${response%???}"
    
    if [[ "$http_code" =~ ^2 ]]; then
        log_success "$method $endpoint - HTTP $http_code"
        if [[ -n "$body" ]]; then
            echo "$body" | jq . 2>/dev/null || echo "$body"
        fi
        return 0
    else
        log_error "$method $endpoint - HTTP $http_code"
        echo "$body" | jq . 2>/dev/null || echo "$body"
        return 1
    fi
}

test_health_endpoint() {
    echo "================================================================="
    log_info "Testing Health Endpoint (no auth required)"
    echo "================================================================="
    local response=$(curl -s -w "%{http_code}" "$GINXSOM_URL/api/health")
    local http_code="${response: -3}"
    local body="${response%???}"
    
    if [[ "$http_code" =~ ^2 ]]; then
        log_success "GET /api/health - HTTP $http_code"
        echo "$body" | jq .
        return 0
    else
        log_error "GET /api/health - HTTP $http_code"
        echo "$body"
        return 1
    fi
}

test_stats_endpoint() {
    echo ""
    echo "================================================================="
    log_info "Testing Statistics Endpoint"
    echo "================================================================="
    send_admin_request "GET" "/api/stats"
}

test_config_endpoints() {
    echo ""
    echo "================================================================="
    log_info "Testing Configuration Endpoints"
    echo "================================================================="
    
    # Get current config
    log_info "Getting current configuration..."
    send_admin_request "GET" "/api/config"
    
    echo ""
    
    # Update config
    log_info "Updating configuration..."
    local config_update='{
        "max_file_size": "209715200",
        "nip94_enabled": "true",
        "auth_cache_ttl": "600"
    }'
    
    if send_admin_request "PUT" "/api/config" "$config_update"; then
        echo ""
        log_info "Verifying configuration update..."
        send_admin_request "GET" "/api/config"
    fi
}

test_files_endpoint() {
    echo ""
    echo "================================================================="
    log_info "Testing Files Endpoint"
    echo "================================================================="
    send_admin_request "GET" "/api/files?limit=10&offset=0"
}

verify_server_status() {
    log_info "Checking if Ginxsom server is running..."
    
    if curl -s --connect-timeout 5 "$GINXSOM_URL/api/health" >/dev/null 2>&1; then
        log_success "Server is responding"
        return 0
    else
        log_error "Server is not responding at $GINXSOM_URL"
        echo ""
        echo "Please ensure the Ginxsom server is running:"
        echo "  make run"
        echo ""
        echo "Or check if the server is running on a different port."
        return 1
    fi
}

verify_admin_config() {
    log_info "Verifying admin configuration in database..."
    
    if [ ! -f "db/ginxsom.db" ]; then
        log_warning "Database not found at db/ginxsom.db"
        return 1
    fi
    
    local db_admin_pubkey=$(sqlite3 db/ginxsom.db "SELECT value FROM server_config WHERE key = 'admin_pubkey';" 2>/dev/null || echo "")
    local admin_enabled=$(sqlite3 db/ginxsom.db "SELECT value FROM server_config WHERE key = 'admin_enabled';" 2>/dev/null || echo "")
    
    if [ -z "$db_admin_pubkey" ]; then
        log_warning "No admin_pubkey found in database"
        echo ""
        echo "Configure admin access with:"
        echo "sqlite3 db/ginxsom.db << EOF"
        echo "INSERT OR REPLACE INTO server_config (key, value, description) VALUES"
        echo "    ('admin_pubkey', '$ADMIN_PUBKEY', 'Admin authorized pubkey'),"
        echo "    ('admin_enabled', 'true', 'Enable admin interface');"
        echo "EOF"
        return 1
    fi
    
    if [ "$db_admin_pubkey" != "$ADMIN_PUBKEY" ]; then
        log_warning "Admin pubkey mismatch!"
        echo "  Database: $db_admin_pubkey"
        echo "  Current:  $ADMIN_PUBKEY"
        return 1
    fi
    
    if [ "$admin_enabled" != "true" ]; then
        log_warning "Admin interface is disabled in database"
        return 1
    fi
    
    log_success "Admin configuration verified"
    return 0
}

show_test_summary() {
    echo ""
    echo "================================================================="
    log_success "Admin API testing complete!"
    echo "================================================================="
    echo ""
    echo "Admin credentials:"
    echo "  Private Key: $ADMIN_PRIVKEY"
    echo "  Public Key:  $ADMIN_PUBKEY"
    echo ""
    echo "Next steps:"
    echo "1. Implement web admin interface"
    echo "2. Set up monitoring dashboards"
    echo "3. Configure additional admin features"
    echo ""
}

main() {
    echo "=== Ginxsom Admin API Test Suite ==="
    echo ""
    
    check_dependencies
    load_admin_keys
    
    if ! verify_server_status; then
        exit 1
    fi
    
    if ! verify_admin_config; then
        log_warning "Admin configuration issues detected - some tests may fail"
        echo ""
    fi
    
    # Run API tests
    local failed_tests=0
    
    if ! test_health_endpoint; then
        ((failed_tests++))
    fi
    
    if ! test_stats_endpoint; then
        ((failed_tests++))
    fi
    
    if ! test_config_endpoints; then
        ((failed_tests++))
    fi
    
    if ! test_files_endpoint; then
        ((failed_tests++))
    fi
    
    show_test_summary
    
    if [ $failed_tests -gt 0 ]; then
        log_warning "$failed_tests tests failed"
        exit 1
    else
        log_success "All tests passed!"
        exit 0
    fi
}

# Allow sourcing for individual function testing
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi