//! Option behavior: capture, shorthand, relax/strict zeros, wrap.

mod common;

use common::to_regex;
use regex_range::{to_regex_range, Options};

fn d() -> Options {
    Options::default()
}

fn call(min: &str, max: &str, opts: &Options) -> String {
    to_regex_range(min, Some(max), opts).expect("valid range")
}

#[test]
fn shorthand_swaps_digit_class() {
    let got = call("0", "999999", &d().shorthand(true));
    assert_eq!(got, "(?:\\d|[1-9]\\d{1,5})");
}

#[test]
fn shorthand_only_swaps_full_classes() {
    // The shorthand output equals the default with [0-9] rewritten to \d.
    for (min, max) in [
        ("0", "999999"),
        ("1", "3456"),
        ("-99", "99"),
        ("1", "100000"),
    ] {
        let default = call(min, max, &d());
        let short = call(min, max, &d().shorthand(true));
        assert_eq!(short, default.replace("[0-9]", "\\d"), "({min},{max})");
    }
}

#[test]
fn relax_zeros_false_makes_zeros_strict() {
    assert_eq!(call("001", "005", &d().relax_zeros(false)), "00[1-5]");
    assert_eq!(call("01", "05", &d().relax_zeros(false)), "0[1-5]");
    assert_eq!(
        call("0001", "1000", &d().relax_zeros(false)),
        "(?:0{3}[1-9]|00[1-9][0-9]|0[1-9][0-9]{2}|1000)"
    );
}

#[test]
fn strict_zeros_aliases_relax_zeros() {
    // strict_zeros:true == relax_zeros:false
    assert_eq!(
        call("001", "005", &d().strict_zeros(true)),
        call("001", "005", &d().relax_zeros(false))
    );
    // strict_zeros:false == relax_zeros:true (the default)
    assert_eq!(
        call("001", "005", &d().strict_zeros(false)),
        call("001", "005", &d())
    );
    // strict_zeros overrides an explicit relax_zeros.
    assert_eq!(
        call("001", "005", &d().relax_zeros(true).strict_zeros(true)),
        "00[1-5]"
    );
}

#[test]
fn capture_wraps_even_single_condition() {
    assert_eq!(call("-4", "-2", &d().capture(true)), "(-[2-4])");
    assert_eq!(call("1", "5", &d().capture(true)), "([1-5])");
}

#[test]
fn capture_takes_precedence_over_wrap_false() {
    let got = to_regex_range("-10", Some("10"), &d().capture(true).wrap(false)).unwrap();
    assert_eq!(got, "(-[1-9]|-?10|[0-9])");
}

#[test]
fn wrap_false_suppresses_group() {
    assert_eq!(call("-10", "10", &d().wrap(false)), "-[1-9]|-?10|[0-9]");
    assert_eq!(
        call("15", "95", &d().wrap(false)),
        "1[5-9]|[2-8][0-9]|9[0-5]"
    );
}

#[test]
fn adjacent_values_honor_wrap_and_capture() {
    assert_eq!(call("0", "1", &d()), "(?:0|1)");
    assert_eq!(call("0", "1", &d().wrap(false)), "0|1");
    assert_eq!(call("0", "1", &d().capture(true)), "(0|1)");
    // Adjacent branch keeps original argument order.
    assert_eq!(call("6", "5", &d()), "(?:6|5)");
    assert_eq!(call("5", "6", &d()), "(?:5|6)");
}

#[test]
fn relax_zeros_false_match_behavior() {
    // README strict example: only the full-width zero-padded forms match.
    let relaxed = call("-0010", "0010", &d());
    let re = to_regex(&relaxed);
    for v in ["-10", "-010", "-0010", "10", "010", "0010"] {
        assert!(re.is_match(v), "relaxed should match {v}");
    }

    let strict = call("-0010", "0010", &d().relax_zeros(false));
    let re = to_regex(&strict);
    assert!(re.is_match("-0010"));
    assert!(re.is_match("0010"));
    for v in ["-10", "-010", "10", "010"] {
        assert!(!re.is_match(v), "strict should not match {v}");
    }
}

#[test]
fn non_padded_zero_is_not_padded() {
    // A lone "0" has no digit after the zero, so it is not padded.
    assert_eq!(call("0", "9", &d()), "[0-9]");
}
