//! `DagBackend` impl for `JsonlBackend`.

use async_trait::async_trait;
use uuid::Uuid;

use crate::backend::DagBackend;
use crate::backends::jsonl::backend::JsonlBackend;
use crate::error::Result;
use crate::storage::{append_ndjson, read_ndjson};
use crate::types::{DagEdge, SessionMetadata};

#[async_trait]
impl DagBackend for JsonlBackend {
    async fn append_dag_edge(&self, edge: DagEdge) -> Result<()> {
        let dag_path = self.paths.dag_path();
        if let Some(parent) = dag_path.parent() {
            tokio::fs::create_dir_all(parent).await?;
        }
        append_ndjson(&dag_path, &edge).await?;
        Ok(())
    }

    async fn get_children(&self, parent: Uuid) -> Result<Vec<SessionMetadata>> {
        let dag_path = self.paths.dag_path();
        let edges: Vec<DagEdge> = read_ndjson(&dag_path).await.unwrap_or_default();

        let child_ids: Vec<Uuid> = edges
            .iter()
            .filter(|e| e.parent == parent)
            .map(|e| e.child)
            .collect();

        let mut children = Vec::new();
        for child_id in child_ids {
            match crate::backend::ArchiveBackend::get_session(self, child_id).await {
                Ok(Some(meta)) => children.push(meta),
                Ok(None) => {
                    tracing::warn!(
                        child_scroll_id = %child_id,
                        "DAG child session not found"
                    );
                }
                Err(e) => {
                    tracing::warn!(
                        child_scroll_id = %child_id,
                        error = %e,
                        "DAG child session not found"
                    );
                }
            }
        }

        Ok(children)
    }

    async fn get_dag_edges(&self, root: Uuid) -> Result<Vec<DagEdge>> {
        // Single-level read: return edges whose parent == root.
        // The recursive DAG walk is coordinator-level orchestration.
        let dag_path = self.paths.dag_path();
        let all_edges: Vec<DagEdge> = read_ndjson(&dag_path).await.unwrap_or_default();

        let edges = all_edges
            .into_iter()
            .filter(|e| e.parent == root)
            .collect();

        Ok(edges)
    }
}
