mod common;

use sqpack_rs::eid::{EID_MAX_ENTRIES, Eid, EidVersion};
use sqpack_rs::{DatFile, Index, SqPackPayload};

fn looks_like_eid(bytes: &[u8]) -> bool {
    bytes.len() >= 4 && &bytes[0..4] == b"eid\0"
}

#[test]
#[ignore = "requires real FFXIV install; run with `cargo test -- --ignored`"]
fn scanned_eid_files_parse_and_expose_typed_entries() {
    let Some(data_dir) = common::maybe_data_dir() else {
        eprintln!("skipping: no sqpack data available (set SQPACK_TEST_DATA_DIR)");
        return;
    };

    let dat_path = data_dir.join("040000.win32.dat0");
    let idx_path = data_dir.join("040000.win32.index");

    if !dat_path.exists() || !idx_path.exists() {
        eprintln!("skipping: 040000.win32.dat0 or .index not found");
        return;
    }

    let idx = Index::open(&idx_path).expect("Index::open");
    let mut dat = DatFile::open(&dat_path).expect("DatFile::open");

    let mut checked = 0usize;
    let target = 3usize;
    let mut eid_count = 0usize;

    'outer: for entry in idx
        .entries()
        .iter()
        .filter(|e| !e.is_synonym() && e.data_file_id() == 0)
        .take(5000)
    {
        let Ok(SqPackPayload::Standard(payload)) = dat.read_file_typed(entry.byte_offset()) else {
            continue;
        };

        if !looks_like_eid(&payload) {
            continue;
        }
        eid_count += 1;

        let eid = match Eid::parse(&payload) {
            Ok(e) => e,
            Err(e) => panic!("Eid::parse failed for hash {:#018x}: {e}", entry.hash),
        };

        let version = eid.version();
        assert!(
            matches!(version, EidVersion::V1 | EidVersion::Old),
            "version must be V1 or Old, got {version:?}"
        );

        let entries = eid.entries();
        assert!(
            !entries.is_empty(),
            "retail EID for hash {:#018x} unexpectedly has zero entries",
            entry.hash,
        );
        let entries_len_u32 =
            u32::try_from(entries.len()).expect("entry count fits u32 (capped at EID_MAX_ENTRIES)");
        assert!(
            entries_len_u32 <= EID_MAX_ENTRIES,
            "entry count {} exceeds defensive cap {}",
            entries.len(),
            EID_MAX_ENTRIES,
        );

        for (idx, e) in entries.iter().enumerate() {
            assert!(
                !e.name.is_empty(),
                "EID {:#018x} entry {} has an empty bone name",
                entry.hash,
                idx,
            );
        }

        checked += 1;
        eprintln!(
            "  eid {checked}: hash={:#018x} version={version:?} count={} \
             first_bone={:?} first_id={}",
            entry.hash,
            entries.len(),
            entries[0].name,
            entries[0].id,
        );
        if checked >= target {
            break 'outer;
        }
    }

    eprintln!(
        "scanned_eid: found {eid_count} eid-magic entry/entries in first 5000 entries of \
         040000.win32 ({checked} structurally validated)"
    );
}
