mod common;

use sqpack_rs::hash::{hash_index1_key, hash_index2};
use sqpack_rs::{Index, Index2};

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

    let index_path = dir.join("0a0000.win32.index");
    if !index_path.exists() {
        eprintln!("skipping: {} not present", index_path.display());
        return;
    }

    let idx = Index::open(&index_path).expect("Index::open should succeed");
    let key = hash_index1_key("exd/root.exl");

    let entry = idx.get(key).unwrap_or_else(|| {
        panic!(
            "exd/root.exl (v1 key {key:#018x}) not found in {}",
            index_path.display()
        )
    });

    assert!(
        !entry.is_synonym(),
        "exd/root.exl must not be a synonym entry"
    );
    let loc = entry
        .dat_location()
        .expect("non-synonym entry must have a dat location");
    eprintln!(
        "exd/root.exl v1: key={key:#018x} dat{} @ {:#x}",
        loc.data_file_id, loc.byte_offset
    );
}

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

    let index2_path = dir.join("0a0000.win32.index2");
    if !index2_path.exists() {
        eprintln!("skipping: {} not present", index2_path.display());
        return;
    }

    let idx2 = Index2::open(&index2_path).expect("Index2::open should succeed");
    let key = hash_index2("exd/root.exl");

    let entry = idx2.get(key).unwrap_or_else(|| {
        panic!(
            "exd/root.exl (v2 key {key:#010x}) not found in {}",
            index2_path.display()
        )
    });

    let loc = entry.dat_location();
    eprintln!(
        "exd/root.exl v2: key={key:#010x} dat{} @ {:#x}",
        loc.data_file_id, loc.byte_offset
    );
}

#[test]
#[ignore = "requires real FFXIV .index and .index2 files; run with `cargo test -- --ignored`"]
fn v1_and_v2_agree_on_dat_location_for_root_exl() {
    let Some(dir) = common::maybe_data_dir() else {
        eprintln!("skipping: no sqpack data available (set SQPACK_TEST_DATA_DIR)");
        return;
    };

    let index_path = dir.join("0a0000.win32.index");
    let index2_path = dir.join("0a0000.win32.index2");

    if !index_path.exists() || !index2_path.exists() {
        eprintln!("skipping: one or both index files not present");
        return;
    }

    let idx = Index::open(&index_path).expect("Index::open");
    let idx2 = Index2::open(&index2_path).expect("Index2::open");

    let v1_key = hash_index1_key("exd/root.exl");
    let v2_key = hash_index2("exd/root.exl");

    let v1_entry = idx.get(v1_key).expect("exd/root.exl not found in .index");
    let v2_entry = idx2.get(v2_key).expect("exd/root.exl not found in .index2");

    let v1_loc = v1_entry
        .dat_location()
        .expect("v1 entry must not be a synonym");
    let v2_loc = v2_entry.dat_location();

    assert_eq!(
        v1_loc.data_file_id, v2_loc.data_file_id,
        "v1 and v2 must agree on data_file_id for exd/root.exl"
    );
    assert_eq!(
        v1_loc.byte_offset, v2_loc.byte_offset,
        "v1 and v2 must agree on byte_offset for exd/root.exl"
    );
    eprintln!(
        "v1 and v2 agree: dat{} @ {:#x}",
        v1_loc.data_file_id, v1_loc.byte_offset
    );
}
