//! Corpus building operations - fetching and ingesting authoritative sources.

use crate::bridge;
use crate::config::AphoriaConfig;
use crate::corpus::{CorpusBuildResult, CorpusBuilderInfo, CorpusRegistry};
use crate::current_timestamp;
use crate::episteme;
use crate::error::AphoriaError;
use tracing::{info, instrument};

/// Arguments for corpus build command.
#[derive(Debug, Clone, Default)]
pub struct CorpusBuildArgs {
    /// Only include specific corpus sources (comma-separated: rfc,owasp,vendor,hardcoded).
    pub only: Option<Vec<String>>,
    /// Run in offline mode (skip sources requiring network).
    pub offline: bool,
    /// Clear cache before building.
    pub clear_cache: bool,
}

/// Build the authoritative corpus from configured sources.
///
/// This command:
/// 1. Fetches RFCs, OWASP cheat sheets, and vendor documentation
/// 2. Parses normative statements and recommendations
/// 3. Ingests them as assertions into the local Episteme instance
#[instrument(skip(config), fields(offline = args.offline, clear_cache = args.clear_cache))]
pub async fn build_corpus(
    args: CorpusBuildArgs,
    config: &AphoriaConfig,
) -> Result<CorpusBuildResult, AphoriaError> {
    info!("Building authoritative corpus");

    let project_root = std::env::current_dir()?;

    // Clear cache if requested
    if args.clear_cache {
        let cache_dir = &config.corpus.cache_dir;
        if cache_dir.exists() {
            info!(cache_dir = %cache_dir.display(), "Clearing corpus cache");
            std::fs::remove_dir_all(cache_dir)?;
        }
    }

    // Build corpus config based on --only flag
    let mut corpus_config = config.corpus.clone();
    if let Some(only) = &args.only {
        corpus_config.include_hardcoded = only.iter().any(|s| s == "hardcoded");
        corpus_config.include_rfc = only.iter().any(|s| s == "rfc");
        corpus_config.include_owasp = only.iter().any(|s| s == "owasp");
        corpus_config.include_vendor = only.iter().any(|s| s == "vendor");
    }

    // Create registry with configured builders
    let registry = CorpusRegistry::with_defaults(&corpus_config);

    // Load signing key
    let signing_key = bridge::load_or_generate_key(&project_root)?;

    // Build corpus
    let timestamp = current_timestamp();

    let result = registry.build_all(&signing_key, timestamp, &corpus_config, args.offline)?;

    // Ingest into Episteme
    if !result.assertions.is_empty() {
        let mut episteme = episteme::LocalEpisteme::open(config, &project_root).await?;
        let ingested = episteme.ingest_authoritative(&result.assertions).await?;
        episteme.shutdown().await;
        info!(ingested, "Corpus ingested into Episteme");
    }

    Ok(result)
}

/// List available corpus sources.
#[instrument(skip(config))]
pub fn list_corpus_sources(config: &AphoriaConfig) -> Vec<CorpusBuilderInfo> {
    info!("Listing corpus sources");

    let registry = CorpusRegistry::with_defaults(&config.corpus);
    registry.list_builders()
}
