use clippy_config::Conf;
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::SpanRangeExt;
use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for manual `is_finite` reimplementations
    /// (i.e., `x != <float>::INFINITY && x != <float>::NEG_INFINITY`).
    ///
    /// ### Why is this bad?
    /// The method `is_finite` is shorter and more readable.
    ///
    /// ### Example
    /// ```no_run
    /// # let x = 1.0f32;
    /// if x != f32::INFINITY && x != f32::NEG_INFINITY {}
    /// if x.abs() < f32::INFINITY {}
    /// ```
    /// Use instead:
    /// ```no_run
    /// # let x = 1.0f32;
    /// if x.is_finite() {}
    /// if x.is_finite() {}
    /// ```
    #[clippy::version = "1.73.0"]
    pub MANUAL_IS_FINITE,
    style,
    "use dedicated method to check if a float is finite"
}

declare_clippy_lint! {
    /// ### What it does
    /// Checks for manual `is_infinite` reimplementations
    /// (i.e., `x == <float>::INFINITY || x == <float>::NEG_INFINITY`).
    ///
    /// ### Why is this bad?
    /// The method `is_infinite` is shorter and more readable.
    ///
    /// ### Example
    /// ```no_run
    /// # let x = 1.0f32;
    /// if x == f32::INFINITY || x == f32::NEG_INFINITY {}
    /// ```
    /// Use instead:
    /// ```no_run
    /// # let x = 1.0f32;
    /// if x.is_infinite() {}
    /// ```
    #[clippy::version = "1.73.0"]
    pub MANUAL_IS_INFINITE,
    style,
    "use dedicated method to check if a float is infinite"
}

impl_lint_pass!(ManualFloatMethods => [MANUAL_IS_FINITE, MANUAL_IS_INFINITE]);

#[derive(Clone, Copy)]
enum Variant {
    ManualIsInfinite,
    ManualIsFinite,
}

impl Variant {
    pub fn lint(self) -> &'static Lint {
        match self {
            Self::ManualIsInfinite => MANUAL_IS_INFINITE,
            Self::ManualIsFinite => MANUAL_IS_FINITE,
        }
    }

    pub fn msg(self) -> &'static str {
        match self {
            Self::ManualIsInfinite => "manually checking if a float is infinite",
            Self::ManualIsFinite => "manually checking if a float is finite",
        }
    }
}

pub struct ManualFloatMethods {
    msrv: Msrv,
}

impl ManualFloatMethods {
    pub fn new(conf: &'static Conf) -> Self {
        Self { msrv: conf.msrv }
    }
}

fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    match tcx.def_kind(def_id) {
        DefKind::Mod
        | DefKind::Struct
        | DefKind::Union
        | DefKind::Enum
        | DefKind::Variant
        | DefKind::Trait
        | DefKind::TyAlias
        | DefKind::ForeignTy
        | DefKind::TraitAlias
        | DefKind::AssocTy
        | DefKind::Macro(..)
        | DefKind::Field
        | DefKind::LifetimeParam
        | DefKind::ExternCrate
        | DefKind::Use
        | DefKind::ForeignMod
        | DefKind::GlobalAsm
        | DefKind::Impl { .. }
        | DefKind::OpaqueTy
        | DefKind::SyntheticCoroutineBody
        | DefKind::TyParam => true,

        DefKind::AnonConst
        | DefKind::InlineConst
        | DefKind::Const { .. }
        | DefKind::ConstParam
        | DefKind::Static { .. }
        | DefKind::Ctor(..)
        | DefKind::AssocConst { .. } => false,

        DefKind::Fn | DefKind::AssocFn | DefKind::Closure => tcx.constness(def_id) == Constness::NotConst,
    }
}

impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
        if let ExprKind::Binary(kind, lhs, rhs) = expr.kind
            && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind
            && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind
            // Checking all possible scenarios using a function would be a hopeless task, as we have
            // 16 possible alignments of constants/operands. For now, let's use `partition`.
            && let mut exprs = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs]
            && exprs.iter_mut().partition_in_place(|i| i.res_local_id().is_some()) == 2
            && !expr.span.in_external_macro(cx.sess().source_map())
            && (
                is_not_const(cx.tcx, cx.tcx.hir_enclosing_body_owner(expr.hir_id).into())
                    || self.msrv.meets(cx, msrvs::CONST_FLOAT_CLASSIFY)
            )
            && let [first, second, const_1, const_2] = exprs
            && let ecx = ConstEvalCtxt::new(cx)
            && let ctxt = expr.span.ctxt()
            && let Some(const_1) = ecx.eval_local(const_1, ctxt)
            && let Some(const_2) = ecx.eval_local(const_2, ctxt)
            && first.res_local_id().is_some_and(|f| second.res_local_id().is_some_and(|s| f == s))
            // The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in
            // case somebody does that for some reason
            && (const_1.is_pos_infinity() && const_2.is_neg_infinity()
                || const_1.is_neg_infinity() && const_2.is_pos_infinity())
            && let Some(local_snippet) = first.span.get_source_text(cx)
        {
            let variant = match (kind.node, lhs_kind.node, rhs_kind.node) {
                (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite,
                (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => Variant::ManualIsFinite,
                _ => return,
            };
            if is_from_proc_macro(cx, expr) {
                return;
            }

            span_lint_and_then(cx, variant.lint(), expr.span, variant.msg(), |diag| {
                match variant {
                    Variant::ManualIsInfinite => {
                        diag.span_suggestion(
                            expr.span,
                            "use the dedicated method instead",
                            format!("{local_snippet}.is_infinite()"),
                            Applicability::MachineApplicable,
                        );
                    },
                    Variant::ManualIsFinite => {
                        // TODO: There's probably some better way to do this, i.e., create
                        // multiple suggestions with notes between each of them
                        diag.span_suggestion_verbose(
                            expr.span,
                            "use the dedicated method instead",
                            format!("{local_snippet}.is_finite()"),
                            Applicability::MaybeIncorrect,
                        )
                        .span_suggestion_verbose(
                            expr.span,
                            "this will alter how it handles NaN; if that is a problem, use instead",
                            format!("{local_snippet}.is_finite() || {local_snippet}.is_nan()"),
                            Applicability::MaybeIncorrect,
                        )
                        .span_suggestion_verbose(
                            expr.span,
                            "or, for conciseness",
                            format!("!{local_snippet}.is_infinite()"),
                            Applicability::MaybeIncorrect,
                        );
                    },
                }
            });
        }
    }
}
