//! Tests for quality validation.

use super::*;
use crate::research::researcher::ResearchedClaim;
use stemedb_core::types::ObjectValue;

fn make_claim(subject: &str, description: &str, source_url: &str) -> ResearchedClaim {
    ResearchedClaim {
        subject: subject.to_string(),
        predicate: "enabled".to_string(),
        value: ObjectValue::Boolean(true),
        description: description.to_string(),
        source_url: source_url.to_string(),
        source_section: "Section 1".to_string(),
        confidence: 0.9,
        tier: 1,
    }
}

#[test]
fn test_valid_claim_passes() {
    let validator = QualityValidator::default();

    let claim = make_claim(
        "vendor://redis/max_memory/policy",
        "Redis max_memory_policy MUST be set to 'volatile-lru' for cache use cases",
        "https://redis.io/docs/management/config/",
    );

    let report = validator.validate(&[claim]);
    assert_eq!(report.passed, 1);
    assert_eq!(report.failed, 0);
    assert!(report.overall_score > 0.9);
}

#[test]
fn test_missing_source_fails() {
    let validator = QualityValidator::default();

    let claim = make_claim(
        "vendor://redis/max_memory/policy",
        "Redis max_memory_policy MUST be set properly",
        "", // No source URL
    );

    let report = validator.validate(&[claim]);
    let result = &report.claim_results[0];

    assert!(result.issues.iter().any(|i| i.category == IssueCategory::SourceAttribution));
}

#[test]
fn test_vague_content_fails() {
    let validator = QualityValidator::default();

    let claim = make_claim(
        "vendor://redis/config/setting",
        "It depends on the use case",
        "https://redis.io/docs/",
    );

    let report = validator.validate(&[claim]);
    let result = &report.claim_results[0];

    assert!(result.issues.iter().any(|i| i.category == IssueCategory::VagueContent));
}

#[test]
fn test_malformed_subject_fails() {
    let validator = QualityValidator::default();

    let claim = make_claim(
        "invalid-subject", // No scheme
        "This MUST be configured properly",
        "https://redis.io/docs/",
    );

    let report = validator.validate(&[claim]);
    let result = &report.claim_results[0];

    assert!(result.issues.iter().any(|i| i.category == IssueCategory::MalformedSubject));
}

#[test]
fn test_missing_normative_language_fails() {
    let validator = QualityValidator::default();

    let claim = make_claim(
        "vendor://redis/max_memory/policy",
        "Redis can be configured with various memory policies",
        "https://redis.io/docs/",
    );

    let report = validator.validate(&[claim]);
    let result = &report.claim_results[0];

    assert!(result.issues.iter().any(|i| i.category == IssueCategory::NormativeLanguage));
}

#[test]
fn test_authoritative_source_scoring() {
    let validator = QualityValidator::default();

    // RFC editor = highly authoritative
    let claim1 = make_claim(
        "rfc://7519/jwt/validation",
        "JWT tokens MUST be validated",
        "https://www.rfc-editor.org/rfc/rfc7519",
    );

    // Random blog = less authoritative
    let claim2 = make_claim(
        "vendor://lib/config",
        "Library SHOULD be configured",
        "https://random-blog.example.com/article",
    );

    let report1 = validator.validate(&[claim1]);
    let report2 = validator.validate(&[claim2]);

    assert!(report1.source_attribution_score > report2.source_attribution_score);
}

#[test]
fn test_filter_passed() {
    let validator = QualityValidator::default();

    let good_claim = make_claim(
        "vendor://redis/max_memory/policy",
        "Redis max_memory_policy MUST be set to 'volatile-lru' for cache use cases",
        "https://redis.io/docs/",
    );

    let bad_claim = make_claim(
        "invalid", // Bad subject
        "short",   // Too short
        "",        // No source
    );

    let filtered = validator.filter_passed(vec![good_claim.clone(), bad_claim]);

    assert_eq!(filtered.len(), 1);
    assert_eq!(filtered[0].subject, good_claim.subject);
}
