//! Embedding-ABI M1 export-signature gate (spec §3, clause-3
//! discriminator): an `(export …)` fn whose params/ret are not all
//! `Int`/`Float`, or whose effect set is non-empty, MUST fail
//! `ail check` with the new diagnostic. A scalar+pure export passes.

use ailang_test_support::examples_dir;

fn check_codes(file: &str) -> Vec<String> {
    let path = examples_dir().join(file);
    let ws = ailang_surface::load_workspace(&path)
        .unwrap_or_else(|e| panic!("load {file}: {e}"));
    ailang_check::check_workspace(&ws)
        .into_iter()
        .map(|d| d.code)
        .collect()
}

#[test]
fn str_param_export_rejected() {
    assert!(check_codes("embed_export_str_param_rejected.ail")
        .iter().any(|c| c == "export-non-scalar-signature"));
}

// M3 RE-POINT (deliberate, reviewed — spec 2026-05-18-embedding-abi-m3
// §"must-fail axis"): the fixture this asserts on
// (embed_export_adt_ret_rejected.ail) is single-ctor two-Int = M3-VALID.
// Task 2 re-points the fixture to a genuinely-still-rejected ADT
// (multi-ctor + Str field). This pin's *meaning* changes from
// "any ADT rejected" to "non-M3-shaped ADT rejected"; it is NOT
// silently inverted — the rejection (export-non-scalar-signature)
// stays asserted, on a fixture that still genuinely fails it.
#[test]
fn adt_ret_export_rejected() {
    assert!(check_codes("embed_export_adt_ret_rejected.ail")
        .iter().any(|c| c == "export-non-scalar-signature"));
}

#[test]
fn io_export_rejected() {
    assert!(check_codes("embed_export_io_rejected.ail")
        .iter().any(|c| c == "export-has-effects"));
}

#[test]
fn combined_effectful_export_rejected_on_signature_first() {
    let codes = check_codes("embed_export_effectful_rejected.ail");
    assert!(codes.iter().any(|c| c == "export-non-scalar-signature"),
        "combined fixture must fail signature-first; got {codes:?}");
}

#[test]
fn scalar_pure_export_passes() {
    let codes = check_codes("embed_export_float_ok.ail");
    assert!(!codes.iter().any(|c|
        c == "export-non-scalar-signature" || c == "export-has-effects"),
        "scalar+pure export must pass the gate; got {codes:?}");
}

#[test]
fn headline_int_export_passes() {
    let codes = check_codes("embed_backtest_step.ail");
    assert!(!codes.iter().any(|c|
        c == "export-non-scalar-signature" || c == "export-has-effects"),
        "headline export must pass the gate; got {codes:?}");
}

#[test]
fn record_export_passes() {
    // single-ctor (Float,Int) record export — M3-valid
    let codes = check_codes("embed_export_record_ok.ail");
    assert!(!codes.iter().any(|c|
        c == "export-non-scalar-signature" || c == "export-has-effects"),
        "single-ctor scalar record export must pass the gate; got {codes:?}");
}

#[test]
fn str_field_record_export_rejected() {
    assert!(check_codes("embed_export_str_field_record_rejected.ail")
        .iter().any(|c| c == "export-non-scalar-signature"));
}

#[test]
fn list_field_record_export_rejected() {
    assert!(check_codes("embed_export_list_field_record_rejected.ail")
        .iter().any(|c| c == "export-non-scalar-signature"));
}

#[test]
fn multictor_export_rejected() {
    assert!(check_codes("embed_export_multictor_rejected.ail")
        .iter().any(|c| c == "export-non-scalar-signature"));
}
