//! ActiveRecord association macros — `has_many`, `has_one`, `belongs_to`,
//! `has_and_belongs_to_many`. Emits `Extends` edges from the declaring
//! class to the associated model class.

use ckg_core::{Edge, EdgeKind};
use tree_sitter::Node;

use crate::lang::ruby::{Ctx, strip_quotes, text};

pub(crate) fn handle_association(
    ctx: &mut Ctx<'_>,
    n: Node<'_>,
    src: &str,
    macro_name: &str,
    class_id: &str,
) {
    let Some(args) = n.child_by_field_name("arguments") else {
        return;
    };
    let mut c = args.walk();
    for arg in args.children(&mut c) {
        if arg.kind() != "simple_symbol" {
            continue;
        }
        let raw = strip_quotes(text(arg, src)).to_string();
        let class_name = if matches!(macro_name, "has_many" | "has_and_belongs_to_many") {
            let stem = raw
                .strip_suffix("ies")
                .map(|s| format!("{s}y"))
                .or_else(|| raw.strip_suffix('s').map(|s| s.to_string()))
                .unwrap_or(raw.clone());
            capitalise(&stem)
        } else {
            capitalise(&raw)
        };
        ctx.out.edges.push(Edge {
            kind: EdgeKind::Extends,
            src: class_id.to_string(),
            dst: class_name,
            confidence: 0.7,
        });
        break;
    }
}

/// Rails-style camelize: `cover_image` → `CoverImage`.
pub(super) fn capitalise(s: &str) -> String {
    s.split('_')
        .map(|seg| {
            let mut out = String::with_capacity(seg.len());
            let mut chars = seg.chars();
            if let Some(c) = chars.next() {
                out.extend(c.to_uppercase());
            }
            out.extend(chars);
            out
        })
        .collect::<Vec<_>>()
        .join("")
}
