//! CRDT state layer — manages pipeline state as a conflict-free replicated document backed by SQLite.
//!
//! The CRDT document is the primary source of truth for pipeline item
//! metadata (stage, name, agent, etc.).  CRDT ops are persisted to SQLite so
//! state survives restarts.  The filesystem `.huskies/work/` directories are
//! still updated as a secondary output for backwards compatibility.
//!
//! Stage transitions detected by `write_item()` are broadcast as [`CrdtEvent`]s
//! so subscribers (auto-assign, WebSocket, notifications) can react without
//! polling the filesystem.

#![allow(unused_imports, dead_code)]
use std::collections::HashMap;

/// A vector clock mapping node IDs (hex-encoded Ed25519 pubkeys) to the count
/// of ops seen from that node.  Used for delta sync — a connecting peer sends
/// its clock so the other side can compute which ops are missing.
pub type VectorClock = HashMap<String, u64>;

mod gateway_config;
mod lww_maps;
mod ops;
mod presence;
mod read;
mod state;
mod types;
mod write;

pub use gateway_config::{read_gateway_active_project, write_gateway_active_project};
pub use lww_maps::{
    EventLogEntryRaw, GAP_PIPELINE_EVENT, append_event_log_entry, append_gap_log_entry,
    assemble_and_advance_session, delete_active_agent, delete_agent_throttle,
    delete_gateway_project, delete_merge_job, delete_test_job, delete_token_usage,
    read_active_agent, read_agent_throttle, read_all_active_agents, read_all_agent_throttles,
    read_all_event_log_entries, read_all_gateway_projects, read_all_merge_jobs, read_all_test_jobs,
    read_all_token_usage, read_gateway_project, read_llm_session, read_merge_job, read_test_job,
    read_token_usage, write_active_agent, write_agent_throttle, write_gateway_project,
    write_llm_session, write_merge_job, write_test_job, write_token_usage,
};
pub use ops::{all_ops_json, apply_remote_op, ops_since, our_vector_clock, subscribe_ops};
pub use presence::{
    is_claimed_by_us, our_node_id, read_all_node_presence, release_claim, sign_challenge,
    sign_versioned_challenge, write_claim, write_node_metadata, write_node_presence,
};
pub use read::{
    CrdtItemDump, CrdtStateDump, check_archived_deps_crdt, check_unmet_deps_crdt,
    dep_is_archived_crdt, dep_is_done_crdt, dump_crdt_state, evict_item, is_tombstoned,
    read_all_items, read_item, tombstoned_ids,
};
pub(crate) use state::flush_persistence;
pub use state::{init, subscribe};
pub use types::{
    ActiveAgentCrdt, ActiveAgentView, AgentThrottleCrdt, AgentThrottleView, CrdtEvent, EpicId,
    EventLogEntryCrdt, GatewayConfigCrdt, GatewayProjectCrdt, GatewayProjectView, LlmSessionCrdt,
    LlmSessionView, MergeJobCrdt, MergeJobView, NodePresenceCrdt, NodePresenceView, PipelineDoc,
    PipelineItemCrdt, PipelineItemView, ScopeFilter, TestJobCrdt, TestJobView, TokenUsageCrdt,
    TokenUsageView, WorkItem,
};
pub use write::{
    bump_retry_count, migrate_legacy_stage_strings, migrate_merge_job, migrate_names_from_slugs,
    migrate_node_claims_to_agent_claims, migrate_story_ids_to_numeric,
    migrate_zombie_pipeline_rows, name_from_story_id, purge_done_stage_merge_jobs, set_agent,
    set_depends_on, set_epic, set_item_type, set_name, set_origin, set_plan_state, set_qa_mode,
    set_resume_to, set_resume_to_raw, set_retry_count, write_item,
};

#[cfg(test)]
pub use write::write_item_str;

#[cfg(test)]
pub use state::init_for_test;

pub(crate) use state::{all_ops_lock, vector_clock_lock};

/// Hex-encode a byte slice (no external dep needed).
pub(crate) mod hex {
    /// Encode `bytes` as a lowercase hexadecimal string.
    pub fn encode(bytes: &[u8]) -> String {
        bytes.iter().map(|b| format!("{b:02x}")).collect()
    }
}
