//! Tests for key encoding/decoding.

use super::*;

#[test]
fn test_validate_subject_rejects_null() {
    let result = validate_subject("has\x00null");
    assert!(result.is_err());
}

#[test]
fn test_validate_subject_rejects_empty() {
    let result = validate_subject("");
    assert!(result.is_err());
}

#[test]
fn test_validate_subject_accepts_normal() {
    validate_subject("Tesla").expect("normal subject should be valid");
    validate_subject("AAPL").expect("ticker should be valid");
    validate_subject("Earth::Moon").expect("colons should be valid");
}

#[test]
fn test_assertion_key() {
    let key = assertion_key("Tesla", "abc123");
    assert_eq!(key, b"Tesla\x00H:abc123");
}

#[test]
fn test_subject_index_key() {
    let key = subject_index_key("Tesla");
    assert_eq!(key, b"Tesla\x00S:");
}

#[test]
fn test_subject_predicate_key() {
    let key = subject_predicate_key("Tesla", "revenue");
    assert_eq!(key, b"Tesla\x00SP:revenue");
}

#[test]
fn test_mv_key() {
    let key = mv_key("Tesla", "revenue");
    assert_eq!(key, b"Tesla\x00MV:revenue");
}

#[test]
fn test_vote_key() {
    let key = vote_key("Tesla", "aaa", "bbb");
    assert_eq!(key, b"Tesla\x00V:aaa:bbb");
}

#[test]
fn test_vote_scan_prefix() {
    let key = vote_scan_prefix("Tesla", "aaa");
    assert_eq!(key, b"Tesla\x00V:aaa:");
}

#[test]
fn test_vote_count_key() {
    let key = vote_count_key("Tesla", "aaa");
    assert_eq!(key, b"Tesla\x00VC:aaa");
}

#[test]
fn test_vote_weight_key() {
    let key = vote_weight_key("Tesla", "aaa");
    assert_eq!(key, b"Tesla\x00VW:aaa");
}

#[test]
fn test_gold_standard_key() {
    let key = gold_standard_key("Earth", "has_shape");
    assert_eq!(key, b"Earth\x00GS:has_shape");
}

#[test]
fn test_trust_rank_key() {
    let key = trust_rank_key("abc123");
    assert_eq!(key, b"\x00TRUST:abc123");
}

#[test]
fn test_quota_key() {
    let key = quota_key("abc", 1705314000);
    assert_eq!(key, b"\x00QUOTA:abc:1705314000");
}

#[test]
fn test_quota_limit_key() {
    let key = quota_limit_key("abc");
    assert_eq!(key, b"\x00QLIMIT:abc");
}

#[test]
fn test_epoch_key() {
    let key = epoch_key("deadbeef");
    assert_eq!(key, b"\x00E:deadbeef");
}

#[test]
fn test_superseded_key() {
    let key = superseded_key("deadbeef");
    assert_eq!(key, b"\x00SUPERSEDED:deadbeef");
}

#[test]
fn test_supersession_key() {
    let key = supersession_key("deadbeef");
    assert_eq!(key, b"\x00SUP:deadbeef");
}

#[test]
fn test_audit_key() {
    let key = audit_key("abc123");
    assert_eq!(key, b"\x00AUD:abc123");
}

#[test]
fn test_escalation_key() {
    let key = escalation_key(1000, "abc123");
    assert_eq!(key, b"\x00ESC:1000:abc123");
}

#[test]
fn test_trust_pack_key() {
    let key = trust_pack_key(&[1u8; 32]);
    assert_eq!(&key[..4], b"\x00TP:");
    assert_eq!(&key[4..], &[1u8; 32]);
}

#[test]
fn test_cursor_key() {
    let key = cursor_key();
    assert_eq!(key, b"\x00META:cursor:ingest");
}

#[test]
fn test_assertion_count_key() {
    let key = assertion_count_key();
    assert_eq!(key, b"\x00META:assertion_count");
}

#[test]
fn test_subjects_index_key() {
    let key = subjects_index_key("Tesla");
    assert_eq!(key, b"\x00SUBJECTS:Tesla");
}

#[test]
fn test_gs_list_key() {
    let key = gs_list_key("Earth", "has_shape");
    assert_eq!(key, b"\x00GS_LIST:Earth:has_shape");
}

#[test]
fn test_hash_subject_key() {
    let key = hash_subject_key("abc123");
    assert_eq!(key, b"\x00HASH_SUBJECT:abc123");
}

#[test]
fn test_gs_verified_key() {
    let key = gs_verified_key("abc", "Earth", "has_shape");
    assert_eq!(key, b"\x00GS_VERIFIED:abc:Earth:has_shape");
}

#[test]
fn test_subject_scan_prefix() {
    let prefix = subject_scan_prefix("Tesla");
    assert_eq!(prefix, b"Tesla\x00");
}

#[test]
fn test_extract_tag_global() {
    let key = b"\x00TRUST:abc123";
    assert_eq!(extract_tag(key), b"TRUST:abc123");
}

#[test]
fn test_extract_tag_subject() {
    let key = b"Tesla\x00H:abc123";
    assert_eq!(extract_tag(key), b"H:abc123");
}

#[test]
fn test_is_global_key() {
    assert!(is_global_key(b"\x00TRUST:abc"));
    assert!(!is_global_key(b"Tesla\x00H:abc"));
    assert!(!is_global_key(b"plain_key"));
}

#[test]
fn test_extract_subject() {
    assert_eq!(extract_subject(b"Tesla\x00H:abc"), Some("Tesla"));
    assert_eq!(extract_subject(b"Earth\x00GS:pred"), Some("Earth"));
    assert_eq!(extract_subject(b"\x00TRUST:abc"), None);
    assert_eq!(extract_subject(b"no_separator"), None);
}

#[test]
fn test_subject_colocation() {
    // All Tesla keys should share the same prefix for range sharding
    let h = assertion_key("Tesla", "abc");
    let s = subject_index_key("Tesla");
    let sp = subject_predicate_key("Tesla", "revenue");
    let mv = mv_key("Tesla", "revenue");
    let v = vote_key("Tesla", "abc", "def");
    let vc = vote_count_key("Tesla", "abc");
    let vw = vote_weight_key("Tesla", "abc");
    let gs = gold_standard_key("Tesla", "stock_price");

    let prefix = b"Tesla\x00";
    assert!(h.starts_with(prefix));
    assert!(s.starts_with(prefix));
    assert!(sp.starts_with(prefix));
    assert!(mv.starts_with(prefix));
    assert!(v.starts_with(prefix));
    assert!(vc.starts_with(prefix));
    assert!(vw.starts_with(prefix));
    assert!(gs.starts_with(prefix));
}

#[test]
fn test_global_keys_sort_first() {
    // Global keys (\x00...) sort before subject keys (a-z...)
    let global = trust_rank_key("abc");
    let subject = assertion_key("Apple", "abc");
    assert!(global < subject, "Global keys should sort before subject keys");
}
