//! Pure-Rust Sodir FactMaps REST loader for KGLite knowledge graphs.
//!
//! The crate has no Python or PyO3 dependency. PyO3 bindings live in
//! the main `kglite` crate under `src/sodir.rs`; the Python-facing API
//! is `kglite.datasets.sodir.open(...)`.
//!
//! It mirrors the `kglite-sec` crate's layered architecture
//! (dependencies flow strictly one direction):
//!
//! ```text
//! lib (public API)
//!   ├── orchestrator  refresh + fetch_all — drives index/client/fetch  [A4]
//!   ├── blueprint     blueprint walk + deep-merge                       [A4]
//!   ├── preprocess    the 4 FK-derivation joins                         [A3]
//!   ├── index         sodir_index.json + two-tier cooldown              [A3]
//!   ├── fetch         paginate ArcGIS GeoJSON → CSV                     [A2]
//!   ├── client        ArcGIS REST client (rate limit + retry)           [A2]
//!   ├── geojson_wkt   GeoJSON → WKT, epoch-ms → ISO date                [A1]
//!   ├── layout        Workdir tiers + StorageMode                       [A1]
//!   ├── catalog       ~150 dataset stem → (url, layer_id)               [A1]
//!   └── error         SodirError                                        [A1]
//! ```

pub mod blueprint;
pub mod catalog;
pub mod client;
pub mod error;
pub mod fetch;
pub mod geojson_wkt;
pub mod index;
pub mod layout;
pub mod orchestrator;
pub mod preprocess;

pub use blueprint::{datasets_used_by_blueprint, deep_merge, merge_blueprint_json};
pub use catalog::{is_known, kind_of, resolve, DataKind};
pub use client::ArcGISClient;
pub use error::{Result, SodirError};
pub use index::{Action, DatasetEntry, SodirIndex};
pub use layout::{StorageMode, Workdir};
pub use orchestrator::{fetch_all, refresh_csvs, FetchAllReport, RefreshReport};
pub use preprocess::{apply as apply_preprocess, PreprocessReport};

/// Sync wrapper around [`fetch_all`] — see [`crate::datasets::blocking`]
/// for the rationale. Pure convenience for synchronous bindings.
pub fn fetch_all_blocking(
    workdir: &Workdir,
    needed: &[String],
    index_cooldown_days: i64,
    dataset_cooldown_days: i64,
    concurrency: usize,
) -> Result<FetchAllReport> {
    crate::datasets::blocking::run(fetch_all(
        workdir,
        needed,
        index_cooldown_days,
        dataset_cooldown_days,
        concurrency,
    ))
}
