//! LLVM harness executor (native executable generation and execution)
//!
//! Handles execution via LLVM harness when available (feature-gated).

use nyash_rust::mir::MirModule;
use super::error::LlvmRunError;

/// Harness executor Box
///
/// **Responsibility**: Execute via LLVM harness (native executable generation and execution)
/// **Input**: &MirModule
/// **Output**: Result<i32, LlvmRunError> (Ok(exit_code) if executed, Err if failed)
pub struct HarnessExecutorBox;

impl HarnessExecutorBox {
    /// Execute via LLVM harness if available
    ///
    /// This function:
    /// 1. Generates a native executable via ny-llvmc
    /// 2. Executes the generated executable
    /// 3. Returns the exit code
    ///
    /// Returns Ok(exit_code) on success, Err(LlvmRunError) on failure.
    #[cfg(feature = "llvm-harness")]
    pub fn try_execute(module: &MirModule) -> Result<i32, LlvmRunError> {
        eprintln!("🎯 [DEBUG] llvm-harness feature IS ENABLED at compile time");
        let harness_enabled = crate::config::env::llvm_use_harness();
        eprintln!("🎯 [DEBUG] llvm_use_harness() = {}", harness_enabled);
        eprintln!("🎯 [DEBUG] NYASH_LLVM_USE_HARNESS env var = {:?}", std::env::var("NYASH_LLVM_USE_HARNESS"));
        if !harness_enabled {
            return Err(LlvmRunError::fatal("LLVM harness not enabled (NYASH_LLVM_USE_HARNESS not set)"));
        }

        // Prefer producing a native executable via ny-llvmc, then execute it
        let exe_out = "tmp/nyash_llvm_run";
        let libs = std::env::var("NYASH_LLVM_EXE_LIBS").ok();

        crate::runner::modes::common_util::exec::ny_llvmc_emit_exe_lib(
            module,
            exe_out,
            None,
            libs.as_deref(),
        ).map_err(|e| LlvmRunError::fatal(format!("ny-llvmc emit-exe error: {} (Hint: build ny-llvmc: cargo build -p nyash-llvm-compiler --release)", e)))?;

        match crate::runner::modes::common_util::exec::run_executable(
            exe_out,
            &[],
            20_000,
        ) {
            Ok((code, _timed_out, stdout_text)) => {
                // Forward program stdout so parity tests can compare outputs
                if !stdout_text.is_empty() {
                    print!("{}", stdout_text);
                }
                crate::console_println!(
                    "✅ LLVM (harness) execution completed (exit={})",
                    code
                );
                Ok(code)
            }
            Err(e) => {
                Err(LlvmRunError::fatal(format!("run executable error: {}", e)))
            }
        }
    }

    #[cfg(not(feature = "llvm-harness"))]
    pub fn try_execute(_module: &MirModule) -> Result<i32, LlvmRunError> {
        eprintln!("❌ [DEBUG] llvm-harness feature IS NOT ENABLED at compile time");
        eprintln!("❌ [DEBUG] You need to rebuild with: cargo build --release --features llvm");
        Err(LlvmRunError::fatal("LLVM harness feature not enabled (built without --features llvm)"))
    }
}
