//! 项目编译器
//!
//! 协调多模块项目的编译流程：
//! 1. 发现项目结构和入口
//! 2. 构建依赖图
//! 3. 按拓扑顺序编译所有模块为 .obj
//! 4. 为每个入口生成独立的可执行文件（内嵌 loader）
//!
//! 输出目录：target/tsn-release/

use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::time::Instant;
use anyhow::{Result, bail};

use crate::codegen::CodeGen;
use crate::dep_graph::DepGraph;
use crate::project::Project;
use crate::standalone_gen::{parse_coff_to_module_data};
use crate::tsn_diag_project;

/// 对齐到指定边界
fn align_up(value: usize, alignment: usize) -> usize {
    (value + alignment - 1) & !(alignment - 1)
}
use crate::swc_transform::parse;

/// 编译阶段计时与内存跟踪
#[derive(Debug, Clone)]
pub struct CompilePhase {
    pub name: String,
    pub start: Instant,
    pub duration_ms: u64,
    /// 阶段结束时的估算内存使用（字节）
    pub memory_bytes: u64,
}

impl CompilePhase {
    pub fn new(name: &str) -> Self {
        Self {
            name: name.to_string(),
            start: Instant::now(),
            duration_ms: 0,
            memory_bytes: 0,
        }
    }

    pub fn finish(&mut self) -> u64 {
        self.duration_ms = self.start.elapsed().as_millis() as u64;
        self.memory_bytes = estimate_memory_usage();
        self.duration_ms
    }
}

/// 估算当前进程的内存使用量（字节）
///
/// 使用平台特定 API 获取 RSS（Resident Set Size）。
/// Windows 上使用 GetProcessMemoryInfo，其他平台使用 /proc 或默认估算。
fn estimate_memory_usage() -> u64 {
    #[cfg(target_os = "windows")]
    {
        use std::mem;
        #[repr(C)]
        struct ProcessMemoryCounters {
            cb: u32,
            page_fault_count: u32,
            peak_working_set_size: usize,
            working_set_size: usize,
            quota_peak_paged_pool_usage: usize,
            quota_paged_pool_usage: usize,
            quota_peak_non_paged_pool_usage: usize,
            quota_non_paged_pool_usage: usize,
            pagefile_usage: usize,
            peak_pagefile_usage: usize,
        }

        #[link(name = "psapi")]
        extern "system" {
            fn GetCurrentProcess() -> *mut std::ffi::c_void;
            fn GetProcessMemoryInfo(
                process: *mut std::ffi::c_void,
                pmc: *mut ProcessMemoryCounters,
                cb: u32,
            ) -> i32;
        }

        unsafe {
            let mut pmc = ProcessMemoryCounters {
                cb: mem::size_of::<ProcessMemoryCounters>() as u32,
                ..mem::zeroed()
            };
            let result = GetProcessMemoryInfo(
                GetCurrentProcess(),
                &mut pmc,
                pmc.cb,
            );
            if result != 0 {
                pmc.working_set_size as u64
            } else {
                0
            }
        }
    }

    #[cfg(not(target_os = "windows"))]
    {
        // 非 Windows 平台：尝试读取 /proc/self/status
        if let Ok(status) = std::fs::read_to_string("/proc/self/status") {
            for line in status.lines() {
                if line.starts_with("VmRSS:") {
                    let parts: Vec<&str> = line.split_whitespace().collect();
                    if parts.len() >= 2 {
                        if let Ok(kb) = parts[1].parse::<u64>() {
                            return kb * 1024;
                        }
                    }
                }
            }
        }
        0
    }
}

/// 格式化字节数为人类可读字符串
fn format_bytes(bytes: u64) -> String {
    const KB: u64 = 1024;
    const MB: u64 = 1024 * KB;
    const GB: u64 = 1024 * MB;
    if bytes >= GB {
        format!("{:.1} GB", bytes as f64 / GB as f64)
    } else if bytes >= MB {
        format!("{:.1} MB", bytes as f64 / MB as f64)
    } else if bytes >= KB {
        format!("{:.0} KB", bytes as f64 / KB as f64)
    } else {
        format!("{} B", bytes)
    }
}

/// 编译报告
#[derive(Debug, Clone)]
pub struct CompileReport {
    pub project_name: String,
    pub total_modules: usize,
    pub total_entries: usize,
    pub phases: Vec<CompilePhase>,
    pub module_results: Vec<ModuleCompileResult>,
    pub entry_results: Vec<EntryCompileResult>,
    pub total_duration_ms: u64,
    /// 代码覆盖率：已编译函数数 / 总声明函数数
    pub functions_compiled: usize,
    pub functions_total: usize,
    /// 总代码段大小（字节）
    pub total_code_size: usize,
    /// 总数据段大小（字节）
    pub total_data_size: usize,
    /// 总符号数
    pub total_symbols: usize,
    /// 总重定位数
    pub total_relocations: usize,
    /// 总 rdata 段大小
    pub total_rdata_size: usize,
    /// 编译警告数
    pub warnings: Vec<String>,
    /// 编译错误数
    pub errors: usize,
    /// 各模块 shim 使用统计
    pub shim_usage: HashMap<String, usize>,
    /// 各模块 node_modules 使用统计
    pub npm_packages_used: Vec<String>,
}

/// 单个模块编译结果
#[derive(Debug, Clone)]
pub struct ModuleCompileResult {
    pub module_name: String,
    pub module_path: PathBuf,
    pub code_size: usize,
    pub data_size: usize,
    pub rdata_size: usize,
    pub symbol_count: usize,
    pub reloc_count: usize,
    pub duration_ms: u64,
    /// 解析阶段耗时（毫秒）
    pub parse_ms: u64,
    /// 代码生成阶段耗时（毫秒）
    pub codegen_ms: u64,
    pub success: bool,
    pub error: Option<String>,
    /// 模块中声明的函数总数
    pub functions_declared: usize,
    /// 模块中成功编译的函数数
    pub functions_compiled: usize,
}

/// 单个入口编译结果
#[derive(Debug, Clone)]
pub struct EntryCompileResult {
    pub entry_name: String,
    pub entry_path: PathBuf,
    pub closure_size: usize,
    pub exe_path: Option<PathBuf>,
    pub duration_ms: u64,
    pub success: bool,
    pub error: Option<String>,
}

/// 项目编译器
pub struct ProjectCompiler {
    /// 项目
    project: Project,
    /// 依赖图
    dep_graph: DepGraph,
    /// 编译后的对象文件（模块路径 -> .obj 字节）
    compiled_objects: HashMap<PathBuf, Vec<u8>>,
    /// 全局模块符号表（函数名 -> 定义模块路径）
    module_symbols: HashMap<String, String>,
    /// 跨模块 const export 值：导出名 -> HirExpr 字面值
    const_values: HashMap<String, crate::codegen::HirExpr>,
    /// 编译报告
    report: CompileReport,
    /// 输出目录
    output_dir: PathBuf,
}

impl ProjectCompiler {
    /// 从目录创建项目编译器
    pub fn from_dir(root: &Path) -> Result<Self> {
        let output_dir = root.canonicalize()
            .unwrap_or_else(|_| root.to_path_buf())
            .join("target")
            .join("tsn-release");
        Self::from_dir_with_output(root, &output_dir)
    }
    
    /// 从目录创建项目编译器（指定输出目录）
    pub fn from_dir_with_output(root: &Path, output_dir: &Path) -> Result<Self> {
        let mut project = Project::from_dir(root)?;
        let dep_graph = DepGraph::from_project(&mut project)?;

        // 构建全局模块符号表
        let mut module_symbols = HashMap::new();
        for (path, node) in &dep_graph.nodes {
            for export in &node.exports {
                module_symbols.insert(export.clone(), path.to_string_lossy().to_string());
            }
        }

        std::fs::create_dir_all(output_dir)?;

        let report = CompileReport {
            project_name: root.file_name()
                .map(|n| n.to_string_lossy().to_string())
                .unwrap_or_else(|| "unknown".to_string()),
            total_modules: dep_graph.compile_order.len(),
            total_entries: project.entries.len(),
            phases: Vec::new(),
            module_results: Vec::new(),
            entry_results: Vec::new(),
            total_duration_ms: 0,
            functions_compiled: 0,
            functions_total: 0,
            total_code_size: 0,
            total_data_size: 0,
            total_symbols: 0,
            total_relocations: 0,
            total_rdata_size: 0,
            warnings: Vec::new(),
            errors: 0,
            shim_usage: HashMap::new(),
            npm_packages_used: Vec::new(),
        };

        Ok(ProjectCompiler {
            project,
            dep_graph,
            compiled_objects: HashMap::new(),
            module_symbols,
            const_values: HashMap::new(),
            report,
            output_dir: output_dir.to_path_buf(),
        })
    }

    /// 编译整个项目
    pub fn compile_project(&mut self) -> Result<&CompileReport> {
        let total_start = Instant::now();

        println!("========================================");
        println!("ts-native Project Compiler");
        println!("========================================");
        println!("Project: {}", self.report.project_name);
        println!("Modules: {}", self.report.total_modules);
        println!("Entries: {}", self.report.total_entries);
        println!("Output:  {}", self.output_dir.display());
        println!("========================================");
        println!();

        // 第一步：按拓扑顺序编译所有模块
        let mut phase = CompilePhase::new("Module Compilation");
        println!("[Phase 1/3] Compiling modules...");

        let compile_order = self.dep_graph.get_compile_order().to_vec();

        // 预解析所有模块的 const export 值
        for path in &compile_order {
            if let Ok(content) = self.project.load_content(path) {
                if let Ok(hir) = parse(&content) {
                    let mut exported_names: HashSet<String> = HashSet::new();
                    // 收集顶层 Export 节点
                    Self::collect_exports(&hir, &mut exported_names);
                    // 搜索 Var 节点（可能在顶层，也可能在 Function 体内）
                    Self::collect_const_vars(&hir, &exported_names, &mut self.const_values);
                }
            }
        }

        for (i, path) in compile_order.iter().enumerate() {
            let module_name = self.project.files.get(path)
                .map(|f| f.module_name.clone())
                .unwrap_or_else(|| path.file_stem().unwrap_or_default().to_string_lossy().to_string());

            print!("  [{}/{}] Compiling {} ... ", i + 1, compile_order.len(), module_name);
            match self.compile_module(path) {
                Ok(_) => println!("OK"),
                Err(e) => {
                    println!("FAILED: {}", e);
                    bail!("Module compilation failed for {}: {}", module_name, e);
                }
            }
        }
        phase.finish();
        println!("  -> {} modules compiled in {}ms", compile_order.len(), phase.duration_ms);
        println!();
        self.report.phases.push(phase);

        // 第二步：为每个入口生成独立可执行文件
        let mut phase = CompilePhase::new("Executable Generation");
        println!("[Phase 2/3] Generating standalone executables...");

        let entries = self.project.entries.clone();
        for (i, entry_path) in entries.iter().enumerate() {
            let entry_name = entry_path.file_stem()
                .map(|s| s.to_string_lossy().to_string())
                .unwrap_or_else(|| "main".to_string());

            print!("  [{}/{}] Building {}.exe ... ", i + 1, entries.len(), entry_name);
            match self.build_standalone_executable(entry_path) {
                Ok(exe_path) => {
                    println!("OK -> {}", exe_path.display());
                }
                Err(e) => {
                    println!("FAILED: {}", e);
                    // 继续处理其他入口
                }
            }
        }
        phase.finish();
        println!("  -> {} executables generated in {}ms", entries.len(), phase.duration_ms);
        println!();
        self.report.phases.push(phase);

        // 第三步：生成编译报告
        let mut phase = CompilePhase::new("Report Generation");

        // 汇总统计数据
        self.report.functions_compiled = self.report.module_results.iter()
            .map(|m| m.functions_compiled).sum();
        self.report.functions_total = self.report.module_results.iter()
            .map(|m| m.functions_declared).sum();
        self.report.total_code_size = self.report.module_results.iter()
            .map(|m| m.code_size).sum();
        self.report.total_data_size = self.report.module_results.iter()
            .map(|m| m.data_size).sum();
        self.report.total_rdata_size = self.report.module_results.iter()
            .map(|m| m.rdata_size).sum();
        self.report.total_symbols = self.report.module_results.iter()
            .map(|m| m.symbol_count).sum();
        self.report.total_relocations = self.report.module_results.iter()
            .map(|m| m.reloc_count).sum();
        self.report.errors = self.report.module_results.iter()
            .filter(|m| !m.success).count();

        self.report.total_duration_ms = total_start.elapsed().as_millis() as u64;
        phase.finish();
        self.report.phases.push(phase);

        self.print_report();

        Ok(&self.report)
    }

    /// 递归收集 HIR 中的 Export 节点名
    fn collect_exports(hir: &[crate::codegen::HirExpr], exported_names: &mut HashSet<String>) {
        for expr in hir {
            if let crate::codegen::HirExpr::Export { exported, module, .. } = expr {
                if module.is_empty() {
                    exported_names.insert(exported.clone());
                }
            }
            // 递归搜索 Function/AsyncFunction/Block 体内的 Export
            match expr {
                crate::codegen::HirExpr::Function { body, .. }
                | crate::codegen::HirExpr::AsyncFunction { body, .. } => {
                    Self::collect_exports(body, exported_names);
                }
                _ => {}
            }
        }
    }

    /// 递归搜索 HIR 中的 const Var 节点，与 exported_names 匹配后加入 const_values
    fn collect_const_vars(
        hir: &[crate::codegen::HirExpr],
        exported_names: &HashSet<String>,
        const_values: &mut HashMap<String, crate::codegen::HirExpr>,
    ) {
        for expr in hir {
            if let crate::codegen::HirExpr::Var { name, init, is_mut: _ } = expr {
                if exported_names.contains(name) {
                    if let Some(init_expr) = init {
                        match init_expr.as_ref() {
                            crate::codegen::HirExpr::Number(_)
                            | crate::codegen::HirExpr::String(_)
                            | crate::codegen::HirExpr::Boolean(_)
                            | crate::codegen::HirExpr::Null
                            | crate::codegen::HirExpr::Undefined => {
                                const_values.insert(name.clone(), (**init_expr).clone());
                            }
                            _ => {}
                        }
                    }
                }
            }
            // 递归搜索 Function/AsyncFunction/Block 体内的 Var
            match expr {
                crate::codegen::HirExpr::Function { body, .. }
                | crate::codegen::HirExpr::AsyncFunction { body, .. } => {
                    Self::collect_const_vars(body, exported_names, const_values);
                }
                _ => {}
            }
        }
    }

    /// 编译单个模块为 COFF .obj
    pub fn compile_module(&mut self, path: &Path) -> Result<Vec<u8>> {
        let module_start = Instant::now();
        let content = self.project.load_content(path)?;
        
        let parse_start = Instant::now();
        let mut hir = parse(&content)?;
        let parse_ms = parse_start.elapsed().as_millis() as u64;

        let mut codegen = CodeGen::new();

        // 设置模块符号表（排除本模块的符号）
        let mut module_symbols = self.module_symbols.clone();
        if let Some(node) = self.dep_graph.nodes.get(path) {
            for export in &node.exports {
                module_symbols.remove(export);
            }
        }
        codegen.set_module_symbols(module_symbols);
        codegen.set_const_values(self.const_values.clone());

        // 传入 native addon 配置（用于 FFI 桥接）
        if !self.project.config.native_addons.is_empty() {
            codegen.set_native_addons(self.project.config.native_addons.clone());
        }

        // 传入 QuickJS fallback 包列表（用于运行时 JS 引擎执行）
        if self.project.config.js_engine.enabled && !self.project.config.js_engine.fallback.is_empty() {
            codegen.set_qjs_fallback(self.project.config.js_engine.fallback.clone());
        }

        let codegen_start = Instant::now();
        let obj_bytes = codegen.compile_coff(&mut hir)?;
        let codegen_ms = codegen_start.elapsed().as_millis() as u64;

        // 统计函数覆盖率
        let functions_declared = hir.iter()
            .filter(|e| matches!(e, crate::codegen::HirExpr::Function { .. }))
            .count();
        let functions_compiled = codegen.get_compiled_function_count();

        // 收集编译统计
        let module_data = parse_coff_to_module_data(&obj_bytes).ok();
        let result = ModuleCompileResult {
            module_name: self.project.files.get(path)
                .map(|f| f.module_name.clone())
                .unwrap_or_default(),
            module_path: path.to_path_buf(),
            code_size: module_data.as_ref().map(|m| m.code.len()).unwrap_or(0),
            data_size: module_data.as_ref().map(|m| m.data.len()).unwrap_or(0),
            rdata_size: module_data.as_ref().map(|m| m.rdata.len()).unwrap_or(0),
            symbol_count: module_data.as_ref().map(|m| m.symbols.len()).unwrap_or(0),
            reloc_count: module_data.as_ref().map(|m| m.relocations.len()).unwrap_or(0),
            duration_ms: module_start.elapsed().as_millis() as u64,
            parse_ms,
            codegen_ms,
            success: true,
            error: None,
            functions_declared,
            functions_compiled,
        };
        self.report.module_results.push(result);

        self.compiled_objects.insert(path.to_path_buf(), obj_bytes.clone());

        Ok(obj_bytes)
    }

    /// 为入口生成独立可执行文件（预编译 loader + .tsnobj 方案）
    fn build_standalone_executable(&mut self, entry_path: &Path) -> Result<PathBuf> {
        let build_start = Instant::now();
        let entry_name = entry_path.file_stem()
            .map(|s| s.to_string_lossy().to_string())
            .unwrap_or_else(|| "main".to_string());
        tsn_diag_project!("build_standalone_executable: entry={}, output_dir={}", entry_name, self.output_dir.display());

        // 收集入口闭包中的所有 .obj 文件
        let closure = self.dep_graph.get_entry_modules(entry_path);

        // 合并所有对象文件为一个模块数据
        let mut merged_module = crate::standalone_gen::ModuleData {
            code: Vec::new(),
            data: Vec::new(),
            rdata: Vec::new(),
            symbols: Vec::new(),
            relocations: Vec::new(),
            addon_dlls: Vec::new(),
        };

        // 按编译顺序合并（确保依赖在前，入口在后）
        let compile_order = self.dep_graph.get_compile_order();
        let mut merged_paths: Vec<PathBuf> = Vec::new();
        for path in compile_order {
            if closure.contains(path) {
                merged_paths.push(path.clone());
            }
        }

        // 确保入口文件在最后
        if let Some(pos) = merged_paths.iter().position(|p| p == entry_path) {
            let entry = merged_paths.remove(pos);
            merged_paths.push(entry);
        }

        // 通用符号命名空间：基于模块 ID 的全局唯一前缀
        const ALIGNMENT: usize = 16;

        // 第一阶段：收集所有模块的原始符号和重命名映射（使用 dep_graph 的 export_map）
        let mut module_renames: HashMap<PathBuf, HashMap<String, String>> = HashMap::new();
        let mut all_original_symbols: HashMap<String, PathBuf> = HashMap::new();

        for path in &merged_paths {
            let is_entry = path == entry_path;
            if let Some(obj_bytes) = self.compiled_objects.get(path) {
                if let Ok(module_data) = parse_coff_to_module_data(obj_bytes) {
                    let mut local_rename: HashMap<String, String> = HashMap::new();

                    if !is_entry {
                        // 使用 dep_graph 的 export_map 获取 mod_{id}_{name} 映射
                        if let Some(export_map) = self.dep_graph.export_map.get(path) {
                            for sym in &module_data.symbols {
                                if sym.name.starts_with("js_") || sym.name.starts_with("__") {
                                    continue;
                                }
                                // 只重命名已定义的符号（section != 0xFF Undefined, 0xFE Absolute）
                                if sym.section != 0xFF && sym.section != 0xFE {
                                    // 优先使用 export_map 中的映射（唯一符号名）
                                    // 对未在 export_map 中的内部符号也加前缀避免跨模块碰撞
                                    let new_name = export_map.get(&sym.name)
                                        .cloned()
                                        .unwrap_or_else(|| {
                                            let fallback_prefix = format!("m{}_", self.dep_graph.module_id_map.get(path).unwrap_or(&0));
                                            format!("{}{}", fallback_prefix, sym.name)
                                        });
                                    local_rename.insert(sym.name.clone(), new_name);
                                    all_original_symbols.insert(sym.name.clone(), path.clone());
                                }
                            }
                        }
                    }

                    module_renames.insert(path.clone(), local_rename);
                }
            }
        }

        // 第二阶段：合并模块数据（应用重命名）
        for path in &merged_paths {
            let _is_entry = path == entry_path;
            let local_rename = module_renames.get(path).cloned().unwrap_or_default();

            if let Some(obj_bytes) = self.compiled_objects.get(path) {
                match parse_coff_to_module_data(obj_bytes) {
                    Ok(module_data) => {
                        // 节区对齐
                        let code_offset = align_up(merged_module.code.len(), ALIGNMENT) as u32;
                        let data_offset = align_up(merged_module.data.len(), ALIGNMENT) as u32;
                        let rdata_offset = align_up(merged_module.rdata.len(), ALIGNMENT) as u32;

                        while merged_module.code.len() < code_offset as usize {
                            merged_module.code.push(0);
                        }
                        while merged_module.data.len() < data_offset as usize {
                            merged_module.data.push(0);
                        }
                        while merged_module.rdata.len() < rdata_offset as usize {
                            merged_module.rdata.push(0);
                        }

                        // 复制节区数据
                        merged_module.code.extend_from_slice(&module_data.code);
                        merged_module.data.extend_from_slice(&module_data.data);
                        merged_module.rdata.extend_from_slice(&module_data.rdata);

                        // 添加符号（应用重命名）
                        for sym in &module_data.symbols {
                            let adjusted_offset = match sym.section {
                                0 => sym.offset + code_offset,
                                1 => sym.offset + data_offset,
                                2 => sym.offset + rdata_offset,
                                _ => sym.offset,
                            };
                            let final_name = local_rename.get(&sym.name).cloned()
                                .unwrap_or_else(|| sym.name.clone());
                            merged_module.symbols.push(crate::standalone_gen::ModuleSymbol {
                                section: sym.section,
                                offset: adjusted_offset,
                                name: final_name,
                            });
                        }

                        // 添加重定位（应用重命名，包括跨模块调用）
                        for reloc in &module_data.relocations {
                            let adjusted_offset = match reloc.section {
                                0 => reloc.offset + code_offset,
                                1 => reloc.offset + data_offset,
                                2 => reloc.offset + rdata_offset,
                                _ => reloc.offset,
                            };

                            // 解析重定位目标
                            let final_target = if reloc.target_name.starts_with("js_") || reloc.target_name.starts_with("__") {
                                // 外部符号，保持不变
                                reloc.target_name.clone()
                            } else if let Some(renamed) = local_rename.get(&reloc.target_name) {
                                // 本模块符号被重命名
                                renamed.clone()
                            } else {
                                // 可能是跨模块调用，查找其他模块的重命名映射
                                let mut cross_module_target = reloc.target_name.clone();
                                for (other_path, other_rename) in &module_renames {
                                    if other_path != path {
                                        if let Some(renamed) = other_rename.get(&reloc.target_name) {
                                            cross_module_target = renamed.clone();
                                            break;
                                        }
                                    }
                                }
                                cross_module_target
                            };

                            merged_module.relocations.push(crate::standalone_gen::ModuleRelocation {
                                section: reloc.section,
                                offset: adjusted_offset,
                                type_: reloc.type_,
                                target_name: final_target,
                            });
                        }
                    }
                    Err(e) => {
                        eprintln!("[WARN] Failed to parse COFF for {}: {}", path.display(), e);
                    }
                }
            }
        }

        // 填充 addon DLLs 列表（从项目配置中收集）
        for addon_config in self.project.config.native_addons.values() {
            if !addon_config.dll.is_empty() {
                merged_module.addon_dlls.push(addon_config.dll.clone());
            }
        }

        // 序列化为 .tsnobj 文件
        let tsnobj_bytes = crate::standalone_gen::serialize_to_tsnobj(&merged_module, &entry_name);
        let tsnobj_path = self.output_dir.join(format!("{}.tsnobj", entry_name));
        // 使用 OpenOptions 创建文件，避免某些 Windows 权限问题
        use std::io::Write;
        #[cfg(windows)]
        use std::os::windows::fs::OpenOptionsExt;
        let mut opts = std::fs::OpenOptions::new();
        opts.write(true).create(true).truncate(true);
        #[cfg(windows)]
        opts.share_mode(0x00000001 | 0x00000002); // FILE_SHARE_READ | FILE_SHARE_WRITE
        let mut f = opts.open(&tsnobj_path)
            .map_err(|e| anyhow::anyhow!("Failed to create {}: {}", tsnobj_path.display(), e))?;
        f.write_all(&tsnobj_bytes)
            .map_err(|e| anyhow::anyhow!("Failed to write {}: {}", tsnobj_path.display(), e))?;
        drop(f);

        // 复制预编译的 loader 并重命名
        let exe_path = self.output_dir.join(format!("{}.exe", entry_name));
        self.copy_prebuilt_loader(&exe_path)
            .map_err(|e| anyhow::anyhow!("Failed to copy loader to {}: {}", exe_path.display(), e))?;

        // 自动复制 tsn_runtime.dll 到输出目录
        self.copy_runtime_dll()?;

        let result = EntryCompileResult {
            entry_name: entry_name.clone(),
            entry_path: entry_path.to_path_buf(),
            closure_size: closure.len(),
            exe_path: Some(exe_path.clone()),
            duration_ms: build_start.elapsed().as_millis() as u64,
            success: true,
            error: None,
        };
        self.report.entry_results.push(result);

        Ok(exe_path)
    }

    /// 复制预编译的 standalone loader 可执行文件
    /// 优先使用缓存的 standalone-loader.exe，否则用 rustc 编译 standalone_loader.rs
    fn copy_prebuilt_loader(&self, dest_path: &Path) -> Result<()> {
        // standalone loader 编译缓存：放在 workspace 根 target 目录下
        let cwd = std::env::current_dir().unwrap_or_default();
        let cache_path = cwd.join("target").join("standalone-loader.exe");

        if cache_path.exists() {
            // 缓存命中，直接复制
            std::fs::copy(&cache_path, dest_path)?;
            return Ok(());
        }

        // 缓存未命中：编译 standalone_loader.rs 并缓存
        let loader_src = self.find_loader_source()
            .ok_or_else(|| anyhow::anyhow!("standalone_loader.rs not found in any parent directory"))?;

        eprintln!("  [INFO] Compiling standalone loader from {}", loader_src.display());

        // 先编译到临时文件
        let tmp_dest = format!("{}.tmp", cache_path.display());
        let output = std::process::Command::new("rustc")
            .args(&[
                "--edition", "2021",
                "-C", "opt-level=2",
                "-o", &tmp_dest,
                loader_src.to_str().unwrap(),
            ])
            .output()
            .map_err(|e| anyhow::anyhow!("Failed to run rustc: {}", e))?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            bail!("standalone loader compilation failed:\n{}", stderr);
        }

        // 重命名临时文件到缓存路径
        std::fs::rename(&tmp_dest, &cache_path)?;

        // 复制到目标路径
        std::fs::copy(&cache_path, dest_path)?;
        Ok(())
    }

    /// 向上搜索 standalone_loader.rs 源文件
    fn find_loader_source(&self) -> Option<PathBuf> {
        let mut dir = self.project.root.clone();
        for _ in 0..10 {
            let candidate = dir.join("src").join("standalone_loader.rs");
            if candidate.exists() {
                return Some(candidate);
            }
            dir = dir.parent()?.to_path_buf();
        }
        None
    }

    /// 自动复制 tsn_runtime.dll 到输出目录
    /// 搜索策略：环境变量 > 配置路径 > 默认位置
    fn copy_runtime_dll(&self) -> Result<()> {
        let target_dll = self.output_dir.join("tsn_runtime.dll");
        
        // 查找源 DLL（按优先级）
        let source_path = self.find_runtime_dll()?;
        
        // 检查是否需要更新
        if !self.needs_update(&source_path, &target_dll)? {
            println!("  [Runtime] {} is up to date", target_dll.display());
            return Ok(());
        }
        
        // 复制 DLL（带重试机制）
        self.copy_with_retry(&source_path, &target_dll, 3)?;
        Ok(())
    }
    
    /// 查找 runtime DLL（优先级：环境变量 > 配置 > 默认）
    fn find_runtime_dll(&self) -> Result<PathBuf> {
        let dll_name = "tsn_runtime.dll";
        
        // 1. 环境变量（最高优先级）
        if let Ok(path) = std::env::var("TSN_RUNTIME_DLL") {
            let p = PathBuf::from(path);
            if p.exists() {
                return Ok(p);
            }
        }
        
        // 2. 从 cargo metadata 获取 runtime target 目录
        let runtime_target = self.get_runtime_target_dir()?;
        for profile in &["debug", "release"] {
            let candidate = runtime_target.join(profile).join(dll_name);
            if candidate.exists() {
                return Ok(candidate);
            }
        }
        
        anyhow::bail!(
            "runtime DLL not found. Set TSN_RUNTIME_DLL environment variable or ensure runtime is compiled (expected at {:?}/{{debug,release}}/{})",
            runtime_target, dll_name
        )
    }
    
    /// 获取 runtime target 目录（从配置或默认值）
    fn get_runtime_target_dir(&self) -> Result<PathBuf> {
        // 1. 环境变量
        if let Ok(path) = std::env::var("TSN_RUNTIME_TARGET") {
            return Ok(PathBuf::from(path));
        }
        
        // 2. 默认值：workspace 根目录/target（runtime 是 workspace 成员，cargo build 输出在此）
        let workspace_root = self.get_workspace_root()?;
        Ok(workspace_root.join("target"))
    }
    
    /// 获取 workspace 根目录
    fn get_workspace_root(&self) -> Result<PathBuf> {
        // 尝试从 cargo metadata 获取
        let output = std::process::Command::new("cargo")
            .args(["metadata", "--format-version=1", "--no-deps"])
            .current_dir(&self.project.root)
            .output();
        
        if let Ok(out) = output {
            if let Ok(json) = serde_json::from_slice::<serde_json::Value>(&out.stdout) {
                if let Some(root) = json.get("workspace_root").and_then(|v| v.as_str()) {
                    return Ok(PathBuf::from(root));
                }
            }
        }
        
        // fallback：项目根目录的父目录
        Ok(self.project.root.parent()
            .map(|p| p.to_path_buf())
            .unwrap_or_else(|| self.project.root.clone()))
    }
    
    /// 检查是否需要更新目标文件
    fn needs_update(&self, source: &PathBuf, target: &PathBuf) -> Result<bool> {
        if !target.exists() {
            return Ok(true);
        }
        
        let src_meta = std::fs::metadata(source)?;
        let tgt_meta = std::fs::metadata(target)?;
        
        // 大小不同 → 需要更新
        if src_meta.len() != tgt_meta.len() {
            return Ok(true);
        }
        
        // 源文件更新 → 需要更新
        let src_mtime = src_meta.modified()?;
        let tgt_mtime = tgt_meta.modified()?;
        Ok(src_mtime > tgt_mtime)
    }
    
    /// 复制文件（带重试机制，处理 Windows DLL 占用问题）
    fn copy_with_retry(&self, source: &PathBuf, target: &PathBuf, max_retries: u32) -> Result<()> {
        for attempt in 0..max_retries {
            match std::fs::copy(source, target) {
                Ok(bytes) => {
                    println!(
                        "  [Runtime] Copied {} ({} bytes) -> {}",
                        source.file_name().unwrap().to_string_lossy(),
                        bytes,
                        target.display()
                    );
                    return Ok(());
                }
                Err(e) => {
                    if attempt < max_retries - 1 {
                        eprintln!(
                            "  [WARN] Copy failed (attempt {}/{}): {}. Retrying...",
                            attempt + 1,
                            max_retries,
                            e
                        );
                        std::thread::sleep(std::time::Duration::from_millis(500));
                    } else {
                        anyhow::bail!("Failed to copy runtime DLL after {} attempts: {}", max_retries, e);
                    }
                }
            }
        }
        Ok(())
    }

    /// 打印编译报告
    fn print_report(&self) {
        println!("--- Compile Report ---");
        println!("Duration: {}ms", self.report.total_duration_ms);
        println!("Memory:   {}", format_bytes(self.report.phases.last().map(|p| p.memory_bytes).unwrap_or(0)));
        println!("Modules:  {}", self.report.total_modules);
        println!("Entries:  {}", self.report.total_entries);
        let fn_pct = if self.report.functions_total > 0 {
            self.report.functions_compiled as f64 / self.report.functions_total as f64 * 100.0
        } else { 0.0 };
        println!("Functions: {}/{} ({:.1}%)", self.report.functions_compiled, self.report.functions_total, fn_pct);
        println!("Code: {} | Data: {} | RData: {} | Total: {}",
            format_bytes(self.report.total_code_size as u64),
            format_bytes(self.report.total_data_size as u64),
            format_bytes(self.report.total_rdata_size as u64),
            format_bytes((self.report.total_code_size + self.report.total_data_size + self.report.total_rdata_size) as u64));
        println!("Symbols: {} | Relocations: {}", self.report.total_symbols, self.report.total_relocations);
        println!("--- Phases ---");
        for phase in &self.report.phases {
            println!("  {}: {}ms {}", phase.name, phase.duration_ms, format_bytes(phase.memory_bytes));
        }
        println!("--- Modules ---");
        for m in &self.report.module_results {
            let status = if m.success { "OK" } else { "FAIL" };
            let fn_cov = if m.functions_declared > 0 {
                format!("{}/{}", m.functions_compiled, m.functions_declared)
            } else { "-".to_string() };
            println!("  {} | {} | code={} sym={} fn={} total={}ms parse={}ms codegen={}ms",
                m.module_name, status, m.code_size, m.symbol_count, fn_cov,
                m.duration_ms, m.parse_ms, m.codegen_ms);
        }
        if self.report.errors > 0 {
            println!("Errors: {} module(s) failed", self.report.errors);
            for m in &self.report.module_results {
                if !m.success {
                    if let Some(ref err) = m.error {
                        println!("  {}: {}", m.module_name, err);
                    }
                }
            }
        }
        if !self.report.warnings.is_empty() {
            println!("Warnings: {}", self.report.warnings.len());
            for w in self.report.warnings.iter().take(5) {
                println!("  {}", w);
            }
            if self.report.warnings.len() > 5 {
                println!("  ... and {} more", self.report.warnings.len() - 5);
            }
        }
        println!("--- Executables ---");
        for e in &self.report.entry_results {
            if let Some(ref path) = e.exe_path {
                println!("  {} -> {}", e.entry_name, path.file_name().unwrap_or_default().to_string_lossy());
            }
        }
        println!("---");
    }

    /// 获取编译报告
    pub fn get_report(&self) -> &CompileReport {
        &self.report
    }

    /// 获取编译报告摘要（单行字符串）
    pub fn get_summary(&self) -> String {
        let r = &self.report;
        let fn_pct = if r.functions_total > 0 {
            format!("{:.0}%", r.functions_compiled as f64 / r.functions_total as f64 * 100.0)
        } else {
            "-".to_string()
        };
        let total_size = r.total_code_size + r.total_data_size + r.total_rdata_size;
        format!(
            "modules={} entries={} functions={}/{}({}) code={} data={} rdata={} total={} symbols={} relocs={} errors={} warnings={} duration={}ms",
            r.total_modules, r.total_entries,
            r.functions_compiled, r.functions_total, fn_pct,
            format_bytes(r.total_code_size as u64),
            format_bytes(r.total_data_size as u64),
            format_bytes(r.total_rdata_size as u64),
            format_bytes(total_size as u64),
            r.total_symbols, r.total_relocations,
            r.errors, r.warnings.len(),
            r.total_duration_ms,
        )
    }

    /// 获取编译结果
    pub fn get_compiled_objects(&self) -> &HashMap<PathBuf, Vec<u8>> {
        &self.compiled_objects
    }

    /// 获取项目信息
    pub fn get_project(&self) -> &Project {
        &self.project
    }

    /// 获取依赖图
    pub fn get_dep_graph(&self) -> &DepGraph {
        &self.dep_graph
    }

    /// 获取输出目录
    pub fn get_output_dir(&self) -> &Path {
        &self.output_dir
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // === align_up 测试 ===

    #[test]
    fn test_align_up_already_aligned() {
        assert_eq!(align_up(16, 16), 16);
        assert_eq!(align_up(4096, 4096), 4096);
        assert_eq!(align_up(0, 16), 0);
    }

    #[test]
    fn test_align_up_needs_padding() {
        assert_eq!(align_up(1, 16), 16);
        assert_eq!(align_up(15, 16), 16);
        assert_eq!(align_up(17, 16), 32);
        assert_eq!(align_up(100, 16), 112);
        assert_eq!(align_up(3, 4), 4);
        assert_eq!(align_up(5, 8), 8);
    }

    #[test]
    fn test_align_up_power_of_two() {
        // 验证各种对齐边界
        for align in &[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 4096] {
            assert_eq!(align_up(0, *align), 0, "align=0, alignment={}", align);
            assert_eq!(align_up(*align, *align), *align, "align={}, alignment={}", align, align);
            assert_eq!(align_up(*align + 1, *align), *align * 2, "align={}+1, alignment={}", align, align);
        }
    }

    // === format_bytes 测试 ===

    #[test]
    fn test_format_bytes_zero() {
        assert_eq!(format_bytes(0), "0 B");
    }

    #[test]
    fn test_format_bytes_bytes() {
        assert_eq!(format_bytes(1), "1 B");
        assert_eq!(format_bytes(512), "512 B");
        assert_eq!(format_bytes(1023), "1023 B");
    }

    #[test]
    fn test_format_bytes_kilobytes() {
        assert_eq!(format_bytes(1024), "1 KB");
        assert_eq!(format_bytes(2048), "2 KB");
        assert_eq!(format_bytes(1048575), "1024 KB"); // 1048575 / 1024 = 1023.999 → 1024 KB
    }

    #[test]
    fn test_format_bytes_megabytes() {
        assert_eq!(format_bytes(1048576), "1.0 MB");
        assert_eq!(format_bytes(2097152), "2.0 MB");
        assert_eq!(format_bytes(1073741823), "1024.0 MB"); // 1073741823 / 1048576 ≈ 1023.999
    }

    #[test]
    fn test_format_bytes_gigabytes() {
        assert_eq!(format_bytes(1073741824), "1.0 GB");
        assert_eq!(format_bytes(2147483648), "2.0 GB");
    }

    // === CompilePhase 测试 ===

    #[test]
    fn test_compile_phase_timing() {
        let mut phase = CompilePhase::new("TestPhase");
        assert_eq!(phase.name, "TestPhase");
        assert_eq!(phase.duration_ms, 0);

        // 等待一小段时间后结束
        std::thread::sleep(std::time::Duration::from_millis(5));
        let duration = phase.finish();
        assert!(duration >= 5, "duration_ms 应 >= 5ms，实际: {}", duration);
        assert!(phase.memory_bytes > 0, "memory_bytes 应 > 0");
    }

    // === CompileReport 结构测试 ===

    #[test]
    fn test_compile_report_default() {
        let report = CompileReport {
            project_name: "test".into(),
            total_modules: 3,
            total_entries: 1,
            phases: Vec::new(),
            module_results: Vec::new(),
            entry_results: Vec::new(),
            total_duration_ms: 100,
            functions_compiled: 10,
            functions_total: 12,
            total_code_size: 2048,
            total_data_size: 512,
            total_symbols: 30,
            total_relocations: 45,
            total_rdata_size: 128,
            warnings: Vec::new(),
            errors: 0,
            shim_usage: HashMap::new(),
            npm_packages_used: Vec::new(),
        };
        assert_eq!(report.project_name, "test");
        assert_eq!(report.total_modules, 3);
        assert_eq!(report.functions_compiled, 10);
        assert_eq!(report.functions_total, 12);
        assert_eq!(report.total_symbols, 30);
        assert_eq!(report.total_relocations, 45);
    }

    #[test]
    fn test_module_compile_result() {
        let result = ModuleCompileResult {
            module_name: "main".into(),
            module_path: PathBuf::from("/src/main.ts"),
            code_size: 1024,
            data_size: 256,
            rdata_size: 128,
            symbol_count: 15,
            reloc_count: 30,
            duration_ms: 5,
            parse_ms: 1,
            codegen_ms: 3,
            success: true,
            error: None,
            functions_declared: 5,
            functions_compiled: 5,
        };
        assert_eq!(result.module_name, "main");
        assert!(result.success);
        assert!(result.error.is_none());
        assert_eq!(result.functions_declared, 5);
        assert_eq!(result.functions_compiled, 5);
    }

    #[test]
    fn test_module_compile_result_failure() {
        let result = ModuleCompileResult {
            module_name: "broken".into(),
            module_path: PathBuf::from("/src/broken.ts"),
            code_size: 0,
            data_size: 0,
            rdata_size: 0,
            symbol_count: 0,
            reloc_count: 0,
            duration_ms: 1,
            parse_ms: 0,
            codegen_ms: 0,
            success: false,
            error: Some("syntax error".into()),
            functions_declared: 0,
            functions_compiled: 0,
        };
        assert!(!result.success);
        assert_eq!(result.error.as_deref(), Some("syntax error"));
    }

    // === estimate_memory_usage 测试 ===

    #[test]
    fn test_estimate_memory_usage_returns_value() {
        let mem = estimate_memory_usage();
        // Windows 上应返回非零值（当前进程内存）
        assert!(mem > 0, "estimate_memory_usage 应返回 > 0");
    }
}
