//! Analysis-side enrichment over [`xenia_cpu::disasm::iter_disasm`].
//!
//! Turns a stream of decoder-only [`xenia_cpu::disasm::DisasmItem`]s into a
//! stream of [`RichDisasmItem`]s carrying section name + enclosing function +
//! label name. The three sinks in [`crate::sinks`] (text, JSON, DuckDB) all
//! consume `RichDisasmItem`.

use std::collections::HashMap;

use xenia_cpu::disasm::DisasmItem;

use crate::func::FuncAnalysis;

/// `DisasmItem` plus the analysis context (section/function/label).
#[derive(Debug, Clone)]
pub struct RichDisasmItem<'a> {
    pub item: DisasmItem,
    pub section: &'a str,
    pub function: Option<u32>,
    pub label: Option<&'a str>,
}

/// Walk one code section, yielding rich items annotated with section name,
/// rolling-window enclosing function, and label-at-address.
///
/// The `function` field tracks the most recent function-start the iterator
/// has crossed — matching the legacy `current_func` behaviour in
/// `db.rs::insert_instructions_streaming`.
pub fn enrich_section<'a>(
    image: &'a [u8],
    image_base: u32,
    section_name: &'a str,
    va_start: u32,
    va_end: u32,
    func_analysis: &'a FuncAnalysis,
    labels: &'a HashMap<u32, String>,
) -> impl Iterator<Item = RichDisasmItem<'a>> + 'a {
    let mut current_func: Option<u32> = None;
    xenia_cpu::disasm::iter_disasm(image, image_base, va_start, va_end).map(move |item| {
        if func_analysis.is_function_start(item.addr) {
            current_func = Some(item.addr);
        }
        let label = labels.get(&item.addr).map(|s| s.as_str());
        RichDisasmItem {
            item,
            section: section_name,
            function: current_func,
            label,
        }
    })
}
