#![cfg(feature = "wasm-backend")]
/*!
 * WASM String Constants Test - Validates Issue #65 implementation
 *
 * Tests string constant support in WASM backend:
 * - ConstValue::String handling in generate_const
 * - Data segment generation for string literals
 * - StringBox creation with proper layout
 * - WAT generation includes data segments and string allocation
 */

use nyash_rust::backend::wasm::WasmBackend;
use nyash_rust::mir::{
    BasicBlock, BasicBlockId, ConstValue, EffectMask, FunctionSignature, MirFunction,
    MirInstruction, MirModule, MirType, ValueId,
};

#[test]
fn test_wasm_string_constant_basic() {
    // Build MIR equivalent to:
    // function main() {
    //     %str = const "Hello, WASM!"
    //     return %str  // Should return StringBox pointer
    // }

    let mut backend = WasmBackend::new();
    let mir_module = build_string_const_mir_module();

    // Generate WAT text for debugging
    let wat_result = backend.compile_to_wat(mir_module.clone());
    assert!(
        wat_result.is_ok(),
        "WAT generation should succeed for string constants"
    );

    let wat_text = wat_result.unwrap();

    // Verify WAT contains expected elements for string support
    assert!(
        wat_text.contains("(module"),
        "Should contain module declaration"
    );
    assert!(
        wat_text.contains("memory"),
        "Should contain memory declaration"
    );
    assert!(
        wat_text.contains("data"),
        "Should contain data segment for string literal"
    );
    assert!(
        wat_text.contains("\\48\\65\\6c\\6c\\6f"),
        "Should contain UTF-8 bytes for 'Hello'"
    );
    assert!(
        wat_text.contains("$alloc_stringbox"),
        "Should contain StringBox allocator"
    );
    assert!(
        wat_text.contains("print_str"),
        "Should contain print_str import"
    );

    // Verify string literal is properly embedded
    // (The assertion for UTF-8 bytes is above)

    // Compile to WASM binary
    let wasm_result = backend.compile_module(mir_module);
    if let Err(e) = &wasm_result {
        println!("WASM compilation error: {}", e);
        println!("Generated WAT:\n{}", wat_text);
    }
    assert!(
        wasm_result.is_ok(),
        "WASM compilation should succeed for string constants"
    );
}

#[test]
fn test_wasm_string_constant_multiple() {
    // Test multiple string constants to verify data segment management
    // function main() {
    //     %str1 = const "First"
    //     %str2 = const "Second"
    //     %str3 = const "First"   // Duplicate should reuse data segment
    //     return %str1
    // }

    let mut backend = WasmBackend::new();
    let mir_module = build_multiple_string_const_mir_module();

    let wat_result = backend.compile_to_wat(mir_module.clone());
    assert!(
        wat_result.is_ok(),
        "WAT generation should succeed for multiple strings"
    );

    let wat_text = wat_result.unwrap();

    // Should contain both unique strings (in hex format)
    assert!(
        wat_text.contains("\\46\\69\\72\\73\\74"),
        "Should contain 'First' string in hex"
    );
    assert!(
        wat_text.contains("\\53\\65\\63\\6f\\6e\\64"),
        "Should contain 'Second' string in hex"
    );

    // Should have 2 data segments (First and Second, duplicate First reused)
    let data_count = wat_text.matches("(data").count();
    assert_eq!(
        data_count, 2,
        "Should have exactly 2 data segments for 2 unique strings"
    );

    let wasm_result = backend.compile_module(mir_module);
    assert!(
        wasm_result.is_ok(),
        "WASM compilation should succeed for multiple strings"
    );
}

/// Build a MIR module with a single string constant
fn build_string_const_mir_module() -> MirModule {
    let mut module = MirModule::new("test_string_const".to_string());

    // Create main function signature
    let main_signature = FunctionSignature {
        name: "main".to_string(),
        params: vec![],
        return_type: MirType::Integer, // StringBox pointer as i32
        effects: EffectMask::PURE,
    };

    // Create basic block
    let entry_block = BasicBlockId::new(0);
    let mut main_function = MirFunction::new(main_signature, entry_block);
    let mut block = BasicBlock::new(entry_block);

    // %str = const "Hello, WASM!"
    let str_value = ValueId::new(0);
    block.instructions.push(MirInstruction::Const {
        dst: str_value,
        value: ConstValue::String("Hello, WASM!".to_string()),
    });

    // return %str
    block.set_terminator(MirInstruction::Return {
        value: Some(str_value),
    });

    main_function.blocks.insert(entry_block, block);

    module.functions.insert("main".to_string(), main_function);
    module
}

/// Build a MIR module with multiple string constants
fn build_multiple_string_const_mir_module() -> MirModule {
    let mut module = MirModule::new("test_multiple_strings".to_string());

    let main_signature = FunctionSignature {
        name: "main".to_string(),
        params: vec![],
        return_type: MirType::Integer,
        effects: EffectMask::PURE,
    };

    let entry_block = BasicBlockId::new(0);
    let mut main_function = MirFunction::new(main_signature, entry_block);
    let mut block = BasicBlock::new(entry_block);

    // %str1 = const "First"
    let str1_value = ValueId::new(0);
    block.instructions.push(MirInstruction::Const {
        dst: str1_value,
        value: ConstValue::String("First".to_string()),
    });

    // %str2 = const "Second"
    let str2_value = ValueId::new(1);
    block.instructions.push(MirInstruction::Const {
        dst: str2_value,
        value: ConstValue::String("Second".to_string()),
    });

    // %str3 = const "First" (duplicate)
    let str3_value = ValueId::new(2);
    block.instructions.push(MirInstruction::Const {
        dst: str3_value,
        value: ConstValue::String("First".to_string()),
    });

    // return %str1
    block.set_terminator(MirInstruction::Return {
        value: Some(str1_value),
    });

    main_function.blocks.insert(entry_block, block);

    module.functions.insert("main".to_string(), main_function);
    module
}
