pub mod cfg;
pub(crate) mod diags;
mod helpers;

use crate::{diag, LintLevel};
pub use diags::Code;
pub use helpers::{
    db::{AdvisoryDb, DbSet, Fetch, Id, Report},
    index::{Entry, Indices},
};

pub trait AuditReporter {
    fn report(&mut self, report: serde_json::Value);
}

/// For when you just want to satisfy `AuditReporter` without doing anything
pub struct NoneReporter;
impl AuditReporter for NoneReporter {
    fn report(&mut self, _report: serde_json::Value) {}
}

impl<F> AuditReporter for F
where
    F: FnMut(serde_json::Value),
{
    fn report(&mut self, report: serde_json::Value) {
        self(report);
    }
}

/// Check crates against the advisory database to detect vulnerabilities or
/// unmaintained crates
pub fn check<R, S>(
    ctx: crate::CheckCtx<'_, cfg::ValidConfig>,
    advisory_dbs: &DbSet,
    audit_compatible_reporter: Option<R>,
    indices: Option<Indices<'_>>,
    sink: S,
) where
    R: AuditReporter,
    S: Into<diag::ErrorSink>,
{
    let mut sink = sink.into();
    let emit_audit_compatible_reports = audit_compatible_reporter.is_some();

    let (report, yanked) = rayon::join(
        || Report::generate(advisory_dbs, ctx.krates, emit_audit_compatible_reports),
        || {
            if let Some(indices) = indices {
                let yanked: Vec<_> = ctx
                    .krates
                    .krates()
                    .filter_map(|package| match indices.is_yanked(package) {
                        Ok(is_yanked) => {
                            if is_yanked {
                                Some((package, None))
                            } else {
                                None
                            }
                        }
                        Err(err) => Some((package, Some(err))),
                    })
                    .collect();

                yanked
            } else {
                Vec::new()
            }
        },
    );

    use bitvec::prelude::*;
    let mut ignore_hits: BitVec = BitVec::repeat(false, ctx.cfg.ignore.len());
    let mut ignore_yanked_hits: BitVec = BitVec::repeat(false, ctx.cfg.ignore_yanked.len());

    // Emit diagnostics for any advisories found that matched crates in the graph
    for (krate, krate_index, advisory) in &report.advisories {
        let diag = ctx.diag_for_advisory(
            krate,
            *krate_index,
            &advisory.metadata,
            Some(&advisory.versions),
            |index| {
                ignore_hits.as_mut_bitslice().set(index, true);
            },
        );

        sink.push(diag);
    }

    for (krate, status) in yanked {
        let Some(ind) = ctx.krates.nid_for_kid(&krate.id) else {
            log::warn!("failed to locate node id for '{krate}'");
            continue;
        };

        if let Some(e) = status {
            if ctx.cfg.yanked.value != LintLevel::Allow {
                sink.push(ctx.diag_for_index_failure(krate, ind, e));
            }
        } else {
            // Check to see if the user has added an ignore for the yanked
            // crate, eg. see https://github.com/EmbarkStudios/cargo-deny/issues/579
            // this should be extremely rare and very temporary as in most cases
            // a new semver compatible version of the yanked version is published
            // around the same time as a yank occurs
            if let Some(i) = ctx
                .cfg
                .ignore_yanked
                .iter()
                .position(|iy| crate::match_krate(krate, &iy.spec))
            {
                sink.push(ctx.diag_for_yanked_ignore(krate, i));
                ignore_yanked_hits.as_mut_bitslice().set(i, true);
            } else {
                sink.push(ctx.diag_for_yanked(krate, ind));
            }
        }
    }

    // Check for advisory identifiers that were set to be ignored, but
    // are not actually in any database.
    for ignored in &ctx.cfg.ignore {
        if !advisory_dbs.has_advisory(&ignored.id.value) {
            sink.push(ctx.diag_for_unknown_advisory(ignored));
        }
    }

    // Check for advisory identifiers that were set to be ignored, but
    // were not actually encountered, for cases where a crate, or specific
    // version of that crate, has been removed or replaced and the advisory
    // no longer applies to it, so that users can cleanup their configuration
    for ignore in ignore_hits
        .into_iter()
        .zip(ctx.cfg.ignore.iter())
        .filter_map(|(hit, ignore)| if !hit { Some(ignore) } else { None })
    {
        sink.push(ctx.diag_for_advisory_not_encountered(ignore));
    }

    for ignore in ignore_yanked_hits
        .into_iter()
        .zip(ctx.cfg.ignore_yanked.iter())
        .filter_map(|(hit, ignore)| if !hit { Some(ignore) } else { None })
    {
        sink.push(ctx.diag_for_ignored_yanked_not_encountered(ignore));
    }

    if let Some(mut reporter) = audit_compatible_reporter {
        for ser_report in report.serialized_reports {
            reporter.report(ser_report);
        }
    }
}
