use crate::inspect::smp::regions::*;
use crate::inspect::smp::*;

pub(in crate::inspect::smp) fn parse_save_region_queued_notice_record_probe(
    bytes: &[u8],
    file_extension_hint: Option<&str>,
    container_profile: Option<&SmpContainerProfile>,
    region_header_probe: Option<&SmpSaveTaggedCollectionHeaderProbe>,
) -> Option<SmpSaveRegionQueuedNoticeRecordProbe> {
    if file_extension_hint != Some("gms") {
        return None;
    }
    let profile = container_profile?;
    let max_region_id = region_header_probe
        .map(|probe| probe.live_id_bound)
        .unwrap_or(0x1000);
    let entries = find_u32_le_offsets(bytes, SAVE_REGION_QUEUED_NOTICE_PAYLOAD_SEED)
        .into_iter()
        .filter_map(|payload_seed_offset| {
            let node_base_offset = payload_seed_offset.checked_sub(4)?;
            let _node_bytes = bytes
                .get(node_base_offset..node_base_offset + SAVE_REGION_QUEUED_NOTICE_NODE_LEN)?;
            let next_link_raw = read_u32_at(bytes, node_base_offset)?;
            let kind = read_u32_at(bytes, node_base_offset + 8)?;
            let promotion_latch_dword = read_u32_at(bytes, node_base_offset + 12)?;
            let region_id = read_u32_at(bytes, node_base_offset + 16)?;
            let amount = read_u32_at(bytes, node_base_offset + 20)?;
            let trailing_sentinel_i32_0 = read_i32_at(bytes, node_base_offset + 24)?;
            let trailing_sentinel_i32_1 = read_i32_at(bytes, node_base_offset + 28)?;
            if !(kind == SAVE_REGION_QUEUED_NOTICE_NODE_KIND
                && promotion_latch_dword == 0
                && region_id >= 1
                && region_id <= max_region_id
                && amount > 0
                && trailing_sentinel_i32_0 == -1
                && trailing_sentinel_i32_1 == -1)
            {
                return None;
            }
            Some(SmpSaveRegionQueuedNoticeRecordEntryProbe {
                node_base_offset,
                payload_seed_offset,
                next_link_raw,
                next_link_raw_hex: format!("0x{next_link_raw:08x}"),
                payload_seed_dword: SAVE_REGION_QUEUED_NOTICE_PAYLOAD_SEED,
                payload_seed_dword_hex: format!("0x{SAVE_REGION_QUEUED_NOTICE_PAYLOAD_SEED:08x}"),
                kind,
                kind_hex: format!("0x{kind:08x}"),
                promotion_latch_dword,
                promotion_latch_dword_hex: format!("0x{promotion_latch_dword:08x}"),
                region_id,
                region_id_hex: format!("0x{region_id:08x}"),
                amount,
                amount_hex: format!("0x{amount:08x}"),
                trailing_sentinel_i32_0,
                trailing_sentinel_i32_0_hex: format!("0x{:08x}", trailing_sentinel_i32_0 as u32),
                trailing_sentinel_i32_1,
                trailing_sentinel_i32_1_hex: format!("0x{:08x}", trailing_sentinel_i32_1 as u32),
            })
        })
        .collect::<Vec<_>>();
    if entries.is_empty() {
        return None;
    }
    Some(SmpSaveRegionQueuedNoticeRecordProbe {
        profile_family: profile.profile_family.clone(),
        source_kind: "save-region-queued-notice-records".to_string(),
        semantic_family: "scenario-save-region-queued-notice-records".to_string(),
        payload_seed_dword: SAVE_REGION_QUEUED_NOTICE_PAYLOAD_SEED,
        payload_seed_dword_hex: format!("0x{SAVE_REGION_QUEUED_NOTICE_PAYLOAD_SEED:08x}"),
        entries,
        evidence: vec![
            "save-side scan searches for the grounded region queued-notice payload seed 0x005c87a8 and validates the full 0x20-byte node shape from the atlas-backed queue owner".to_string(),
            "accepted nodes require kind=7, promotion-latch dword=0, a bounded live region id, a positive amount, and trailing sentinel dwords -1/-1".to_string(),
        ],
    })
}
