#!/bin/bash

# Test script for Dapr PubSub integration with Sekiban

echo "=== Dapr PubSub Integration Test ==="
echo ""

# Check if dapr is installed
if ! command -v dapr &> /dev/null; then
    echo "ERROR: Dapr CLI is not installed. Please install Dapr first."
    exit 1
fi

# API base URL
API_URL="http://localhost:5000"
DAPR_URL="http://localhost:3500"

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

# Function to wait for API to be ready
wait_for_api() {
    echo "Waiting for API to be ready..."
    local max_attempts=30
    local attempt=0
    
    while [ $attempt -lt $max_attempts ]; do
        if curl -s -o /dev/null -w "%{http_code}" "$API_URL/debug/env" | grep -q "200"; then
            echo -e "${GREEN}API is ready!${NC}"
            return 0
        fi
        echo -n "."
        sleep 2
        ((attempt++))
    done
    
    echo -e "${RED}API failed to start within timeout${NC}"
    return 1
}

# Function to create a user
create_user() {
    local user_id=$1
    local name=$2
    
    echo "Creating user: $name (ID: $user_id)"
    
    response=$(curl -s -X POST "$API_URL/api/users/create" \
        -H "Content-Type: application/json" \
        -d "{\"userId\": \"$user_id\", \"name\": \"$name\"}")
    
    if echo "$response" | grep -q '"success":true'; then
        echo -e "${GREEN}✓ User created successfully${NC}"
        echo "Response: $response"
        return 0
    else
        echo -e "${RED}✗ Failed to create user${NC}"
        echo "Response: $response"
        return 1
    fi
}

# Function to update user name
update_user_name() {
    local user_id=$1
    local new_name=$2
    
    echo "Updating user name to: $new_name"
    
    response=$(curl -s -X POST "$API_URL/api/users/$user_id/update-name" \
        -H "Content-Type: application/json" \
        -d "{\"newName\": \"$new_name\"}")
    
    if echo "$response" | grep -q '"success":true'; then
        echo -e "${GREEN}✓ User name updated successfully${NC}"
        echo "Response: $response"
        return 0
    else
        echo -e "${RED}✗ Failed to update user name${NC}"
        echo "Response: $response"
        return 1
    fi
}

# Function to get user details
get_user_details() {
    local user_id=$1
    local wait_for_event=$2
    
    echo "Getting user details (ID: $user_id)"
    
    if [ -n "$wait_for_event" ]; then
        echo "Waiting for event: $wait_for_event"
        response=$(curl -s -X GET "$API_URL/api/users/$user_id/details?waitForSortableUniqueId=$wait_for_event")
    else
        response=$(curl -s -X GET "$API_URL/api/users/$user_id/details")
    fi
    
    if echo "$response" | grep -q '"success":true'; then
        echo -e "${GREEN}✓ User details retrieved successfully${NC}"
        echo "Response: $response"
        return 0
    else
        echo -e "${RED}✗ Failed to get user details${NC}"
        echo "Response: $response"
        return 1
    fi
}

# Function to get user list
get_user_list() {
    local wait_for_event=$1
    
    echo "Getting user list"
    
    if [ -n "$wait_for_event" ]; then
        echo "Waiting for event: $wait_for_event"
        response=$(curl -s -X GET "$API_URL/api/users/list?waitForSortableUniqueId=$wait_for_event")
    else
        response=$(curl -s -X GET "$API_URL/api/users/list")
    fi
    
    if echo "$response" | grep -q '"success":true'; then
        echo -e "${GREEN}✓ User list retrieved successfully${NC}"
        echo "Response: $response"
        return 0
    else
        echo -e "${RED}✗ Failed to get user list${NC}"
        echo "Response: $response"
        return 1
    fi
}

# Function to check Dapr actors
check_dapr_actors() {
    echo "Checking Dapr actors..."
    
    # Get actor metadata
    response=$(curl -s "$DAPR_URL/v1.0/metadata")
    
    if echo "$response" | grep -q "actors"; then
        echo -e "${GREEN}✓ Dapr actors are registered${NC}"
        echo "Metadata: $response" | jq '.actors' 2>/dev/null || echo "$response"
        return 0
    else
        echo -e "${YELLOW}⚠ Could not verify actor registration${NC}"
        return 1
    fi
}

# Function to check PubSub subscriptions
check_pubsub_subscriptions() {
    echo "Checking PubSub subscriptions..."
    
    # Get subscriptions
    response=$(curl -s "$DAPR_URL/v1.0/metadata")
    
    if echo "$response" | grep -q "subscriptions"; then
        echo -e "${GREEN}✓ PubSub subscriptions found${NC}"
        echo "Subscriptions: $response" | jq '.subscriptions' 2>/dev/null || echo "$response"
        return 0
    else
        echo -e "${YELLOW}⚠ Could not verify subscriptions${NC}"
        return 1
    fi
}

# Function to test pubsub flow (from origin/main)
test_pubsub_flow() {
    echo ""
    echo "=== Testing pub/sub flow with dedicated endpoint ==="
    echo "POST $API_URL/api/test/pubsub-flow"
    echo ""
    
    response=$(curl -s -X POST "$API_URL/api/test/pubsub-flow" \
        -H "Content-Type: application/json")
    
    echo "Response:"
    echo "$response" | jq '.' 2>/dev/null || echo "$response"
    echo ""
    
    # Parse response
    if echo "$response" | grep -q '"projectionAvailable":true'; then
        echo -e "${GREEN}✅ SUCCESS! Pub/Sub is working correctly.${NC}"
        echo "   Events are being published and multi-projections are being updated."
    else
        echo -e "${YELLOW}⚠️  WARNING: Pub/Sub might not be working correctly.${NC}"
        echo "   User was created but not found in multi-projections."
        echo ""
        echo "Troubleshooting steps:"
        echo "1. Check if Redis is running: redis-cli ping"
        echo "2. Check Dapr logs for any errors"
        echo "3. Verify EventPubSubController is registered"
        echo "4. Check if multi-projector actors are running"
    fi
}

# Main test flow
main() {
    echo "Starting Dapr PubSub integration test..."
    echo ""
    
    # Wait for API to be ready
    if ! wait_for_api; then
        echo "Exiting due to API not being ready"
        exit 1
    fi
    
    echo ""
    echo "=== Step 1: Check Dapr Components ==="
    check_dapr_actors
    echo ""
    check_pubsub_subscriptions
    echo ""
    
    # Generate test data
    user_id1=$(uuidgen 2>/dev/null || echo "11111111-2222-3333-4444-555555555555")
    user_id2=$(uuidgen 2>/dev/null || echo "66666666-7777-8888-9999-000000000000")
    
    echo ""
    echo "=== Step 2: Create Test Users ==="
    create_user "$user_id1" "Test User 1"
    echo ""
    sleep 2  # Give time for event to propagate
    
    create_user "$user_id2" "Test User 2"
    echo ""
    sleep 2  # Give time for event to propagate
    
    echo ""
    echo "=== Step 3: Verify Projections (Initial) ==="
    get_user_list
    echo ""
    
    echo ""
    echo "=== Step 4: Update User and Test Real-time Projection ==="
    
    # Extract the sortable unique ID from the response for waiting
    update_response=$(curl -s -X POST "$API_URL/api/users/$user_id1/update-name" \
        -H "Content-Type: application/json" \
        -d '{"newName": "Updated User 1"}')
    
    echo "Update response: $update_response"
    
    # Extract version or generate a wait ID
    version=$(echo "$update_response" | grep -o '"version":[0-9]*' | cut -d: -f2)
    
    echo ""
    sleep 2  # Give time for PubSub to propagate
    
    echo ""
    echo "=== Step 5: Verify Projections (After Update) ==="
    get_user_details "$user_id1"
    echo ""
    get_user_list
    echo ""
    
    echo ""
    echo "=== Step 6: Test Multiple Updates (Stress Test) ==="
    for i in {1..3}; do
        echo "Update $i:"
        update_user_name "$user_id1" "Stress Test User $i"
        sleep 1
    done
    
    echo ""
    sleep 3  # Give time for all events to propagate
    
    echo ""
    echo "=== Step 7: Final Verification ==="
    get_user_details "$user_id1"
    echo ""
    get_user_list
    echo ""
    
    # Also test the dedicated pubsub flow endpoint
    test_pubsub_flow
    
    echo ""
    echo "=== Additional checks ==="
    echo ""
    
    # Check if pub/sub component is configured
    echo "Checking Dapr components..."
    dapr components -k pubsub 2>/dev/null || echo "Could not list Dapr components"
    
    echo ""
    echo -e "${GREEN}=== Test Complete ===${NC}"
    echo "The test has verified:"
    echo "1. Events are published to Dapr PubSub when saved"
    echo "2. MultiProjectorActor receives events via PubSub subscription"
    echo "3. Projections are updated in real-time"
    echo "4. Multiple rapid updates are handled correctly"
}

# Run the main test
main