#!/usr/bin/env julia
# Test script for mixed-content message testing
# Tests sending a mix of text, json, table, image, audio, video, and binary data
# from Julia serviceA to Julia serviceB using NATSBridge.jl smartsend
# 
# This test demonstrates that any combination and any number of mixed content
# can be sent and received correctly.

using NATS, JSON, UUIDs, Dates, PrettyPrinting, DataFrames, Arrow, HTTP, Base64

# Include the bridge module
include("../src/NATSBridge.jl")
using .NATSBridge

# Configuration
const SUBJECT = "/NATSBridge_mix_test"
const NATS_URL = "nats.yiem.cc"
const FILESERVER_URL = "http://192.168.88.104:8080"

# Create correlation ID for tracing
correlation_id = string(uuid4())


# ------------------------------------------------------------------------------------------------ #
#                                      test mixed content transfer                                 #
# ------------------------------------------------------------------------------------------------ #


# Helper: Log with correlation ID
function log_trace(message)
    timestamp = Dates.now()
    println("[$timestamp] [Correlation: $correlation_id] $message")
end


# File upload handler for plik server
function plik_upload_handler(fileserver_url::String, dataname::String, data::Vector{UInt8})::Dict{String, Any}
    # Get upload ID
    url_getUploadID = "$fileserver_url/upload"
    headers = ["Content-Type" => "application/json"]
    body = """{ "OneShot" : true }"""
    httpResponse = HTTP.request("POST", url_getUploadID, headers, body; body_is_form=false)
    responseJson = JSON.parse(String(httpResponse.body))
    uploadid = responseJson["id"]
    uploadtoken = responseJson["uploadToken"]
    
    # Upload file
    file_multipart = HTTP.Multipart(dataname, IOBuffer(data), "application/octet-stream")
    url_upload = "$fileserver_url/file/$uploadid"
    headers = ["X-UploadToken" => uploadtoken]
    
    form = HTTP.Form(Dict("file" => file_multipart))
    httpResponse = HTTP.post(url_upload, headers, form)
    responseJson = JSON.parse(String(httpResponse.body))
    
    fileid = responseJson["id"]
    url = "$fileserver_url/file/$uploadid/$fileid/$dataname"
    
    return Dict("status" => httpResponse.status, "uploadid" => uploadid, "fileid" => fileid, "url" => url)
end


# Helper: Create sample data for each type
function create_sample_data()
    # Text data (small - direct transport)
    text_data = "Hello! This is a test chat message. 🎉\nHow are you doing today? 😊"
    
    # Dictionary/JSON data (medium - could be direct or link)
    dict_data = Dict(
        "type" => "chat",
        "sender" => "serviceA",
        "receiver" => "serviceB",
        "metadata" => Dict(
            "timestamp" => string(Dates.now()),
            "priority" => "high",
            "tags" => ["urgent", "chat", "test"]
        ),
        "content" => Dict(
            "text" => "This is a JSON-formatted chat message with nested structure.",
            "format" => "markdown",
            "mentions" => ["user1", "user2"]
        )
    )
    
    # Table data (DataFrame - small - direct transport)
    table_data_small = DataFrame(
        id = 1:10,
        message = ["msg_$i" for i in 1:10],
        sender = ["sender_$i" for i in 1:10],
        timestamp = [string(Dates.now()) for _ in 1:10],
        priority = rand(1:3, 10)
    )
    
    # Table data (DataFrame - large - link transport)
    # ~1.5MB of data (150,000 rows) - should trigger link transport
    table_data_large = DataFrame(
        id = 1:150_000,
        message = ["msg_$i" for i in 1:150_000],
        sender = ["sender_$i" for i in 1:150_000],
        timestamp = [string(Dates.now()) for i in 1:150_000],
        priority = rand(1:3, 150_000)
    )
    
    # Image data (small binary - direct transport)
    # Create a simple 10x10 pixel PNG-like data (128 bytes header + 100 pixels = 112 bytes)
    # Using simple RGB data (10*10*3 = 300 bytes of pixel data)
    image_width = 10
    image_height = 10
    image_data = UInt8[]
    # PNG header (simplified)
    push!(image_data, 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)
    # Simple RGB data (RGBRGBRGB...)
    for i in 1:image_width*image_height
        push!(image_data, 0xFF, 0x00, 0x00)  # Red pixel
    end
    
    # Image data (large - link transport)
    # Create a larger image (~1.5MB) to test link transport
    large_image_width = 500
    large_image_height = 1000
    large_image_data = UInt8[]
    # PNG header (simplified for 500x1000)
    push!(large_image_data, 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)
    # RGB data (500*1000*3 = 1,500,000 bytes)
    for i in 1:large_image_width*large_image_height
        push!(large_image_data, rand(1:255), rand(1:255), rand(1:255))  # Random color pixels
    end
    
    # Audio data (small binary - direct transport)
    audio_data = UInt8[rand(1:255) for _ in 1:100]
    
    # Audio data (large - link transport)
    # ~1.5MB of audio-like data
    large_audio_data = UInt8[rand(1:255) for _ in 1:1_500_000]
    
    # Video data (small binary - direct transport)
    video_data = UInt8[rand(1:255) for _ in 1:150]
    
    # Video data (large - link transport)
    # ~1.5MB of video-like data
    large_video_data = UInt8[rand(1:255) for _ in 1:1_500_000]
    
    # Binary data (small - direct transport)
    binary_data = UInt8[rand(1:255) for _ in 1:200]
    
    # Binary data (large - link transport)
    # ~1.5MB of binary data
    large_binary_data = UInt8[rand(1:255) for _ in 1:1_500_000]
    
    return (
        text_data,
        dict_data,
        table_data_small,
        table_data_large,
        image_data,
        large_image_data,
        audio_data,
        large_audio_data,
        video_data,
        large_video_data,
        binary_data,
        large_binary_data
    )
end


# Sender: Send mixed content via smartsend
function test_mix_send()
    # Create sample data
    (text_data, dict_data, table_data_small, table_data_large, image_data, large_image_data, audio_data, large_audio_data, video_data, large_video_data, binary_data, large_binary_data) = create_sample_data()
    
    # Create payloads list - mixed content with both small and large data
    # Small data uses direct transport, large data uses link transport
    payloads = [
        # Small data (direct transport) - text, dictionary, small table
        ("chat_text", text_data, "text"),
        ("chat_json", dict_data, "dictionary"),
        ("chat_table_small", table_data_small, "table"),
        
        # Large data (link transport) - large table, large image, large audio, large video, large binary
        ("chat_table_large", table_data_large, "table"),
        ("user_image_large", large_image_data, "image"),
        ("audio_clip_large", large_audio_data, "audio"),
        ("video_clip_large", large_video_data, "video"),
        ("binary_file_large", large_binary_data, "binary")
    ]
    
    # Use smartsend with mixed content
    env, env_json_str = NATSBridge.smartsend(
        SUBJECT,
        payloads;  # List of (dataname, data, type) tuples
        broker_url = NATS_URL,
        fileserver_url = FILESERVER_URL,
        fileserver_upload_handler = plik_upload_handler,
        size_threshold = 1_000_000,  # 1MB threshold
        correlation_id = correlation_id,
        msg_purpose = "chat",
        sender_name = "mix_sender",
        receiver_name = "",
        receiver_id = "",
        reply_to = "",
        reply_to_msg_id = "",
        is_publish = true  # Publish the message to NATS
    )
    
    log_trace("Sent message with $(length(env.payloads)) payloads")
    
    # Log transport type for each payload
    for (i, payload) in enumerate(env.payloads)
        log_trace("Payload $i ('$payload.dataname'):")
        log_trace("  Transport: $(payload.transport)")
        log_trace("  Type: $(payload.payload_type)")
        log_trace("  Size: $(payload.size) bytes")
        log_trace("  Encoding: $(payload.encoding)")
        
        if payload.transport == "link"
            log_trace("  URL: $(payload.data)")
        end
    end
    
    # Summary
    println("\n--- Transport Summary ---")
    direct_count = count(p -> p.transport == "direct", env.payloads)
    link_count = count(p -> p.transport == "link", env.payloads)
    log_trace("Direct transport: $direct_count payloads")
    log_trace("Link transport: $link_count payloads")
end


# Run the test
println("Starting mixed-content transport test...")
println("Correlation ID: $correlation_id")

# Run sender
println("start smartsend for mixed content")
test_mix_send()

println("\nTest completed.")
println("Note: Run test_julia_to_julia_mix_receiver.jl to receive the messages.")