//! Authoritative corpus creation for Aphoria.
//!
//! Provides functions to create pre-built authoritative assertions
//! for common security patterns (TLS, JWT, CORS, etc.).

use std::time::{SystemTime, UNIX_EPOCH};

use blake3::Hasher;
use ed25519_dalek::{Signer, SigningKey};
use stemedb_core::types::{
    Assertion, HlcTimestamp, LifecycleStage, ObjectValue, SignatureEntry, SourceClass,
};

/// Get the current Unix timestamp in seconds.
///
/// This is the canonical timestamp function for Aphoria. Use this instead of
/// inline `SystemTime::now()` or `Utc::now().timestamp()` calls.
///
/// For millisecond precision, use `current_timestamp_millis()`.
pub fn current_timestamp() -> u64 {
    SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0)
}

/// Get the current Unix timestamp in milliseconds.
///
/// Use this when millisecond precision is needed (e.g., performance timing).
pub fn current_timestamp_millis() -> u128 {
    SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_millis()).unwrap_or(0)
}

/// Create authoritative assertions for the RFC/OWASP corpus.
#[allow(clippy::vec_init_then_push)]
pub fn create_authoritative_corpus(signing_key: &SigningKey) -> Vec<Assertion> {
    let timestamp = current_timestamp();
    let mut assertions = Vec::new();

    // TLS verification requirements
    assertions.push(create_authoritative_assertion(
        signing_key,
        "rfc://5246/tls/cert_verification",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Regulatory,
        "TLS certificate verification MUST be enabled (RFC 5246)",
        timestamp,
    ));

    // OWASP TLS guidance
    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://transport_layer/tls/cert_verification",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Clinical, // Tier 1
        "OWASP: Always verify TLS certificates",
        timestamp,
    ));

    // JWT audience validation (RFC 7519)
    assertions.push(create_authoritative_assertion(
        signing_key,
        "rfc://7519/jwt/audience_validation",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Regulatory,
        "JWT audience claim MUST be validated (RFC 7519 Section 4.1.3)",
        timestamp,
    ));

    // JWT expiry validation
    assertions.push(create_authoritative_assertion(
        signing_key,
        "rfc://7519/jwt/expiry_validation",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Regulatory,
        "JWT expiry claim MUST be validated (RFC 7519 Section 4.1.4)",
        timestamp,
    ));

    // JWT signature verification
    assertions.push(create_authoritative_assertion(
        signing_key,
        "rfc://7519/jwt/signature_verification",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Regulatory,
        "JWT signatures MUST be verified (RFC 7519)",
        timestamp,
    ));

    // JWT algorithm restriction
    assertions.push(create_authoritative_assertion(
        signing_key,
        "rfc://7519/jwt/algorithm_restriction",
        "config_value",
        ObjectValue::Text("explicit_list".to_string()),
        SourceClass::Regulatory,
        "JWT algorithm MUST be explicitly specified, 'none' algorithm forbidden",
        timestamp,
    ));

    // OWASP secrets management
    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://secrets/api_key",
        "storage_method",
        ObjectValue::Text("environment_or_vault".to_string()),
        SourceClass::Clinical,
        "OWASP: Never hardcode API keys in source code",
        timestamp,
    ));

    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://secrets/password",
        "storage_method",
        ObjectValue::Text("environment_or_vault".to_string()),
        SourceClass::Clinical,
        "OWASP: Never hardcode passwords in source code",
        timestamp,
    ));

    // CORS security
    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://cors/allow_origin",
        "config_value",
        ObjectValue::Text("explicit_list".to_string()),
        SourceClass::Clinical,
        "OWASP: Never use wildcard (*) for CORS Allow-Origin in production",
        timestamp,
    ));

    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://cors/credentials_with_wildcard",
        "enabled",
        ObjectValue::Boolean(false),
        SourceClass::Regulatory,
        "CORS credentials MUST NOT be allowed with wildcard origin (security vulnerability)",
        timestamp,
    ));

    // Rate limiting
    assertions.push(create_authoritative_assertion(
        signing_key,
        "owasp://rate_limit/enabled",
        "enabled",
        ObjectValue::Boolean(true),
        SourceClass::Clinical,
        "OWASP: Rate limiting SHOULD be enabled for API endpoints",
        timestamp,
    ));

    assertions
}

/// Create a signed authoritative assertion.
///
/// This helper is used by corpus builders to create signed assertions with
/// consistent structure and metadata.
pub fn create_authoritative_assertion(
    signing_key: &SigningKey,
    subject: &str,
    predicate: &str,
    object: ObjectValue,
    source_class: SourceClass,
    description: &str,
    timestamp: u64,
) -> Assertion {
    // Compute source hash
    let mut hasher = Hasher::new();
    hasher.update(subject.as_bytes());
    hasher.update(predicate.as_bytes());
    hasher.update(description.as_bytes());
    let source_hash = *hasher.finalize().as_bytes();

    // Create signature
    let message = format!("{}:{}", subject, predicate);
    let signature = signing_key.sign(message.as_bytes());
    let verifying_key = signing_key.verifying_key();

    let signature_entry = SignatureEntry {
        agent_id: verifying_key.to_bytes(),
        signature: signature.to_bytes(),
        timestamp,
        version: 1,
    };

    let source_metadata = serde_json::json!({
        "description": description,
        "source": "authoritative_corpus",
    });

    Assertion {
        subject: subject.to_string(),
        predicate: predicate.to_string(),
        object,
        parent_hash: None,
        source_hash,
        source_class,
        visual_hash: None,
        epoch: None,
        source_metadata: serde_json::to_vec(&source_metadata).ok(),
        lifecycle: LifecycleStage::Approved,
        signatures: vec![signature_entry],
        confidence: 1.0,
        timestamp,
        hlc_timestamp: HlcTimestamp::default(),
        vector: None,
    }
}
