//! Index-rebuild helpers: map domain keys to `ListCrdt` positions for O(1) lookup.
//!
//! Each function scans the corresponding `ListCrdt` in the CRDT document and
//! returns a fresh `HashMap` from the entry's primary key to its position index.
//! These are called once during [`super::init::init`] to populate the secondary
//! indices in [`super::CrdtState`], and again by write helpers whenever an entry
//! is inserted.

use std::collections::HashMap;

use bft_json_crdt::json_crdt::{BaseCrdt, CrdtNode, JsonValue};

use super::super::types::PipelineDoc;

/// Rebuild the story_id → list index mapping from the current CRDT state.
pub(in crate::crdt_state) fn rebuild_index(crdt: &BaseCrdt<PipelineDoc>) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, item) in crdt.doc.items.iter().enumerate() {
        if let JsonValue::String(ref sid) = item.story_id.view() {
            map.insert(sid.clone(), i);
        }
    }
    map
}

/// Rebuild the node_id → nodes list index mapping from the current CRDT state.
pub(in crate::crdt_state) fn rebuild_node_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, node) in crdt.doc.nodes.iter().enumerate() {
        if let JsonValue::String(ref nid) = node.node_id.view() {
            map.insert(nid.clone(), i);
        }
    }
    map
}

/// Rebuild the agent_id → tokens list index.
pub(in crate::crdt_state) fn rebuild_token_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.tokens.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.agent_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the story_id → merge_jobs list index.
pub(in crate::crdt_state) fn rebuild_merge_job_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.merge_jobs.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.story_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the agent_id → active_agents list index.
pub(in crate::crdt_state) fn rebuild_active_agent_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.active_agents.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.agent_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the story_id → test_jobs list index.
pub(in crate::crdt_state) fn rebuild_test_job_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.test_jobs.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.story_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the node_id → agent_throttle list index.
pub(in crate::crdt_state) fn rebuild_agent_throttle_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.agent_throttle.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.node_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the project name → gateway_projects list index.
pub(in crate::crdt_state) fn rebuild_gateway_project_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.gateway_projects.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.name.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}

/// Rebuild the session_id → llm_sessions list index.
pub(in crate::crdt_state) fn rebuild_llm_session_index(
    crdt: &BaseCrdt<PipelineDoc>,
) -> HashMap<String, usize> {
    let mut map = HashMap::new();
    for (i, entry) in crdt.doc.llm_sessions.iter().enumerate() {
        if let JsonValue::String(ref k) = entry.session_id.view() {
            map.insert(k.clone(), i);
        }
    }
    map
}
