//! Subject-prefixed keys — co-located by subject for range sharding.
//!
//! Format: `{subject}\x00{TAG}:{suffix}`

use super::builders::subject_key;
use super::SEPARATOR;

/// Assertion key: `{subject}\x00H:{hash_hex}`
pub fn assertion_key(subject: &str, hash_hex: &str) -> Vec<u8> {
    subject_key(subject, b"H:", hash_hex.as_bytes())
}

/// Subject index key: `{subject}\x00S:`
pub fn subject_index_key(subject: &str) -> Vec<u8> {
    subject_key(subject, b"S:", b"")
}

/// Subject+predicate index key: `{subject}\x00SP:{predicate}`
pub fn subject_predicate_key(subject: &str, predicate: &str) -> Vec<u8> {
    subject_key(subject, b"SP:", predicate.as_bytes())
}

/// Materialized view key: `{subject}\x00MV:{predicate}`
pub fn mv_key(subject: &str, predicate: &str) -> Vec<u8> {
    subject_key(subject, b"MV:", predicate.as_bytes())
}

/// Vote key: `{subject}\x00V:{assert_hex}:{vote_hex}`
pub fn vote_key(subject: &str, assertion_hex: &str, vote_hex: &str) -> Vec<u8> {
    let suffix = format!("{}:{}", assertion_hex, vote_hex);
    subject_key(subject, b"V:", suffix.as_bytes())
}

/// Vote scan prefix: `{subject}\x00V:{assert_hex}:`
pub fn vote_scan_prefix(subject: &str, assertion_hex: &str) -> Vec<u8> {
    let suffix = format!("{}:", assertion_hex);
    subject_key(subject, b"V:", suffix.as_bytes())
}

/// Vote count cache key: `{subject}\x00VC:{assert_hex}`
pub fn vote_count_key(subject: &str, assertion_hex: &str) -> Vec<u8> {
    subject_key(subject, b"VC:", assertion_hex.as_bytes())
}

/// Vote weight cache key: `{subject}\x00VW:{assert_hex}`
pub fn vote_weight_key(subject: &str, assertion_hex: &str) -> Vec<u8> {
    subject_key(subject, b"VW:", assertion_hex.as_bytes())
}

/// Vote count scan prefix: `{subject}\x00VC:` - for scanning all vote counts under a subject.
pub fn vote_count_prefix(subject: &str) -> Vec<u8> {
    subject_key(subject, b"VC:", b"")
}

/// Assertion scan prefix: `{subject}\x00H:` - for scanning all assertions under a subject.
pub fn assertion_prefix(subject: &str) -> Vec<u8> {
    subject_key(subject, b"H:", b"")
}

/// Gold standard key: `{subject}\x00GS:{predicate}`
pub fn gold_standard_key(subject: &str, predicate: &str) -> Vec<u8> {
    subject_key(subject, b"GS:", predicate.as_bytes())
}

/// Subject+predicate scan prefix: `{subject}\x00SP:` — returns all SP keys for a subject.
pub fn subject_predicate_scan_prefix(subject: &str) -> Vec<u8> {
    subject_key(subject, b"SP:", b"")
}

/// Subject scan prefix: `{subject}\x00` — returns ALL data for a subject.
pub fn subject_scan_prefix(subject: &str) -> Vec<u8> {
    let mut key = Vec::with_capacity(subject.len() + 1);
    key.extend_from_slice(subject.as_bytes());
    key.push(SEPARATOR);
    key
}

/// Pack source key: `{subject}\x00PKS:` — stores which Trust Pack an assertion came from.
pub fn pack_source_key(subject: &str) -> Vec<u8> {
    subject_key(subject, b"PKS:", b"")
}

// ── Pattern Aggregate Keys (Community Corpus) ──────────────────────────

/// Pattern aggregate key: `{subject}\x00PA:{predicate}:{value_hash}`
///
/// Stores the aggregated pattern data for a (subject, predicate, value) triple.
pub fn pattern_aggregate_key(subject: &str, predicate: &str, value_hash: &str) -> Vec<u8> {
    let suffix = format!("{}:{}", predicate, value_hash);
    subject_key(subject, b"PA:", suffix.as_bytes())
}

/// Pattern project count key: `{subject}\x00PC:{predicate}:{value_hash}`
///
/// Stores the count of distinct projects that reported this pattern.
pub fn pattern_project_count_key(subject: &str, predicate: &str, value_hash: &str) -> Vec<u8> {
    let suffix = format!("{}:{}", predicate, value_hash);
    subject_key(subject, b"PC:", suffix.as_bytes())
}

/// Pattern observation count key: `{subject}\x00PO:{predicate}:{value_hash}`
///
/// Stores the total count of observations for this pattern.
pub fn pattern_observation_count_key(subject: &str, predicate: &str, value_hash: &str) -> Vec<u8> {
    let suffix = format!("{}:{}", predicate, value_hash);
    subject_key(subject, b"PO:", suffix.as_bytes())
}

/// Pattern project set key: `{subject}\x00PS:{predicate}:{value_hash}:{project_hash}`
///
/// Tracks which projects have reported this pattern (for deduplication).
/// Each project_hash gets its own key entry.
pub fn pattern_project_set_key(
    subject: &str,
    predicate: &str,
    value_hash: &str,
    project_hash: &str,
) -> Vec<u8> {
    let suffix = format!("{}:{}:{}", predicate, value_hash, project_hash);
    subject_key(subject, b"PS:", suffix.as_bytes())
}

/// Pattern aggregate scan prefix: `{subject}\x00PA:` — scan all patterns for a subject.
pub fn pattern_aggregate_scan_prefix(subject: &str) -> Vec<u8> {
    subject_key(subject, b"PA:", b"")
}

/// Pattern project set scan prefix: `{subject}\x00PS:{predicate}:{value_hash}:`
pub fn pattern_project_set_scan_prefix(
    subject: &str,
    predicate: &str,
    value_hash: &str,
) -> Vec<u8> {
    let suffix = format!("{}:{}:", predicate, value_hash);
    subject_key(subject, b"PS:", suffix.as_bytes())
}
