//! Pin for `CheckError::DuplicateCtor` — same-named ctors in two
//! different ADTs within one module. Ratifies the load-bearing
//! consumer of the per-module `env.ctor_index` rebuild in
//! `check_in_workspace`. Env construction is code-SoT (the
//! `env-construction` ledger row in design/INDEX.md is source-link
//! only). The two overlays — typecheck-side rebuild + mono-side
//! narrowed — are deliberately asymmetric: the typecheck-side
//! `ctor_index` half exists *for this very diagnostic*, while the
//! mono-side overlay is narrowed to types-only because the runtime
//! ctor lookup is type-driven. If the per-module rebuild is ever
//! removed without an equivalent replacement path, this test goes
//! red.

use ailang_check::check_workspace;
use ailang_core::ast::{Ctor, Def, Module, TypeDef};
use ailang_core::workspace::{Registry, Workspace};
use ailang_core::SCHEMA;
use std::collections::BTreeMap;

#[test]
fn duplicate_ctor_across_two_adts_in_one_module() {
    let m = Module {
        schema: SCHEMA.into(),
        name: "M".into(),
        kernel: false,
        imports: vec![],
        defs: vec![
            Def::Type(TypeDef {
                name: "Cat".into(),
                vars: vec![],
                ctors: vec![Ctor {
                    name: "Twins".into(),
                    fields: vec![],
                }],
                doc: None,
                drop_iterative: false,
                param_in: BTreeMap::new(),
            }),
            Def::Type(TypeDef {
                name: "Dog".into(),
                vars: vec![],
                ctors: vec![Ctor {
                    name: "Twins".into(),
                    fields: vec![],
                }],
                doc: None,
                drop_iterative: false,
                param_in: BTreeMap::new(),
            }),
        ],
    };
    let mut modules = BTreeMap::new();
    modules.insert(m.name.clone(), m.clone());
    let ws = Workspace {
        entry: m.name.clone(),
        modules,
        root_dir: std::path::PathBuf::from("."),
        registry: Registry::default(),
    };

    let diags = check_workspace(&ws);
    let dup = diags
        .iter()
        .find(|d| d.code == "duplicate-ctor")
        .unwrap_or_else(|| {
            panic!(
                "expected at least one `duplicate-ctor` diagnostic, got: {diags:?}"
            )
        });
    assert!(
        dup.message.contains("Twins"),
        "expected message to name the duplicate ctor `Twins`, got: {}",
        dup.message
    );
    assert!(
        dup.message.contains("Cat") && dup.message.contains("Dog"),
        "expected message to name both ADTs `Cat` and `Dog`, got: {}",
        dup.message
    );
}
