use super::*;

#[test]
fn parses_zeroed_post_special_conditions_scalar_window() {
    let mut bytes = vec![0u8; POST_SPECIAL_CONDITIONS_GROUNDED_TEXT_FIELD_FILE_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gmp"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_post_special_conditions_scalar_probe(
        &bytes,
        Some("gmp"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-map-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("post-special-conditions probe should parse");

    assert_eq!(probe.window_offset, POST_SPECIAL_CONDITIONS_SCALAR_OFFSET);
    assert_eq!(
        probe.window_end_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_END_OFFSET
    );
    assert_eq!(probe.dword_count, 79);
    assert_eq!(
        probe.overlap_end_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_OVERLAP_END_OFFSET
    );
    assert_eq!(probe.overlap_dword_count, 14);
    assert_eq!(probe.overlap_nonzero_dword_count, 0);
    assert!(probe.overlap_nonzero_relative_offset_hexes.is_empty());
    assert_eq!(
        probe.tail_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_OFFSET
    );
    assert_eq!(probe.tail_dword_count, 65);
    assert_eq!(
        probe.tail_runtime_object_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_RUNTIME_OBJECT_OFFSET
    );
    assert_eq!(
        probe.tail_runtime_object_end_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_RUNTIME_OBJECT_END_OFFSET
    );
    assert!(!probe.tail_runtime_object_validated_byte_mirror);
    assert_eq!(
        probe.tail_grounded_live_field_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_GROUNDED_TEXT_FIELD_OFFSET
    );
    assert_eq!(
        probe.tail_grounded_live_field_copy_len,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_GROUNDED_TEXT_FIELD_COPY_LEN
    );
    assert_eq!(
        probe.tail_grounded_live_field_copy_end_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_TAIL_GROUNDED_TEXT_FIELD_COPY_END_OFFSET
    );
    assert!(probe.tail_window_cuts_through_grounded_live_field);
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_offset,
        POST_SPECIAL_CONDITIONS_SCALAR_END_OFFSET
    );
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_len,
        0x28
    );
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_nonzero_byte_count,
        0
    );
    assert_eq!(probe.tail_next_grounded_dword_field_offset_hex, "0x4c80");
    assert_eq!(
        probe.tail_next_grounded_dword_field_file_offset_hex,
        "0x0f65"
    );
    assert_eq!(probe.tail_second_grounded_dword_field_offset_hex, "0x4c8c");
    assert_eq!(
        probe.tail_second_grounded_dword_field_file_offset_hex,
        "0x0f71"
    );
    assert!(!probe.post_text_field_file_alignment_matches_grounded_dword_fields);
    assert!(
        probe
            .tail_grounded_live_field_remaining_file_window_first_nonzero_offset
            .is_none()
    );
    assert!(
        probe
            .tail_grounded_live_field_remaining_file_window_last_nonzero_offset
            .is_none()
    );
    assert_eq!(probe.tail_nonzero_dword_count, 0);
    assert!(probe.tail_first_nonzero_offset.is_none());
    assert!(probe.tail_last_nonzero_offset.is_none());
    assert!(probe.tail_nonzero_relative_offset_hexes.is_empty());
    assert_eq!(probe.nonzero_dword_count, 0);
    assert!(probe.first_nonzero_offset.is_none());
    assert!(probe.last_nonzero_offset.is_none());
    assert!(probe.nonzero_lanes.is_empty());
}

#[test]
fn parses_zeroed_smp_aligned_runtime_rule_band() {
    let mut bytes = vec![0u8; POST_SPECIAL_CONDITIONS_GROUNDED_TEXT_FIELD_FILE_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gmp"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_smp_aligned_runtime_rule_band_probe(
        &bytes,
        Some("gmp"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-map-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("aligned runtime-rule band probe should parse");

    assert_eq!(probe.band_offset, SPECIAL_CONDITIONS_OFFSET);
    assert_eq!(probe.band_end_offset, SMP_ALIGNED_RUNTIME_RULE_END_OFFSET);
    assert_eq!(probe.dword_count, SMP_ALIGNED_RUNTIME_RULE_DWORD_COUNT);
    assert_eq!(
        probe.known_editor_rule_dword_count,
        SMP_ALIGNED_RUNTIME_RULE_KNOWN_EDITOR_RULE_COUNT
    );
    assert_eq!(
        probe.post_window_overlap_start_index,
        SMP_ALIGNED_RUNTIME_RULE_POST_WINDOW_OVERLAP_START_INDEX
    );
    assert_eq!(
        probe.post_window_overlap_dword_count,
        SMP_ALIGNED_RUNTIME_RULE_POST_WINDOW_OVERLAP_DWORD_COUNT
    );
    assert_eq!(probe.nonzero_lane_count, 1);
    assert_eq!(probe.nonzero_band_indices, vec![35]);
    assert!(probe.nonzero_post_window_overlap_band_indices.is_empty());
    assert!(
        probe
            .nonzero_post_window_overlap_post_relative_offset_hexes
            .is_empty()
    );
    assert_eq!(
        probe.nonzero_lanes[0].lane_kind,
        "known-special-condition-dword"
    );
    assert_eq!(
        probe.nonzero_lanes[0].known_label.as_deref(),
        Some("Hidden sentinel")
    );
}

#[test]
fn parses_nonzero_post_special_conditions_scalar_window() {
    let mut bytes = vec![0u8; POST_SPECIAL_CONDITIONS_GROUNDED_TEXT_FIELD_FILE_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());
    bytes[0x0df8..0x0dfc].copy_from_slice(&0x413d298cu32.to_le_bytes());
    bytes[0x0e00..0x0e04].copy_from_slice(&0x40e6b756u32.to_le_bytes());
    bytes[0x0f0c..0x0f10].copy_from_slice(&0x42574909u32.to_le_bytes());
    bytes[0x0f34] = 0xaa;
    bytes[0x0f4e] = 0xbb;

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gms"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_post_special_conditions_scalar_probe(
        &bytes,
        Some("gms"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-save-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("post-special-conditions probe should parse");

    assert_eq!(probe.nonzero_dword_count, 3);
    assert_eq!(probe.first_nonzero_offset, Some(0x0df8));
    assert_eq!(probe.last_nonzero_offset, Some(0x0f0c));
    assert_eq!(probe.overlap_nonzero_dword_count, 2);
    assert_eq!(
        probe.overlap_nonzero_relative_offset_hexes,
        vec!["0x4".to_string(), "0xc".to_string()]
    );
    assert_eq!(probe.tail_nonzero_dword_count, 1);
    assert_eq!(probe.tail_first_nonzero_offset, Some(0x0f0c));
    assert_eq!(probe.tail_last_nonzero_offset, Some(0x0f0c));
    assert_eq!(
        probe.tail_nonzero_relative_offset_hexes,
        vec!["0x118".to_string()]
    );
    assert_eq!(probe.tail_runtime_object_offset_hex, "0x4b47");
    assert_eq!(probe.tail_runtime_object_end_offset_hex, "0x4c4b");
    assert_eq!(
        probe.tail_grounded_live_field_copy_end_offset_hex,
        "0x4c73".to_string()
    );
    assert_eq!(
        probe.tail_grounded_live_field_name,
        "victory-or-outcome status text buffer"
    );
    assert!(probe.tail_window_cuts_through_grounded_live_field);
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_len_hex,
        "0x28"
    );
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_nonzero_byte_count,
        2
    );
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_first_nonzero_offset,
        Some(0x0f34)
    );
    assert_eq!(
        probe.tail_grounded_live_field_remaining_file_window_last_nonzero_offset,
        Some(0x0f4e)
    );
    assert_eq!(probe.tail_next_grounded_dword_field_file_offset, 0x0f65);
    assert_eq!(probe.tail_second_grounded_dword_field_file_offset, 0x0f71);
    assert!(!probe.post_text_field_file_alignment_matches_grounded_dword_fields);
    assert_eq!(probe.nonzero_lanes[0].relative_offset, 0x04);
    assert_eq!(probe.nonzero_lanes[1].relative_offset, 0x0c);
    assert_eq!(probe.nonzero_lanes[2].relative_offset, 0x118);
    assert!(
        probe
            .nonzero_lanes
            .iter()
            .all(|lane| lane.probable_f32_le.is_some())
    );
}

#[test]
fn parses_post_text_field_neighborhood_probe() {
    let mut bytes = vec![0u8; POST_TEXT_FIELD_NEIGHBORHOOD_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());
    bytes[0x0f59] = 0x01;
    bytes[0x0f5d] = 0x02;
    bytes[0x0f61] = 0x03;
    bytes[0x0f6d] = 0x04;
    bytes[0x0f5c..0x0f60].copy_from_slice(&0x40f33333u32.to_le_bytes());
    bytes[0x0f6c..0x0f70].copy_from_slice(&0x40c08cfbu32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gms"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_post_text_field_neighborhood_probe(
        &bytes,
        Some("gms"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-scenario-save-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("post-text field neighborhood probe should parse");

    assert_eq!(probe.window_offset, POST_TEXT_FIELD_NEIGHBORHOOD_OFFSET);
    assert_eq!(
        probe.window_end_offset,
        POST_TEXT_FIELD_NEIGHBORHOOD_END_OFFSET
    );
    assert_eq!(probe.grounded_field_observations.len(), 6);
    assert_eq!(
        probe.grounded_field_observations[0].field_name,
        "Auto-Show Grade During Track Lay"
    );
    assert_eq!(probe.grounded_field_observations[0].value_u8, Some(0x01));
    assert_eq!(
        probe.grounded_field_observations[3].field_name,
        "leftover simulation time accumulator"
    );
    assert_eq!(probe.one_byte_early_float_candidates.len(), 2);
    assert_eq!(
        probe.one_byte_early_float_candidates[0].grounded_field_name,
        "Starting Building Density Level"
    );
    assert_eq!(
        probe.one_byte_early_float_candidates[0].candidate_offset_hex,
        "0x0f5c"
    );
    assert_eq!(
        probe.one_byte_early_float_candidates[1].grounded_field_name,
        "selected-year lane snapshot"
    );
    assert_eq!(
        probe.one_byte_early_float_candidates[1].candidate_offset_hex,
        "0x0f6c"
    );
}

#[test]
fn parses_locomotive_policy_neighborhood_probe() {
    let mut bytes = vec![0u8; LOCOMOTIVE_POLICY_NEIGHBORHOOD_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());
    bytes[0x0f78] = 0x01;
    bytes[0x0f7c] = 0x02;
    bytes[0x0f7d] = 0x03;
    bytes[0x0f7e] = 0x04;
    bytes[0x0f9c..0x0fa0].copy_from_slice(&0x42c1c036u32.to_le_bytes());
    bytes[0x0fa0..0x0fa4].copy_from_slice(&0x433a7abeu32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gms"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_locomotive_policy_neighborhood_probe(
        &bytes,
        Some("gms"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-scenario-save-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("locomotive policy neighborhood probe should parse");

    assert_eq!(probe.window_offset, LOCOMOTIVE_POLICY_NEIGHBORHOOD_OFFSET);
    assert_eq!(
        probe.window_end_offset,
        LOCOMOTIVE_POLICY_NEIGHBORHOOD_END_OFFSET
    );
    assert_eq!(probe.grounded_field_observations.len(), 9);
    assert_eq!(
        probe.grounded_field_observations[0].field_name,
        "selected-year bucket companion scalar"
    );
    assert_eq!(
        probe.grounded_field_observations[4].field_name,
        "All Steam Locos Avail."
    );
    assert_eq!(probe.grounded_field_observations[4].value_u8, Some(0x02));
    assert_eq!(
        probe.grounded_field_observations[8].field_name,
        "cached available-locomotive rating"
    );
    assert_eq!(probe.three_byte_early_float_candidates.len(), 2);
    assert_eq!(
        probe.three_byte_early_float_candidates[0].grounded_field_name,
        "station-list selected station id"
    );
    assert_eq!(
        probe.three_byte_early_float_candidates[0].candidate_offset_hex,
        "0x0f9c"
    );
    assert_eq!(
        probe.three_byte_early_float_candidates[1].grounded_field_name,
        "cached available-locomotive rating"
    );
    assert_eq!(
        probe.three_byte_early_float_candidates[1].candidate_offset_hex,
        "0x0fa0"
    );
}

#[test]
fn parses_pre_recipe_scalar_plateau_probe() {
    let mut bytes = vec![0u8; PRE_RECIPE_SCALAR_PLATEAU_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());
    bytes[0x0fa7..0x0fab].copy_from_slice(&0x82839300u32.to_le_bytes());
    bytes[0x0fab..0x0faf].copy_from_slice(&0x948c9949u32.to_le_bytes());
    bytes[0x0faf..0x0fb3].copy_from_slice(&0x8000003fu32.to_le_bytes());
    bytes[0x0fb3..0x0fb7].copy_from_slice(&0x75c28f3fu32.to_le_bytes());
    bytes[0x0fcb..0x0fcf].copy_from_slice(&0x00300000u32.to_le_bytes());
    bytes[0x0fdb..0x0fdf].copy_from_slice(&0x00ffea22u32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gms"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_pre_recipe_scalar_plateau_probe(
        &bytes,
        Some("gms"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-save-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("pre-recipe scalar plateau probe should parse");

    assert_eq!(probe.window_offset, PRE_RECIPE_SCALAR_PLATEAU_OFFSET);
    assert_eq!(
        probe.window_end_offset,
        PRE_RECIPE_SCALAR_PLATEAU_END_OFFSET
    );
    assert_eq!(probe.family_signature, "rt3-105-base-pre-recipe-plateau-v1");
    assert_eq!(probe.nonzero_lanes[0].absolute_offset_hex, "0x0fa7");
    assert_eq!(probe.nonzero_lanes[2].absolute_offset_hex, "0x0faf");
    assert_eq!(probe.nonzero_lanes[2].value_hex, "0x8000003f");
}

#[test]
fn parses_recipe_book_summary_probe() {
    let mut bytes = vec![0u8; RECIPE_BOOK_SUMMARY_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());

    let book0 = RECIPE_BOOK_ROOT_OFFSET;
    bytes[book0..book0 + 16].copy_from_slice(&[
        0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
        0x80,
    ]);
    bytes[book0 + RECIPE_BOOK_MAX_ANNUAL_PRODUCTION_OFFSET
        ..book0 + RECIPE_BOOK_MAX_ANNUAL_PRODUCTION_OFFSET + 4]
        .copy_from_slice(&0x41200000u32.to_le_bytes());
    bytes[book0 + RECIPE_BOOK_LINE_AREA_OFFSET
        ..book0 + RECIPE_BOOK_LINE_AREA_OFFSET + RECIPE_BOOK_LINE_AREA_LEN]
        .fill(0xcd);
    bytes[book0 + RECIPE_BOOK_LINE_AREA_OFFSET..book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 4]
        .copy_from_slice(&0x00000003u32.to_le_bytes());
    bytes[book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 4..book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 8]
        .copy_from_slice(&0x41a00000u32.to_le_bytes());
    bytes[book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 8..book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 12]
        .copy_from_slice(&0x00000017u32.to_le_bytes());
    bytes[book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 0x1c..book0 + RECIPE_BOOK_LINE_AREA_OFFSET + 0x20]
        .copy_from_slice(&0x0000002au32.to_le_bytes());

    let book1 = RECIPE_BOOK_ROOT_OFFSET + RECIPE_BOOK_STRIDE;
    bytes[book1 + RECIPE_BOOK_MAX_ANNUAL_PRODUCTION_OFFSET
        ..book1 + RECIPE_BOOK_MAX_ANNUAL_PRODUCTION_OFFSET + 4]
        .copy_from_slice(&0x00000000u32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gmp"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_recipe_book_summary_probe(
        &bytes,
        Some("gmp"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-map-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("recipe-book summary probe should parse");

    assert_eq!(probe.root_offset, RECIPE_BOOK_ROOT_OFFSET);
    assert_eq!(probe.book_count, RECIPE_BOOK_COUNT);
    assert_eq!(probe.book_stride, RECIPE_BOOK_STRIDE);
    assert_eq!(
        probe.max_annual_production_relative_offset,
        RECIPE_BOOK_MAX_ANNUAL_PRODUCTION_OFFSET
    );
    assert_eq!(probe.books[0].head_kind, "mixed");
    assert_eq!(probe.books[0].line_area_kind, "mixed");
    assert_eq!(probe.books[0].max_annual_production_word_hex, "0x41200000");
    assert_eq!(
        probe.books[0]
            .max_annual_production_probable_f32_le
            .as_deref(),
        Some("10.000000")
    );
    assert_eq!(probe.books[0].lines.len(), RECIPE_BOOK_LINE_COUNT);
    assert_eq!(probe.books[0].lines[0].line_kind, "mixed");
    assert_eq!(probe.books[0].lines[0].mode_word_hex, "0x00000003");
    assert_eq!(probe.books[0].lines[0].annual_amount_word_hex, "0x41a00000");
    assert_eq!(
        probe.books[0].lines[0]
            .annual_amount_probable_f32_le
            .as_deref(),
        Some("20.000000")
    );
    assert_eq!(
        probe.books[0].lines[0].supplied_cargo_token_word_hex,
        "0x00000017"
    );
    assert_eq!(
        probe.books[0].lines[0].supplied_cargo_token_window_hex,
        "17000000cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd2a000000"
    );
    assert_eq!(
        probe.books[0].lines[0].supplied_cargo_token_window_ascii,
        "....................*..."
    );
    assert!(probe.books[0].lines[0].supplied_cargo_token_active_in_runtime_import);
    assert_eq!(
        probe.books[0].lines[0].demanded_cargo_token_word_hex,
        "0x0000002a"
    );
    assert_eq!(
        probe.books[0].lines[0].demanded_cargo_token_window_hex,
        "2a000000cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
    );
    assert_eq!(
        probe.books[0].lines[0].demanded_cargo_token_window_ascii,
        "*..................."
    );
    assert!(probe.books[0].lines[0].demanded_cargo_token_active_in_runtime_import);
    assert_eq!(probe.books[1].head_kind, "zero");
    assert_eq!(probe.books[1].line_area_kind, "zero");
    assert_eq!(probe.books[1].lines[0].line_kind, "zero");
}

#[test]
fn decodes_probable_recipe_token_high16_ascii_stem() {
    assert_eq!(
        probable_recipe_token_high16_ascii_stem(0x72470000).as_deref(),
        Some("Gr")
    );
    assert_eq!(
        probable_recipe_token_high16_ascii_stem(0x68430000).as_deref(),
        Some("Ch")
    );
    assert_eq!(probable_recipe_token_high16_ascii_stem(0x000040a0), None);
    assert_eq!(probable_recipe_token_high16_ascii_stem(0x00170000), None);
}

#[test]
fn classifies_recipe_token_layouts() {
    assert_eq!(classify_recipe_token_layout(0x00000000), "zero");
    assert_eq!(
        classify_recipe_token_layout(0x72470000),
        "high16-ascii-stem"
    );
    assert_eq!(classify_recipe_token_layout(0x00170000), "high16-numeric");
    assert_eq!(classify_recipe_token_layout(0x000040a0), "low16-marker");
}

#[test]
fn classifies_recipe_line_signatures() {
    assert_eq!(
        classify_recipe_line_signature(0x00000000, 0x00000000, 0x00010000),
        "demand-numeric-entry"
    );
    assert_eq!(
        classify_recipe_line_signature(0x00000000, 0x00000000, 0x72470000),
        "demand-stem-entry"
    );
    assert_eq!(
        classify_recipe_line_signature(0x00000000, 0x00170000, 0x00000000),
        "supply-numeric-entry"
    );
    assert_eq!(
        classify_recipe_line_signature(0x00110000, 0x000040a0, 0x00000000),
        "supply-marker-entry"
    );
}

#[test]
fn classifies_recipe_runtime_import_branches() {
    assert_eq!(
        classify_recipe_runtime_import_branch(0),
        "zero-mode-skipped"
    );
    assert_eq!(
        classify_recipe_runtime_import_branch(1),
        "mode1-demand-branch"
    );
    assert_eq!(
        classify_recipe_runtime_import_branch(3),
        "mode3-dual-branch"
    );
    assert_eq!(
        classify_recipe_runtime_import_branch(0x00110000),
        "nonzero-supply-branch"
    );
}

#[test]
fn parses_nonzero_smp_aligned_runtime_rule_band() {
    let mut bytes = vec![0u8; POST_SPECIAL_CONDITIONS_SCALAR_END_OFFSET];
    let sentinel_offset = SPECIAL_CONDITIONS_OFFSET + SPECIAL_CONDITION_HIDDEN_SENTINEL_SLOT * 4;
    bytes[sentinel_offset..sentinel_offset + 4].copy_from_slice(&1u32.to_le_bytes());
    bytes[0x0df8..0x0dfc].copy_from_slice(&0x413d298cu32.to_le_bytes());
    bytes[0x0e00..0x0e04].copy_from_slice(&0x40e6b756u32.to_le_bytes());
    bytes[0x0e18..0x0e1c].copy_from_slice(&0x41d4ccceu32.to_le_bytes());
    bytes[0x0e24..0x0e28].copy_from_slice(&0x3fd2b549u32.to_le_bytes());

    let special_conditions_probe = parse_special_conditions_probe(&bytes, Some("gms"), None)
        .expect("special-conditions probe should parse");
    let probe = parse_smp_aligned_runtime_rule_band_probe(
        &bytes,
        Some("gms"),
        Some(&SmpContainerProfile {
            profile_family: "rt3-105-scenario-save-container-v1".to_string(),
            profile_evidence: vec![],
            is_known_profile: true,
        }),
        Some(&special_conditions_probe),
    )
    .expect("aligned runtime-rule band probe should parse");

    assert_eq!(probe.nonzero_band_indices, vec![35, 37, 39, 45, 48]);
    assert_eq!(
        probe.nonzero_post_window_overlap_band_indices,
        vec![37, 39, 45, 48]
    );
    assert_eq!(
        probe.nonzero_post_window_overlap_post_relative_offset_hexes,
        vec![
            "0x4".to_string(),
            "0xc".to_string(),
            "0x24".to_string(),
            "0x30".to_string()
        ]
    );
    assert_eq!(probe.nonzero_lanes[1].relative_offset, 0x94);
    assert_eq!(
        probe.nonzero_lanes[1].lane_kind,
        "unlabeled-editor-rule-dword"
    );
    assert!(probe.nonzero_lanes[1].probable_f32_le.is_some());
    assert_eq!(probe.nonzero_lanes.last().unwrap().band_index, 48);
}
