//! Key extraction and parsing utilities.
//!
//! Functions to decode and extract information from storage keys.

use super::SEPARATOR;

/// Extract subject from a `\x00SUBJECTS:{subject}` key.
///
/// Returns the subject string, or `None` if the key doesn't match the expected format.
pub fn extract_subject_from_subjects_key(key: &[u8]) -> Option<String> {
    let prefix = b"\x00SUBJECTS:";
    if key.starts_with(prefix) {
        std::str::from_utf8(&key[prefix.len()..]).ok().map(|s| s.to_string())
    } else {
        None
    }
}

/// Extract subject and predicate from a `{subject}\x00SP:{predicate}` key.
///
/// Returns `(subject, predicate)` or `None` if the key doesn't match.
pub fn extract_sp_key(key: &[u8]) -> Option<(String, String)> {
    // Find the \x00 separator
    let sep_pos = memchr::memchr(SEPARATOR, key)?;
    if sep_pos == 0 {
        return None; // Global key, not subject-prefixed
    }

    let subject = std::str::from_utf8(&key[..sep_pos]).ok()?;
    let after_sep = &key[sep_pos + 1..];

    // Check for SP: tag
    if !after_sep.starts_with(b"SP:") {
        return None;
    }

    let predicate = std::str::from_utf8(&after_sep[3..]).ok()?;
    if subject.is_empty() || predicate.is_empty() {
        return None;
    }

    Some((subject.to_string(), predicate.to_string()))
}

/// Extract the tag portion from a key (the part after the separator).
///
/// For subject-prefixed keys: returns bytes after `{subject}\x00`
/// For global keys: returns bytes after `\x00`
pub fn extract_tag(key: &[u8]) -> &[u8] {
    if key.first() == Some(&SEPARATOR) {
        // Global key: \x00TAG:rest
        &key[1..]
    } else if let Some(pos) = memchr::memchr(SEPARATOR, key) {
        // Subject-prefixed: subject\x00TAG:rest
        &key[pos + 1..]
    } else {
        key
    }
}

/// Check if a key is a global key (starts with `\x00`).
pub fn is_global_key(key: &[u8]) -> bool {
    key.first() == Some(&SEPARATOR)
}

/// Extract the subject from a subject-prefixed key.
///
/// Returns `None` for global keys or keys without a separator.
pub fn extract_subject(key: &[u8]) -> Option<&str> {
    if is_global_key(key) {
        return None;
    }
    if let Some(pos) = memchr::memchr(SEPARATOR, key) {
        std::str::from_utf8(&key[..pos]).ok()
    } else {
        None
    }
}

/// Extract alias path from a `\x00CA:{alias_path}` key.
///
/// Returns the alias path string, or `None` if the key doesn't match the expected format.
pub fn extract_alias_path(key: &[u8]) -> Option<String> {
    let prefix = b"\x00CA:";
    if key.starts_with(prefix) {
        std::str::from_utf8(&key[prefix.len()..]).ok().map(|s| s.to_string())
    } else {
        None
    }
}
