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

const { smartreceive, log_trace } = require('./src/NATSBridge');

// Configuration
const SUBJECT = "/NATSBridge_mix_test";
const NATS_URL = "nats.yiem.cc";

// Helper: Log with correlation ID
function log_trace(message) {
    const timestamp = new Date().toISOString();
    console.log(`[${timestamp}] ${message}`);
}

// Receiver: Listen for messages and verify mixed content handling
async function test_mix_receive() {
    // Connect to NATS
    const { connect } = require('nats');
    const nc = await connect({ servers: [NATS_URL] });
    
    // Subscribe to the subject
    const sub = nc.subscribe(SUBJECT);
    
    for await (const msg of sub) {
        log_trace(`Received message on ${msg.subject}`);
        
        // Use NATSBridge.smartreceive to handle the data
        const result = await smartreceive(
            msg,
            {
                maxRetries: 5,
                baseDelay: 100,
                maxDelay: 5000
            }
        );
        
        log_trace(`Received ${result.payloads.length} payloads`);
        
        // Result is an envelope dictionary with payloads field
        // Access payloads with result.payloads
        for (const { dataname, data, type } of result.payloads) {
            log_trace(`\n=== Payload: ${dataname} (type: ${type}) ===`);
            
            // Handle different data types
            if (type === "text") {
                // Text data - should be a String
                if (typeof data === 'string') {
                    log_trace(`  Type: String`);
                    log_trace(`  Length: ${data.length} characters`);
                    
                    // Display first 200 characters
                    if (data.length > 200) {
                        log_trace(`  First 200 chars: ${data.substring(0, 200)}...`);
                    } else {
                        log_trace(`  Content: ${data}`);
                    }
                    
                    // Save to file
                    const fs = require('fs');
                    const output_path = `./received_${dataname}.txt`;
                    fs.writeFileSync(output_path, data);
                    log_trace(`  Saved to: ${output_path}`);
                } else {
                    log_trace(`  ERROR: Expected String, got ${typeof data}`);
                }
                
            } else if (type === "dictionary") {
                // Dictionary data - should be an object
                if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
                    log_trace(`  Type: Object`);
                    log_trace(`  Keys: ${Object.keys(data).join(', ')}`);
                    
                    // Display nested content
                    for (const [key, value] of Object.entries(data)) {
                        log_trace(`  ${key} => ${value}`);
                    }
                    
                    // Save to JSON file
                    const fs = require('fs');
                    const output_path = `./received_${dataname}.json`;
                    const json_str = JSON.stringify(data, null, 2);
                    fs.writeFileSync(output_path, json_str);
                    log_trace(`  Saved to: ${output_path}`);
                } else {
                    log_trace(`  ERROR: Expected Object, got ${typeof data}`);
                }
                
            } else if (type === "table") {
                // Table data - should be an array of objects (requires apache-arrow)
                log_trace(`  Type: Array (requires apache-arrow for full deserialization)`);
                if (Array.isArray(data)) {
                    log_trace(`  Length: ${data.length} items`);
                    log_trace(`  First item: ${JSON.stringify(data[0])}`);
                } else {
                    log_trace(`  ERROR: Expected Array, got ${typeof data}`);
                }
                
            } else if (type === "image" || type === "audio" || type === "video" || type === "binary") {
                // Binary data - should be Uint8Array
                if (data instanceof Uint8Array || Array.isArray(data)) {
                    log_trace(`  Type: Uint8Array (binary)`);
                    log_trace(`  Size: ${data.length} bytes`);
                    
                    // Save to file
                    const fs = require('fs');
                    const output_path = `./received_${dataname}.bin`;
                    fs.writeFileSync(output_path, Buffer.from(data));
                    log_trace(`  Saved to: ${output_path}`);
                } else {
                    log_trace(`  ERROR: Expected Uint8Array, got ${typeof data}`);
                }
                
            } else {
                log_trace(`  ERROR: Unknown data type '${type}'`);
            }
        }
        
        // Summary
        console.log("\n=== Verification Summary ===");
        const text_count = result.payloads.filter(x => x.type === "text").length;
        const dict_count = result.payloads.filter(x => x.type === "dictionary").length;
        const table_count = result.payloads.filter(x => x.type === "table").length;
        const image_count = result.payloads.filter(x => x.type === "image").length;
        const audio_count = result.payloads.filter(x => x.type === "audio").length;
        const video_count = result.payloads.filter(x => x.type === "video").length;
        const binary_count = result.payloads.filter(x => x.type === "binary").length;
        
        log_trace(`Text payloads: ${text_count}`);
        log_trace(`Dictionary payloads: ${dict_count}`);
        log_trace(`Table payloads: ${table_count}`);
        log_trace(`Image payloads: ${image_count}`);
        log_trace(`Audio payloads: ${audio_count}`);
        log_trace(`Video payloads: ${video_count}`);
        log_trace(`Binary payloads: ${binary_count}`);
        
        // Print transport type info for each payload if available
        console.log("\n=== Payload Details ===");
        for (const { dataname, data, type } of result.payloads) {
            if (["image", "audio", "video", "binary"].includes(type)) {
                log_trace(`${dataname}: ${data.length} bytes (binary)`);
            } else if (type === "table") {
                log_trace(`${dataname}: ${data.length} items (Array)`);
            } else if (type === "dictionary") {
                log_trace(`${dataname}: ${JSON.stringify(data).length} bytes (Object)`);
            } else if (type === "text") {
                log_trace(`${dataname}: ${data.length} characters (String)`);
            }
        }
    }
    
    // Keep listening for 2 minutes
    setTimeout(() => {
        nc.close();
        process.exit(0);
    }, 120000);
}

// Run the test
console.log("Starting mixed-content transport test...");
console.log("Note: This receiver will wait for messages from the sender.");
console.log("Run test_js_to_js_mix_sender.js first to send test data.");

// Run receiver
console.log("\ntesting smartreceive for mixed content");
test_mix_receive();

console.log("\nTest completed.");