//! Vulnerability report generator
//!
//! These types map directly to the JSON report generated by `cargo-audit`,
//! but also provide the core reporting functionality used in general.

use crate::{
    advisory,
    database::{Database, Query},
    map,
    platforms::target::{Arch, OS},
    vulnerability::Vulnerability,
    warning::{self, Warning},
    Lockfile, Map,
};
use serde::{Deserialize, Serialize};

/// Vulnerability report for a given lockfile
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Report {
    /// Information about the advisory database
    #[cfg(feature = "git")]
    #[cfg_attr(docsrs, doc(cfg(feature = "git")))]
    pub database: DatabaseInfo,

    /// Information about the audited lockfile
    pub lockfile: LockfileInfo,

    /// Settings used when generating report
    pub settings: Settings,

    /// Vulnerabilities detected in project
    pub vulnerabilities: VulnerabilityInfo,

    /// Warnings about dependencies (from e.g. informational advisories)
    pub warnings: WarningInfo,
}

impl Report {
    /// Generate a report for the given advisory database and lockfile
    pub fn generate(db: &Database, lockfile: &Lockfile, settings: &Settings) -> Self {
        let vulnerabilities = db
            .query_vulnerabilities(lockfile, &settings.query())
            .into_iter()
            .filter(|vuln| !settings.ignore.contains(&vuln.advisory.id))
            .collect();

        let warnings = find_warnings(db, lockfile, settings);

        Self {
            #[cfg(feature = "git")]
            database: DatabaseInfo::new(db),
            lockfile: LockfileInfo::new(lockfile),
            settings: settings.clone(),
            vulnerabilities: VulnerabilityInfo::new(vulnerabilities),
            warnings,
        }
    }
}

/// Options to use when generating the report
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Settings {
    /// CPU architecture
    pub target_arch: Option<Arch>,

    /// Operating system
    pub target_os: Option<OS>,

    /// Severity threshold to alert at
    pub severity: Option<advisory::Severity>,

    /// List of advisory IDs to ignore
    pub ignore: Vec<advisory::Id>,

    /// Types of informational advisories to generate warnings for
    pub informational_warnings: Vec<advisory::Informational>,
}

impl Settings {
    /// Get a query which corresponds to the configured report settings.
    /// Note that queries can't filter ignored advisories, so this happens in
    /// a separate pass
    pub fn query(&self) -> Query {
        let mut query = Query::crate_scope();

        if let Some(target_arch) = self.target_arch {
            query = query.target_arch(target_arch);
        }

        if let Some(target_os) = self.target_os {
            query = query.target_os(target_os);
        }

        if let Some(severity) = self.severity {
            query = query.severity(severity);
        }

        query
    }
}

/// Information about the advisory database
#[cfg(feature = "git")]
#[cfg_attr(docsrs, doc(cfg(feature = "git")))]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DatabaseInfo {
    /// Number of advisories in the database
    #[serde(rename = "advisory-count")]
    pub advisory_count: usize,

    /// Git commit hash for the last commit to the database
    #[serde(rename = "last-commit")]
    pub last_commit: Option<String>,

    /// Date when the advisory database was last committed to
    #[serde(rename = "last-updated", with = "time::serde::rfc3339::option")]
    pub last_updated: Option<time::OffsetDateTime>,
}

#[cfg(feature = "git")]
impl DatabaseInfo {
    /// Create database information from the advisory db
    pub fn new(db: &Database) -> Self {
        Self {
            advisory_count: db.iter().count(),
            last_commit: db.latest_commit().map(|c| c.commit_id.to_hex()),
            last_updated: db.latest_commit().map(|c| c.timestamp),
        }
    }
}

/// Information about `Cargo.lock`
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LockfileInfo {
    /// Number of dependencies in the lock file
    #[serde(rename = "dependency-count")]
    dependency_count: usize,
}

impl LockfileInfo {
    /// Create lockfile information from the given lockfile
    pub fn new(lockfile: &Lockfile) -> Self {
        Self {
            dependency_count: lockfile.packages.len(),
        }
    }
}

/// Information about detected vulnerabilities
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct VulnerabilityInfo {
    /// Were any vulnerabilities found?
    pub found: bool,

    /// Number of vulnerabilities found
    pub count: usize,

    /// List of detected vulnerabilities
    pub list: Vec<Vulnerability>,
}

impl VulnerabilityInfo {
    /// Create new vulnerability info
    pub fn new(list: Vec<Vulnerability>) -> Self {
        Self {
            found: !list.is_empty(),
            count: list.len(),
            list,
        }
    }
}

/// Information about warnings
pub type WarningInfo = Map<warning::WarningKind, Vec<Warning>>;

/// Find warnings from the given advisory [`Database`] and [`Lockfile`]
pub fn find_warnings(db: &Database, lockfile: &Lockfile, settings: &Settings) -> WarningInfo {
    let query = settings.query().informational(true);

    let mut warnings = WarningInfo::default();

    // TODO(tarcieri): abstract `Cargo.lock` query logic between vulnerabilities/warnings
    for advisory_vuln in db.query_vulnerabilities(lockfile, &query) {
        let advisory = &advisory_vuln.advisory;

        if settings.ignore.contains(&advisory.id) {
            continue;
        }

        if settings
            .informational_warnings
            .iter()
            .any(|info| Some(info) == advisory.informational.as_ref())
        {
            let warning_kind = match advisory
                .informational
                .as_ref()
                .expect("informational advisory")
                .warning_kind()
            {
                Some(kind) => kind,
                None => continue,
            };

            let warning = Warning::new(
                warning_kind,
                &advisory_vuln.package,
                Some(advisory.clone()),
                advisory_vuln.affected.clone(),
                Some(advisory_vuln.versions.clone()),
            );

            match warnings.entry(warning.kind) {
                map::Entry::Occupied(entry) => (*entry.into_mut()).push(warning),
                map::Entry::Vacant(entry) => {
                    entry.insert(vec![warning]);
                }
            }
        }
    }

    warnings
}
