use std::collections::BTreeMap;

use eidos_kernel::schema::{Edge, Node};

use super::frontmatter::Frontmatter;
use super::target::resolve_target;

/// Frontmatter fields that declare a typed relation (field -> edge relation).
pub(super) const REL_FIELDS: &[(&str, &str)] = &[
    ("uses", "uses_tool"),
    ("contracts", "requires_contract"),
    ("depends_on", "depends_on"),
    ("produces", "produces"),
    ("consumes", "consumes"),
    ("supports", "supports"),
    ("asserts", "asserts"),
    ("qualifies", "qualifies"),
    ("related", "related_to"),
    ("dispatches", "dispatches"),
];

pub fn default_relation_fields() -> BTreeMap<String, String> {
    REL_FIELDS
        .iter()
        .map(|(field, relation)| ((*field).to_string(), (*relation).to_string()))
        .collect()
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PendingFrontmatterEdge {
    pub from: String,
    pub target: String,
    pub relation: String,
    pub evidence: String,
}

pub(super) fn frontmatter_relation_edges(
    from: &Node,
    fm: &Frontmatter,
    nodes: &[Node],
    relation_fields: &BTreeMap<String, String>,
) -> Vec<Edge> {
    let mut edges = Vec::new();
    for (field, rel) in relation_fields {
        for raw in fm.get_list(field) {
            if let Some(to) = resolve_target(&raw, nodes) {
                edges.push(Edge {
                    from: from.id.clone(),
                    to,
                    relation: rel.clone(),
                    evidence: "frontmatter".into(),
                    // Authored frontmatter relation — earned Resolved.
                    basis: eidos_kernel::schema::EdgeBasis::Resolved,
                    ..Default::default()
                });
            }
        }
    }
    edges
}

pub fn frontmatter_pending_edges(
    nodes: &[Node],
    relation_fields: &BTreeMap<String, String>,
) -> Vec<PendingFrontmatterEdge> {
    let mut edges = Vec::new();
    for node in nodes {
        if node.span.is_some() {
            continue;
        }
        let Some(src) = node.source_files.first() else {
            continue;
        };
        let text = super::helpers::read(std::path::Path::new(src));
        let (fm, _) = super::frontmatter::parse_frontmatter(&text);
        for (field, rel) in relation_fields {
            for target in fm.get_list(field) {
                edges.push(PendingFrontmatterEdge {
                    from: node.id.clone(),
                    target,
                    relation: rel.clone(),
                    evidence: "frontmatter".into(),
                });
            }
        }
    }
    edges
}
