//! Top-100 target-corpus coverage gate tests for Milestones 60 and 66.

use std::collections::BTreeSet;
use std::fs;
use std::path::Path;

use index_core::DocumentQualityCategory;
use index_transformer::{Transformer, state::Empty};

fn transform(html: &str) -> index_core::IndexDocument {
    Transformer::<Empty>::new()
        .fetched(html)
        .parse()
        .extract()
        .transform()
        .into_document()
}

#[test]
fn top100_corpus_matrix_is_well_formed_and_paths_exist() -> Result<(), Box<dyn std::error::Error>> {
    let matrix = include_str!("../../../docs/top100-corpus/matrix.tsv");
    let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
    let mut seen = BTreeSet::new();
    let mut count = 0usize;

    for line in matrix.lines() {
        if line.trim().is_empty() || line.starts_with('#') {
            continue;
        }
        let fields = line.split('\t').collect::<Vec<_>>();
        assert_eq!(fields.len(), 9, "invalid top100 matrix row: {line}");

        let domain = fields[0];
        let family = fields[1];
        let intent = fields[2];
        let min_tier = fields[3].parse::<u8>()?;
        let current_tier = fields[4].parse::<u8>()?;
        let fixture = fields[5];
        let expected_path = fields[6];
        let status = fields[7];
        let known_limit = fields[8];

        assert!(
            matches!(
                family,
                "search-portal"
                    | "knowledge-reference"
                    | "social-community"
                    | "media-streaming"
                    | "commerce-marketplace"
                    | "services-utility"
                    | "ai-assistant"
                    | "adult-content"
            ),
            "invalid family for {domain}: {family}"
        );
        assert!(
            matches!(
                intent,
                "portal-landing"
                    | "search-results"
                    | "article-or-reference"
                    | "app-shell"
                    | "feed-or-thread"
                    | "video-hub"
                    | "marketplace-listing"
            ),
            "invalid primary intent for {domain}: {intent}"
        );
        assert!(min_tier <= 5, "invalid min tier for {domain}");
        assert!(current_tier <= 5, "invalid current tier for {domain}");
        assert!(
            current_tier >= min_tier,
            "tier regression for {domain}: current {current_tier} < min {min_tier}"
        );
        assert!(
            matches!(expected_path, "generic" | "adapter" | "failure"),
            "invalid expected_path for {domain}: {expected_path}"
        );
        assert!(
            matches!(status, "covered" | "partial" | "blocked" | "planned"),
            "invalid status for {domain}: {status}"
        );
        assert!(
            matches!(
                known_limit,
                "none"
                    | "auth-wall"
                    | "script-gate"
                    | "bot-gate"
                    | "geo-gate"
                    | "age-gate"
                    | "policy-blocked"
            ),
            "invalid known_limit for {domain}: {known_limit}"
        );
        assert!(
            seen.insert(domain.to_owned()),
            "duplicate top100 domain row: {domain}"
        );
        assert!(
            workspace_root.join(fixture).is_file(),
            "missing fixture for {domain}: {fixture}"
        );
        count += 1;
    }

    assert_eq!(count, 100, "expected top100 matrix to have 100 rows");
    Ok(())
}

#[test]
fn top100_covered_and_blocked_rows_match_expected_transform_path()
-> Result<(), Box<dyn std::error::Error>> {
    let matrix = include_str!("../../../docs/top100-corpus/matrix.tsv");
    let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");

    for line in matrix.lines() {
        if line.trim().is_empty() || line.starts_with('#') {
            continue;
        }
        let fields = line.split('\t').collect::<Vec<_>>();
        let domain = fields[0];
        let fixture = fields[5];
        let expected_path = fields[6];
        let status = fields[7];

        if !matches!(status, "covered" | "blocked") {
            continue;
        }

        let html = fs::read_to_string(workspace_root.join(fixture))?;
        let document = transform(&html);

        match expected_path {
            "adapter" => assert!(
                document.metadata.adapter_id.is_some(),
                "{domain} expected adapter output"
            ),
            "failure" => assert!(
                matches!(
                    document
                        .metadata
                        .quality
                        .as_ref()
                        .map(|quality| quality.category),
                    Some(DocumentQualityCategory::Fallback | DocumentQualityCategory::Failed)
                ) || document
                    .nodes
                    .iter()
                    .any(|node| matches!(node, index_core::IndexNode::Error(_))),
                "{domain} expected deterministic diagnostic output"
            ),
            "generic" => assert!(
                document.metadata.adapter_id.is_none(),
                "{domain} expected generic output"
            ),
            _ => unreachable!(),
        }
    }

    Ok(())
}
