use super::*;
use obikseq::Sequence;
use obikseq::kmer::Kmer;

const K: usize = 21;
const LEVEL_MAX: usize = 6;

fn kmer_from_ascii(seq: &[u8]) -> CanonicalKmer {
    obikseq::set_k(K);
    Kmer::from_ascii(seq).expect("valid k-mer sequence").canonical()
}

#[test]
fn homopolymer_scores_lower_than_diverse_sequence() {
    let homopolymer = kmer_from_ascii(b"AAAAAAAAAAAAAAAAAAAAA"); // 21 bases
    let diverse = kmer_from_ascii(b"CATTAGCGTACCTGATCAGGT"); // 21 bases, same as used elsewhere in this workspace's tests

    let e_homopolymer = homopolymer.entropy(LEVEL_MAX);
    let e_diverse = diverse.entropy(LEVEL_MAX);

    assert!(
        e_homopolymer < e_diverse,
        "homopolymer ({e_homopolymer}) should score lower than a diverse sequence ({e_diverse})"
    );
    // A pure homopolymer is the most degenerate case representable — its
    // score should sit near the bottom of the range, not just "somewhat lower".
    assert!(e_homopolymer < 0.3, "homopolymer entropy unexpectedly high: {e_homopolymer}");
}

#[test]
fn entropy_is_deterministic_for_the_same_kmer() {
    let a = kmer_from_ascii(b"CATTAGCGTACCTGATCAGGT");
    let b = kmer_from_ascii(b"CATTAGCGTACCTGATCAGGT");
    assert_eq!(a.entropy(LEVEL_MAX), b.entropy(LEVEL_MAX));
}

#[test]
fn entropy_is_within_zero_one_range() {
    let mut repeat = "AT".repeat(K / 2 + 1);
    repeat.truncate(K);

    for seq in [
        "AAAAAAAAAAAAAAAAAAAAA".to_string(),
        repeat,
        "CATTAGCGTACCTGATCAGGT".to_string(),
    ] {
        assert_eq!(seq.len(), K, "test sequence must be exactly K bases: {seq:?}");
        let kmer = kmer_from_ascii(seq.as_bytes());
        let e = kmer.entropy(LEVEL_MAX);
        assert!((0.0..=1.0).contains(&e), "entropy {e} out of [0,1] for {seq:?}");
    }
}
