use anyhow::Result;

use crate::order::PriorityConfig;
use crate::utils::tree_arena::JsonTreeArena as TreeArena;

/// Format-agnostic ingest boundary. Other formats can implement this trait
/// to produce the neutral TreeArena without going through JSON first.
pub trait Ingest {
    fn parse_one(bytes: Vec<u8>, cfg: &PriorityConfig) -> Result<TreeArena>;
    fn parse_many(
        inputs: Vec<(String, Vec<u8>)>,
        cfg: &PriorityConfig,
    ) -> Result<TreeArena>;
}

// Format adapters and builders live under `formats/`.
pub mod fileset;
pub mod formats;

// Use `crate::ingest::formats::{json,yaml,text}` for format-specific helpers.

// Ingest-agnostic helpers (e.g., array sampling policies).
pub mod sampling;

// Convenience re-exports so callers can use `crate::ingest::parse_*`.
#[allow(
    unused_imports,
    reason = "Re-exported helpers need to stay public even when unused internally"
)]
pub use formats::{
    parse_json_many, parse_json_one, parse_text_many, parse_text_one,
    parse_text_one_with_mode, parse_yaml_many, parse_yaml_one,
};

// (intentionally no duplicate re-exports here; see formats::* above)

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

    #[test]
    fn parse_one_basic_shape() {
        let arena = parse_json_one(
            b"{\"a\":1}".to_vec(),
            &PriorityConfig::new(usize::MAX, usize::MAX),
        )
        .unwrap();
        assert!(
            !arena.is_fileset,
            "single input should not be marked fileset"
        );
        let root = arena.root_id;
        assert_eq!(arena.nodes[root].kind, NodeKind::Object);
        assert_eq!(arena.nodes[root].object_len.unwrap_or(1), 1);
    }

    #[test]
    fn parse_many_sets_fileset_root() {
        let inputs = vec![
            ("a.json".to_string(), b"{}".to_vec()),
            ("b.json".to_string(), b"[]".to_vec()),
        ];
        let arena = parse_json_many(
            inputs,
            &PriorityConfig::new(usize::MAX, usize::MAX),
        )
        .unwrap();
        assert!(arena.is_fileset, "multi input should be marked fileset");
        let root = arena.root_id;
        assert_eq!(arena.nodes[root].kind, NodeKind::Object);
        // Expect two top-level entries
        assert_eq!(arena.nodes[root].object_len.unwrap_or(0), 2);
    }
}
