//! API key storage keys (P4.2 Authentication).
//!
//! Format: `\x00APIKEY:{suffix}`

use super::builders::global_key;

/// API key record key: `\x00APIKEY:{key_hash_hex}`
pub fn api_key_record_key(key_hash_hex: &str) -> Vec<u8> {
    global_key(b"APIKEY:", key_hash_hex.as_bytes())
}

/// API key rate limit key: `\x00APIKEY:RATE:{key_hash_hex}:{window}`
pub fn api_key_rate_key(key_hash_hex: &str, window: u64) -> Vec<u8> {
    let suffix = format!("RATE:{}:{}", key_hash_hex, window);
    global_key(b"APIKEY:", suffix.as_bytes())
}

/// API key scan prefix: `\x00APIKEY:`
///
/// Note: This will scan both records and rate limit entries.
/// To scan only records, filter out keys containing ":RATE:".
pub fn api_key_scan_prefix() -> Vec<u8> {
    global_key(b"APIKEY:", b"")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_api_key_record_key() {
        let key_hash_hex = "abcd1234";
        let key = api_key_record_key(key_hash_hex);
        // \x00APIKEY:abcd1234
        assert!(key.starts_with(&[0x00]));
        assert!(key.windows(7).any(|w| w == b"APIKEY:"));
        assert!(key.ends_with(b"abcd1234"));
    }

    #[test]
    fn test_api_key_rate_key() {
        let key_hash_hex = "abcd1234";
        let window = 1705314000;
        let key = api_key_rate_key(key_hash_hex, window);
        // \x00APIKEY:RATE:abcd1234:1705314000
        let key_str = String::from_utf8_lossy(&key[1..]);
        assert!(key_str.contains("RATE:"));
        assert!(key_str.contains("abcd1234"));
        assert!(key_str.contains("1705314000"));
    }

    #[test]
    fn test_api_key_scan_prefix() {
        let prefix = api_key_scan_prefix();
        // \x00APIKEY:
        assert_eq!(prefix, vec![0x00, b'A', b'P', b'I', b'K', b'E', b'Y', b':']);
    }

    #[test]
    fn test_record_key_is_under_scan_prefix() {
        let prefix = api_key_scan_prefix();
        let record_key = api_key_record_key("abcd");
        let rate_key = api_key_rate_key("abcd", 123);

        assert!(record_key.starts_with(&prefix));
        assert!(rate_key.starts_with(&prefix));
    }
}
