use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node};
use clippy_utils::res::MaybeDef as _;
use clippy_utils::source::walk_span_to_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::sym;
use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext as _};
use rustc_middle::ty::{self, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::Span;

declare_clippy_lint! {
    /// ### What it does
    ///
    /// Checks assertions that only test whether a supported value is empty.
    ///
    /// The lint handles `assert!` and `debug_assert!` calls on strings, slices, arrays, and `Vec`.
    ///
    /// ### Why is this bad?
    ///
    /// A boolean assertion only reports that the emptiness check failed. It does not show what the
    /// asserted value contained.
    ///
    /// In CI or another remote test service, the failure output tells you that the value was
    /// unexpectedly empty or non-empty, but not which values were present. The next step is often
    /// to reproduce the failure locally, add temporary logging, or change the test so it exposes
    /// the value. That extra investigation can be much slower than fixing the problem from the
    /// original CI failure.
    ///
    /// The emptiness check also commonly appears before a deeper contents assertion:
    ///
    /// ```no_run
    /// # let items = vec!["baz"];
    /// assert!(!items.is_empty());
    /// assert_eq!(items[0], "bar");
    /// ```
    ///
    /// If the first assertion fails, the second assertion never runs, so the failure can hide the
    /// check that would have shown more useful context.
    ///
    /// Instead, compare the value with an empty value using `assert_eq!`, `assert_ne!`,
    /// `debug_assert_eq!`, or `debug_assert_ne!`. These macros print the asserted value on failure.
    ///
    /// ### Known problems
    ///
    /// Printing the asserted value can be undesirable outside tests, especially when the value may
    /// be very large or contain sensitive information. If the assertion failure should not reveal
    /// the value, keep the boolean assertion and allow this lint at that assertion.
    ///
    /// ### Example
    ///
    /// ```no_run
    /// # let items = vec![1, 2, 3];
    /// assert!(items.is_empty());
    /// assert!(!items.is_empty());
    /// ```
    ///
    /// Use instead:
    ///
    /// ```no_run
    /// # let items = vec![1, 2, 3];
    /// assert_eq!(items, [] as [i32; 0]);
    /// assert_ne!(items, [] as [i32; 0]);
    /// ```
    #[clippy::version = "1.98.0"]
    pub ASSERT_IS_EMPTY,
    pedantic,
    "asserting on emptiness without showing the asserted value on failure"
}

declare_lint_pass!(AssertIsEmpty => [ASSERT_IS_EMPTY]);

impl<'tcx> LateLintPass<'tcx> for AssertIsEmpty {
    /// Finds assertion conditions that only test emptiness.
    ///
    /// Matching assertions without a custom message are rewritten as equality or inequality
    /// assertions against an empty value.
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
        // `assert!` and `debug_assert!` expand to `if`; skip other expressions before walking the
        // macro backtrace.
        if !matches!(expr.kind, ExprKind::If(..)) {
            return;
        }

        let Some((macro_name, condition, assert_span)) = assert_call(cx, expr) else {
            return;
        };
        let Some((assertion_kind, receiver)) = emptiness_assertion(condition) else {
            return;
        };
        let Some((receiver_suffix, empty_value)) = assertion_suggestion(cx, receiver) else {
            return;
        };

        emit_assertion_suggestion(
            cx,
            macro_name,
            assert_span,
            condition,
            assertion_kind,
            receiver,
            (receiver_suffix, &empty_value),
        );
    }
}

/// Extracts the source-level condition from `assert!` and `debug_assert!`.
///
/// The returned macro name omits the trailing `!` so the diagnostic can build `assert_eq`,
/// `assert_ne`, `debug_assert_eq`, or `debug_assert_ne` from the original macro. Returns `None`
/// for other macros, assertions with a custom message parameter, and conditions from macro
/// expansions, where rewriting the condition span would produce confusing or invalid suggestions.
fn assert_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'static str, &'tcx Expr<'tcx>, Span)> {
    let macro_call = root_macro_call_first_node(cx, expr)?;
    let macro_name = match cx.tcx.get_diagnostic_name(macro_call.def_id) {
        Some(sym::assert_macro) => "assert",
        Some(sym::debug_assert_macro) => "debug_assert",
        _ => return None,
    };
    let (condition, panic_expn) = find_assert_args(cx, expr, macro_call.expn)?;
    if !panic_expn.is_default_message() {
        return None;
    }

    if condition.span.from_expansion() {
        return None;
    }

    Some((macro_name, condition, macro_call.span))
}

/// Returns the assertion kind and receiver for an emptiness predicate.
///
/// `value.is_empty()` maps to an equality assertion against an empty value. `!value.is_empty()`
/// maps to an inequality assertion. Returns `None` when the condition is neither form.
fn emptiness_assertion<'tcx>(condition: &'tcx Expr<'tcx>) -> Option<(AssertionKind, &'tcx Expr<'tcx>)> {
    if let Some(receiver) = is_empty_receiver(condition) {
        return Some((AssertionKind::Eq, receiver));
    }

    let ExprKind::Unary(UnOp::Not, inner) = condition.kind else {
        return None;
    };

    is_empty_receiver(inner).map(|receiver| (AssertionKind::Ne, receiver))
}

/// Returns the receiver when `expr` is a direct `value.is_empty()` call.
///
/// Returns `None` for other method calls, negated expressions, and non-method expressions.
fn is_empty_receiver<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
    let ExprKind::MethodCall(method, receiver, [], _) = expr.kind else {
        return None;
    };
    (method.ident.name == sym::is_empty).then_some(receiver)
}

/// Assertion macro polarity for the replacement assertion.
///
/// The variants are named after the comparison macro suffixes rather than the original predicate
/// shape because suggestions are the only consumer.
#[derive(Clone, Copy, PartialEq, Eq)]
enum AssertionKind {
    /// Use an equality assertion against an empty value.
    Eq,

    /// Use an inequality assertion against an empty value.
    Ne,
}

impl AssertionKind {
    /// Returns the assertion macro suffix for this emptiness predicate.
    ///
    /// Empty checks become equality assertions. Non-empty checks become inequality assertions.
    fn suffix(self) -> &'static str {
        match self {
            Self::Eq => "_eq",
            Self::Ne => "_ne",
        }
    }

    /// Returns the expected state named in the diagnostic.
    fn expected_state(self) -> &'static str {
        match self {
            Self::Eq => "empty",
            Self::Ne => "not empty",
        }
    }
}

/// Builds replacement operands when the resulting assertion is useful.
///
/// The replacement assertion must compile, compare the same value, and print useful failure
/// output. Returns `None` for unsupported collection types and for element types that cannot be
/// printed and compared by the replacement assertion.
fn assertion_suggestion<'tcx>(cx: &LateContext<'tcx>, receiver: &'tcx Expr<'tcx>) -> Option<(&'static str, String)> {
    let receiver_ty = cx.typeck_results().expr_ty(receiver);
    let suggestion = suggestion_for_type(cx, receiver_ty)?;
    if type_is_printable_and_comparable(cx, receiver_ty.peel_refs()) {
        Some(suggestion)
    } else {
        None
    }
}

/// Returns the receiver suffix and empty value for this receiver type.
///
/// Arrays and borrowed vectors are compared through slices because direct comparison with `[]` does
/// not compile for those receiver types. Returns `None` when the receiver has no compact
/// empty-literal comparison.
fn suggestion_for_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<(&'static str, String)> {
    match ty.kind() {
        ty::Array(..) => Some((".as_slice()", "[]".to_string())),
        ty::Ref(_, inner, _) if matches!(inner.kind(), ty::Array(..)) => Some((".as_slice()", "[]".to_string())),
        ty::Ref(_, inner, _) if inner.is_diag_item(cx, sym::Vec) => Some((".as_slice()", "[]".to_string())),
        _ => suggestion_for_peeled_type(cx, ty.peel_refs()),
    }
}

/// Returns the empty value for receivers that compare directly after peeling references.
///
/// `String` and `str` compare against `""`. Slices compare against `[]`. `Vec<T>` compares
/// against `[] as [T; 0]` so the empty value carries the element type. Returns `None` for other
/// receiver types.
fn suggestion_for_peeled_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<(&'static str, String)> {
    if ty.is_str() || ty.is_lang_item(cx, LangItem::String) {
        Some(("", "\"\"".to_string()))
    } else if matches!(ty.kind(), ty::Slice(..)) {
        Some(("", "[]".to_string()))
    } else if ty.is_diag_item(cx, sym::Vec) {
        Some(("", format!("[] as [{}; 0]", element_type(cx, ty)?)))
    } else {
        None
    }
}

/// Returns whether the replacement assertion has useful failure output.
///
/// Suggestions are limited to cases where the replacement assertion can both compare the value and
/// print it on failure. Strings satisfy this directly; sequence-like values require printable,
/// self-comparable elements. Returns `false` when either trait bound is missing.
fn type_is_printable_and_comparable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
    if ty.is_str() || ty.is_lang_item(cx, LangItem::String) {
        return true;
    }

    if let Some(element_ty) = element_type(cx, ty)
        && let Some(debug_trait) = cx.tcx.get_diagnostic_item(sym::Debug)
        && let Some(partial_eq_trait) = cx.tcx.get_diagnostic_item(sym::PartialEq)
    {
        implements_trait(cx, element_ty, debug_trait, &[])
            && implements_trait(cx, element_ty, partial_eq_trait, &[element_ty.into()])
    } else {
        false
    }
}

/// Extracts the element type from supported sequence-like values.
///
/// The element type is used both for trait checks and for the typed empty-array suggestion required
/// by `Vec<T>` suggestions. Returns `None` for non-sequence receiver types.
fn element_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
    match ty.kind() {
        ty::Array(ty, _) | ty::Slice(ty) => Some(*ty),
        ty::Adt(_, args) if ty.is_diag_item(cx, sym::Vec) => args.types().next(),
        _ => None,
    }
}

/// Emits the rewrite from a boolean assertion to a comparison assertion.
fn emit_assertion_suggestion(
    cx: &LateContext<'_>,
    macro_name: &str,
    assert_span: Span,
    condition: &Expr<'_>,
    assertion_kind: AssertionKind,
    receiver: &Expr<'_>,
    suggestion: (&str, &str),
) {
    let mut applicability = Applicability::MachineApplicable;
    let receiver_snip =
        Sugg::hir_with_context(cx, receiver, assert_span.ctxt(), "..", &mut applicability).maybe_paren();
    let (receiver_suffix, empty_value) = suggestion;
    let receiver_snip = format!("{receiver_snip}{receiver_suffix}");
    let assertion_suffix = assertion_kind.suffix();
    let expected_state = assertion_kind.expected_state();

    span_lint_and_then(
        cx,
        ASSERT_IS_EMPTY,
        assert_span,
        format!("used `{macro_name}!` to check that a value is {expected_state}"),
        |diag| {
            let macro_name_span = cx.sess().source_map().span_until_char(assert_span, '!');
            let condition_span = walk_span_to_context(condition.span, assert_span.ctxt()).unwrap_or(condition.span);

            diag.multipart_suggestion(
                format!("use `{macro_name}{assertion_suffix}!` to show the value on failure"),
                vec![
                    (macro_name_span.shrink_to_hi(), assertion_suffix.to_string()),
                    (condition_span, format!("{receiver_snip}, {empty_value}")),
                ],
                applicability,
            );
        },
    );
}
