use std::sync::{Arc, LazyLock};
use std::{io, mem};

use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordSet;
use rustc_driver::USING_INTERNAL_FEATURES;
use rustc_errors::TerminalUrl;
use rustc_errors::codes::*;
use rustc_errors::emitter::{
    DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination,
};
use rustc_errors::json::JsonEmitter;
use rustc_feature::UnstableFeatures;
use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path};
use rustc_lint::{MissingDoc, late_lint_mod};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_session::config::{
    self, CrateType, ErrorOutputType, Input, OutFileName, OutputType, OutputTypes, ResolveDocLinks,
};
pub(crate) use rustc_session::config::{Options, UnstableOptions};
use rustc_session::{Session, lint};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use tracing::{debug, info};

use crate::clean::inline::build_trait;
use crate::clean::{self, ItemId};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
use crate::passes;
use crate::passes::Condition::*;
use crate::passes::collect_intra_doc_links::LinkCollector;

pub(crate) struct DocContext<'tcx> {
    pub(crate) tcx: TyCtxt<'tcx>,
    /// Used for normalization.
    ///
    /// Most of this logic is copied from rustc_lint::late.
    pub(crate) param_env: ParamEnv<'tcx>,
    /// Later on moved through `clean::Crate` into `cache`
    pub(crate) external_traits: FxIndexMap<DefId, clean::Trait>,
    /// Used while populating `external_traits` to ensure we don't process the same trait twice at
    /// the same time.
    pub(crate) active_extern_traits: DefIdSet,
    /// The current set of parameter instantiations for expanding type aliases at the HIR level.
    ///
    /// Maps from the `DefId` of a lifetime or type parameter to the
    /// generic argument it's currently instantiated to in this context.
    // FIXME(#82852): We don't record const params since we don't visit const exprs at all and
    // therefore wouldn't use the corresp. generic arg anyway. Add support for them.
    pub(crate) args: DefIdMap<clean::GenericArg>,
    pub(crate) current_type_aliases: DefIdMap<usize>,
    /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
    pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
    /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
    // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
    pub(crate) generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>,
    pub(crate) auto_traits: Vec<DefId>,
    /// The options given to rustdoc that could be relevant to a pass.
    pub(crate) render_options: RenderOptions,
    /// This same cache is used throughout rustdoc, including in [`crate::html::render`].
    pub(crate) cache: Cache,
    /// Used by [`clean::inline`] to tell if an item has already been inlined.
    pub(crate) inlined: FxHashSet<ItemId>,
    /// Used by `calculate_doc_coverage`.
    pub(crate) output_format: OutputFormat,
    /// Used by `strip_private`.
    pub(crate) show_coverage: bool,
}

impl<'tcx> DocContext<'tcx> {
    pub(crate) fn sess(&self) -> &'tcx Session {
        self.tcx.sess
    }

    pub(crate) fn with_param_env<T, F: FnOnce(&mut Self) -> T>(
        &mut self,
        def_id: DefId,
        f: F,
    ) -> T {
        let old_param_env = mem::replace(&mut self.param_env, self.tcx.param_env(def_id));
        let ret = f(self);
        self.param_env = old_param_env;
        ret
    }

    pub(crate) fn typing_env(&self) -> ty::TypingEnv<'tcx> {
        ty::TypingEnv {
            typing_mode: ty::TypingMode::non_body_analysis(),
            param_env: self.param_env,
        }
    }

    /// Call the closure with the given parameters set as
    /// the generic parameters for a type alias' RHS.
    pub(crate) fn enter_alias<F, R>(
        &mut self,
        args: DefIdMap<clean::GenericArg>,
        def_id: DefId,
        f: F,
    ) -> R
    where
        F: FnOnce(&mut Self) -> R,
    {
        let old_args = mem::replace(&mut self.args, args);
        *self.current_type_aliases.entry(def_id).or_insert(0) += 1;
        let r = f(self);
        self.args = old_args;
        if let Some(count) = self.current_type_aliases.get_mut(&def_id) {
            *count -= 1;
            if *count == 0 {
                self.current_type_aliases.remove(&def_id);
            }
        }
        r
    }

    /// Like `tcx.local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
    /// (This avoids a slice-index-out-of-bounds panic.)
    pub(crate) fn as_local_hir_id(tcx: TyCtxt<'_>, item_id: ItemId) -> Option<HirId> {
        match item_id {
            ItemId::DefId(real_id) => {
                real_id.as_local().map(|def_id| tcx.local_def_id_to_hir_id(def_id))
            }
            // FIXME: Can this be `Some` for `Auto` or `Blanket`?
            _ => None,
        }
    }

    /// Returns `true` if the JSON output format is enabled for generating the crate content.
    ///
    /// If another option like `--show-coverage` is enabled, it will return `false`.
    pub(crate) fn is_json_output(&self) -> bool {
        self.output_format.is_json() && !self.show_coverage
    }
}

/// Creates a new `DiagCtxt` that can be used to emit warnings and errors.
///
/// If the given `error_format` is `ErrorOutputType::Json` and no `SourceMap` is given, a new one
/// will be created for the `DiagCtxt`.
pub(crate) fn new_dcx(
    error_format: ErrorOutputType,
    source_map: Option<Arc<source_map::SourceMap>>,
    diagnostic_width: Option<usize>,
    unstable_opts: &UnstableOptions,
) -> rustc_errors::DiagCtxt {
    let translator = rustc_driver::default_translator();
    let emitter: Box<DynEmitter> = match error_format {
        ErrorOutputType::HumanReadable { kind, color_config } => {
            let short = kind.short();
            Box::new(
                HumanEmitter::new(stderr_destination(color_config), translator)
                    .sm(source_map.map(|sm| sm as _))
                    .short_message(short)
                    .diagnostic_width(diagnostic_width)
                    .track_diagnostics(unstable_opts.track_diagnostics)
                    .theme(if let HumanReadableErrorType::Unicode = kind {
                        OutputTheme::Unicode
                    } else {
                        OutputTheme::Ascii
                    })
                    .ui_testing(unstable_opts.ui_testing),
            )
        }
        ErrorOutputType::Json { pretty, json_rendered, color_config } => {
            let source_map = source_map.unwrap_or_else(|| {
                Arc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
            });
            Box::new(
                JsonEmitter::new(
                    Box::new(io::BufWriter::new(io::stderr())),
                    Some(source_map),
                    translator,
                    pretty,
                    json_rendered,
                    color_config,
                )
                .ui_testing(unstable_opts.ui_testing)
                .diagnostic_width(diagnostic_width)
                .track_diagnostics(unstable_opts.track_diagnostics)
                .terminal_url(TerminalUrl::No),
            )
        }
    };

    rustc_errors::DiagCtxt::new(emitter).with_flags(unstable_opts.dcx_flags(true))
}

/// Parse, resolve, and typecheck the given crate.
pub(crate) fn create_config(
    input: Input,
    RustdocOptions {
        crate_name,
        proc_macro_crate,
        error_format,
        diagnostic_width,
        libs,
        externs,
        mut cfgs,
        check_cfgs,
        codegen_options,
        unstable_opts,
        target,
        edition,
        sysroot,
        lint_opts,
        describe_lints,
        lint_cap,
        scrape_examples_options,
        expanded_args,
        remap_path_prefix,
        target_modifiers,
        ..
    }: RustdocOptions,
    render_options: &RenderOptions,
) -> rustc_interface::Config {
    // Add the doc cfg into the doc build.
    cfgs.push("doc".to_string());

    // By default, rustdoc ignores all lints.
    // Specifically unblock lints relevant to documentation or the lint machinery itself.
    let mut lints_to_show = vec![
        // it's unclear whether these should be part of rustdoc directly (#77364)
        rustc_lint::builtin::MISSING_DOCS.name.to_string(),
        rustc_lint::builtin::INVALID_DOC_ATTRIBUTES.name.to_string(),
        // these are definitely not part of rustdoc, but we want to warn on them anyway.
        rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
        rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
        rustc_lint::builtin::UNEXPECTED_CFGS.name.to_string(),
        // this lint is needed to support `#[expect]` attributes
        rustc_lint::builtin::UNFULFILLED_LINT_EXPECTATIONS.name.to_string(),
    ];
    lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string()));

    let (lint_opts, lint_caps) = crate::lint::init_lints(lints_to_show, lint_opts, |lint| {
        Some((lint.name_lower(), lint::Allow))
    });

    let crate_types =
        if proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
    let resolve_doc_links = if render_options.document_private {
        ResolveDocLinks::All
    } else {
        ResolveDocLinks::Exported
    };
    let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
    // plays with error output here!
    let sessopts = config::Options {
        sysroot,
        search_paths: libs,
        crate_types,
        lint_opts,
        lint_cap,
        cg: codegen_options,
        externs,
        target_triple: target,
        unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
        actually_rustdoc: true,
        resolve_doc_links,
        unstable_opts,
        error_format,
        diagnostic_width,
        edition,
        describe_lints,
        crate_name,
        test,
        remap_path_prefix,
        output_types: if let Some(file) = render_options.dep_info() {
            OutputTypes::new(&[(
                OutputType::DepInfo,
                file.map(|f| OutFileName::Real(f.to_path_buf())),
            )])
        } else {
            OutputTypes::new(&[])
        },
        target_modifiers,
        ..Options::default()
    };

    rustc_interface::Config {
        opts: sessopts,
        crate_cfg: cfgs,
        crate_check_cfg: check_cfgs,
        input,
        output_file: None,
        output_dir: None,
        file_loader: None,
        locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
        lint_caps,
        psess_created: None,
        hash_untracked_state: None,
        register_lints: Some(Box::new(crate::lint::register_lints)),
        override_queries: Some(|_sess, providers| {
            // We do not register late module lints, so this only runs `MissingDoc`.
            // Most lints will require typechecking, so just don't run them.
            providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc);
            // hack so that `used_trait_imports` won't try to call typeck
            providers.used_trait_imports = |_, _| {
                static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
                &EMPTY_SET
            };
            // In case typeck does end up being called, don't ICE in case there were name resolution errors
            providers.typeck = move |tcx, def_id| {
                // Closures' tables come from their outermost function,
                // as they are part of the same "inference environment".
                // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`)
                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
                if typeck_root_def_id != def_id {
                    return tcx.typeck(typeck_root_def_id);
                }

                let body = tcx.hir_body_owned_by(def_id);
                debug!("visiting body for {def_id:?}");
                EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
                (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
            };
        }),
        extra_symbols: Vec::new(),
        make_codegen_backend: None,
        registry: rustc_driver::diagnostics_registry(),
        ice_file: None,
        using_internal_features: &USING_INTERNAL_FEATURES,
        expanded_args,
    }
}

pub(crate) fn run_global_ctxt(
    tcx: TyCtxt<'_>,
    show_coverage: bool,
    render_options: RenderOptions,
    output_format: OutputFormat,
) -> (clean::Crate, RenderOptions, Cache) {
    // Certain queries assume that some checks were run elsewhere
    // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
    // so type-check everything other than function bodies in this crate before running lints.

    // NOTE: this does not call `tcx.analysis()` so that we won't
    // typeck function bodies or run the default rustc lints.
    // (see `override_queries` in the `config`)

    // NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
    let _ = tcx.sess.time("wf_checking", || tcx.ensure_ok().check_type_wf(()));

    tcx.dcx().abort_if_errors();

    tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
    tcx.sess.time("check_mod_attrs", || {
        tcx.hir_for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module))
    });
    rustc_passes::stability::check_unused_or_stable_features(tcx);

    let auto_traits =
        tcx.visible_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect();

    let mut ctxt = DocContext {
        tcx,
        param_env: ParamEnv::empty(),
        external_traits: Default::default(),
        active_extern_traits: Default::default(),
        args: Default::default(),
        current_type_aliases: Default::default(),
        impl_trait_bounds: Default::default(),
        generated_synthetics: Default::default(),
        auto_traits,
        cache: Cache::new(render_options.document_private, render_options.document_hidden),
        inlined: FxHashSet::default(),
        output_format,
        render_options,
        show_coverage,
    };

    for cnum in tcx.crates(()) {
        crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id());
    }

    // Small hack to force the Sized trait to be present.
    //
    // Note that in case of `#![no_core]`, the trait is not available.
    if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
        let sized_trait = build_trait(&mut ctxt, sized_trait_did);
        ctxt.external_traits.insert(sized_trait_did, sized_trait);
    }

    let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));

    if krate.module.doc_value().is_empty() {
        let help = format!(
            "The following guide may be of use:\n\
            {}/rustdoc/how-to-write-documentation.html",
            crate::DOC_RUST_LANG_ORG_VERSION
        );
        tcx.node_lint(
            crate::lint::MISSING_CRATE_LEVEL_DOCS,
            DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
            |lint| {
                lint.primary_message("no documentation found for this crate's top-level module");
                lint.help(help);
            },
        );
    }

    // Process all of the crate attributes, extracting plugin metadata along
    // with the passes which we are supposed to run.
    for attr in krate.module.attrs.lists(sym::doc) {
        if attr.is_word() && attr.has_name(sym::document_private_items) {
            ctxt.render_options.document_private = true;
        }
    }

    info!("Executing passes");

    let mut visited = FxHashMap::default();
    let mut ambiguous = FxIndexMap::default();

    for p in passes::defaults(show_coverage) {
        let run = match p.condition {
            Always => true,
            WhenDocumentPrivate => ctxt.render_options.document_private,
            WhenNotDocumentPrivate => !ctxt.render_options.document_private,
            WhenNotDocumentHidden => !ctxt.render_options.document_hidden,
        };
        if run {
            debug!("running pass {}", p.pass.name);
            if let Some(run_fn) = p.pass.run {
                krate = tcx.sess.time(p.pass.name, || run_fn(krate, &mut ctxt));
            } else {
                let (k, LinkCollector { visited_links, ambiguous_links, .. }) =
                    passes::collect_intra_doc_links::collect_intra_doc_links(krate, &mut ctxt);
                krate = k;
                visited = visited_links;
                ambiguous = ambiguous_links;
            }
        }
    }

    tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc)));

    krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate));

    let mut collector =
        LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous };
    collector.resolve_ambiguities();

    tcx.dcx().abort_if_errors();

    (krate, ctxt.render_options, ctxt.cache)
}

/// Due to <https://github.com/rust-lang/rust/pull/73566>,
/// the name resolution pass may find errors that are never emitted.
/// If typeck is called after this happens, then we'll get an ICE:
/// 'Res::Error found but not reported'. To avoid this, emit the errors now.
struct EmitIgnoredResolutionErrors<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> EmitIgnoredResolutionErrors<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx }
    }
}

impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
    type NestedFilter = nested_filter::OnlyBodies;

    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
        // We need to recurse into nested closures,
        // since those will fallback to the parent for type checking.
        self.tcx
    }

    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
        debug!("visiting path {path:?}");
        if path.res == Res::Err {
            // We have less context here than in rustc_resolve,
            // so we can only emit the name and span.
            // However we can give a hint that rustc_resolve will have more info.
            let label = format!(
                "could not resolve path `{}`",
                path.segments
                    .iter()
                    .map(|segment| segment.ident.as_str())
                    .intersperse("::")
                    .collect::<String>()
            );
            rustc_errors::struct_span_code_err!(
                self.tcx.dcx(),
                path.span,
                E0433,
                "failed to resolve: {label}",
            )
            .with_span_label(path.span, label)
            .with_note("this error was originally ignored because you are running `rustdoc`")
            .with_note("try running again with `rustc` or `cargo check` and you may get a more detailed error")
            .emit();
        }
        // We could have an outer resolution that succeeded,
        // but with generic parameters that failed.
        // Recurse into the segments so we catch those too.
        intravisit::walk_path(self, path);
    }
}

/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
/// for `impl Trait` in argument position.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum ImplTraitParam {
    DefId(DefId),
    ParamIndex(u32),
}

impl From<DefId> for ImplTraitParam {
    fn from(did: DefId) -> Self {
        ImplTraitParam::DefId(did)
    }
}

impl From<u32> for ImplTraitParam {
    fn from(idx: u32) -> Self {
        ImplTraitParam::ParamIndex(idx)
    }
}
