//! Shared definition of a YAML merge key (`<<`), used by `key-duplicates`
//! (merge-collision detection) and `merge-keys` (portability).

use std::borrow::Cow;

use granit_parser::{ScalarStyle, Tag};

/// The fully-resolved YAML core-schema merge tag URI.
const MERGE_TAG: &str = "tag:yaml.org,2002:merge";

/// Whether a mapping key resolves to the YAML merge type (`tag:yaml.org,2002:merge`).
///
/// Two forms merge: an untagged plain `<<` (implicit resolution), or ANY scalar
/// explicitly tagged as the merge type regardless of its text — `!!merge foo`
/// merges in `PyYAML` and ruamel.yaml exactly like `!!merge "<<"` (both verified).
/// A quoted `"<<"`, or a `<<` carrying any other tag, is an ordinary string key
/// that never merges.
#[must_use]
pub(crate) fn is_merge_directive(
    value: &str,
    style: ScalarStyle,
    tag: Option<&Cow<'_, Tag>>,
) -> bool {
    match tag {
        // Match the *complete* resolved URI (`handle` ++ `suffix`), not the
        // canonical-split suffix that `yaml_dom::core_schema_suffix` reports. The
        // spec resolves a tag by concatenating the `%TAG` prefix with the suffix
        // (YAML 1.2.2 §6.8.2.2), so the merge URI can be split anywhere: the
        // play.yaml.com reference parser resolves `%TAG !m! tag:yaml.org,2002:m`
        // + `!m!erge`, verbatim `!<tag:yaml.org,2002:merge>`, and `!!merge` all to
        // the same `tag:yaml.org,2002:merge`, and PyYAML/ruamel merge all three.
        // `core_schema_suffix` only reports the canonical/verbatim splits, so the
        // merge check matches the whole URI here instead.
        Some(tag) => MERGE_TAG
            .strip_prefix(tag.handle.as_str())
            .is_some_and(|suffix| suffix == tag.suffix.as_str()),
        None => value == "<<" && matches!(style, ScalarStyle::Plain),
    }
}
