use super::ARITHMETIC_SIDE_EFFECTS;
use clippy_utils::consts::{constant, constant_simple, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::impl_lint_pass;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use {rustc_ast as ast, rustc_hir as hir};

const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]];
const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
const DISALLOWED_INT_METHODS: &[Symbol] = &[
    sym::saturating_div,
    sym::wrapping_div,
    sym::wrapping_rem,
    sym::wrapping_rem_euclid,
];

#[derive(Debug)]
pub struct ArithmeticSideEffects {
    allowed_binary: FxHashMap<String, FxHashSet<String>>,
    allowed_unary: FxHashSet<String>,
    // Used to check whether expressions are constants, such as in enum discriminants and consts
    const_span: Option<Span>,
    disallowed_int_methods: FxHashSet<Symbol>,
    expr_span: Option<Span>,
}

impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);

impl ArithmeticSideEffects {
    #[must_use]
    pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
        let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
        for [lhs, rhs] in user_allowed_binary.into_iter().chain(
            HARD_CODED_ALLOWED_BINARY
                .iter()
                .copied()
                .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
        ) {
            allowed_binary.entry(lhs).or_default().insert(rhs);
        }
        let allowed_unary = user_allowed_unary
            .into_iter()
            .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
            .collect();
        Self {
            allowed_binary,
            allowed_unary,
            const_span: None,
            disallowed_int_methods: DISALLOWED_INT_METHODS.iter().copied().collect(),
            expr_span: None,
        }
    }

    /// Checks if the lhs and the rhs types of a binary operation like "addition" or
    /// "multiplication" are present in the inner set of allowed types.
    fn has_allowed_binary(&self, lhs_ty: Ty<'_>, rhs_ty: Ty<'_>) -> bool {
        let lhs_ty_string = lhs_ty.to_string();
        let lhs_ty_string_elem = lhs_ty_string.split('<').next().unwrap_or_default();
        let rhs_ty_string = rhs_ty.to_string();
        let rhs_ty_string_elem = rhs_ty_string.split('<').next().unwrap_or_default();
        if let Some(rhs_from_specific) = self.allowed_binary.get(lhs_ty_string_elem)
            && {
                let rhs_has_allowed_ty = rhs_from_specific.contains(rhs_ty_string_elem);
                rhs_has_allowed_ty || rhs_from_specific.contains("*")
            }
        {
            true
        } else if let Some(rhs_from_glob) = self.allowed_binary.get("*") {
            rhs_from_glob.contains(rhs_ty_string_elem)
        } else {
            false
        }
    }

    /// Checks if the type of an unary operation like "negation" is present in the inner set of
    /// allowed types.
    fn has_allowed_unary(&self, ty: Ty<'_>) -> bool {
        let ty_string = ty.to_string();
        let ty_string_elem = ty_string.split('<').next().unwrap_or_default();
        self.allowed_unary.contains(ty_string_elem)
    }

    /// Verifies built-in types that have specific allowed operations
    fn has_specific_allowed_type_and_operation<'tcx>(
        cx: &LateContext<'tcx>,
        lhs_ty: Ty<'tcx>,
        op: hir::BinOpKind,
        rhs_ty: Ty<'tcx>,
    ) -> bool {
        let is_div_or_rem = matches!(op, hir::BinOpKind::Div | hir::BinOpKind::Rem);
        let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| {
            let tcx = cx.tcx;

            let ty::Adt(adt, substs) = ty.kind() else { return false };

            if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
                return false;
            };

            let int_type = substs.type_at(0);
            let unsigned_int_types = [
                tcx.types.u8,
                tcx.types.u16,
                tcx.types.u32,
                tcx.types.u64,
                tcx.types.u128,
                tcx.types.usize,
            ];

            unsigned_int_types.contains(&int_type)
        };
        let is_sat_or_wrap = |ty: Ty<'_>| {
            is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping)
        };

        // If the RHS is `NonZero<u*>`, then division or module by zero will never occur.
        if is_non_zero_u(cx, rhs_ty) && is_div_or_rem {
            return true;
        }

        // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module.
        if is_sat_or_wrap(lhs_ty) {
            return !is_div_or_rem;
        }

        false
    }

    // For example, 8i32 or &i64::MAX.
    fn is_integral(ty: Ty<'_>) -> bool {
        ty.peel_refs().is_integral()
    }

    // Common entry-point to avoid code duplication.
    fn issue_lint<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if is_from_proc_macro(cx, expr) {
            return;
        }

        let msg = "arithmetic operation that can potentially result in unexpected side-effects";
        span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
        self.expr_span = Some(expr.span);
    }

    /// Returns the numeric value of a literal integer originated from `expr`, if any.
    ///
    /// Literal integers can be originated from adhoc declarations like `1`, associated constants
    /// like `i32::MAX` or constant references like `N` from `const N: i32 = 1;`,
    fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
        let actual = peel_hir_expr_unary(expr).0;
        if let hir::ExprKind::Lit(lit) = actual.kind
            && let ast::LitKind::Int(n, _) = lit.node
        {
            return Some(n.get());
        }
        if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
            return Some(n);
        }
        None
    }

    /// Methods like `add_assign` are send to their `BinOps` references.
    fn manage_sugar_methods<'tcx>(
        &mut self,
        cx: &LateContext<'tcx>,
        expr: &'tcx hir::Expr<'_>,
        lhs: &'tcx hir::Expr<'_>,
        ps: &hir::PathSegment<'_>,
        rhs: &'tcx hir::Expr<'_>,
    ) {
        if ps.ident.name == sym::add || ps.ident.name == sym::add_assign {
            self.manage_bin_ops(cx, expr, hir::BinOpKind::Add, lhs, rhs);
        } else if ps.ident.name == sym::div || ps.ident.name == sym::div_assign {
            self.manage_bin_ops(cx, expr, hir::BinOpKind::Div, lhs, rhs);
        } else if ps.ident.name == sym::mul || ps.ident.name == sym::mul_assign {
            self.manage_bin_ops(cx, expr, hir::BinOpKind::Mul, lhs, rhs);
        } else if ps.ident.name == sym::rem || ps.ident.name == sym::rem_assign {
            self.manage_bin_ops(cx, expr, hir::BinOpKind::Rem, lhs, rhs);
        } else if ps.ident.name == sym::sub || ps.ident.name == sym::sub_assign {
            self.manage_bin_ops(cx, expr, hir::BinOpKind::Sub, lhs, rhs);
        }
    }

    /// Manages when the lint should be triggered. Operations in constant environments, hard coded
    /// types, custom allowed types and non-constant operations that don't overflow are ignored.
    fn manage_bin_ops<'tcx>(
        &mut self,
        cx: &LateContext<'tcx>,
        expr: &'tcx hir::Expr<'_>,
        op: hir::BinOpKind,
        lhs: &'tcx hir::Expr<'_>,
        rhs: &'tcx hir::Expr<'_>,
    ) {
        if constant_simple(cx, cx.typeck_results(), expr).is_some() {
            return;
        }
        if !matches!(
            op,
            hir::BinOpKind::Add
                | hir::BinOpKind::Div
                | hir::BinOpKind::Mul
                | hir::BinOpKind::Rem
                | hir::BinOpKind::Shl
                | hir::BinOpKind::Shr
                | hir::BinOpKind::Sub
        ) {
            return;
        };
        let (mut actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
        let (mut actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
        actual_lhs = expr_or_init(cx, actual_lhs);
        actual_rhs = expr_or_init(cx, actual_rhs);
        let lhs_ty = cx.typeck_results().expr_ty(actual_lhs).peel_refs();
        let rhs_ty = cx.typeck_results().expr_ty(actual_rhs).peel_refs();
        if self.has_allowed_binary(lhs_ty, rhs_ty) {
            return;
        }
        if Self::has_specific_allowed_type_and_operation(cx, lhs_ty, op, rhs_ty) {
            return;
        }
        let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
            if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op {
                // At least for integers, shifts are already handled by the CTFE
                return;
            }
            match (
                Self::literal_integer(cx, actual_lhs),
                Self::literal_integer(cx, actual_rhs),
            ) {
                (None, None) => false,
                (None, Some(n)) => match (&op, n) {
                    // Division and module are always valid if applied to non-zero integers
                    (hir::BinOpKind::Div | hir::BinOpKind::Rem, local_n) if local_n != 0 => true,
                    // Adding or subtracting zeros is always a no-op
                    (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
                    // Multiplication by 1 or 0 will never overflow
                    | (hir::BinOpKind::Mul, 0 | 1)
                    => true,
                    _ => false,
                },
                (Some(n), None) => match (&op, n) {
                    // Adding or subtracting zeros is always a no-op
                    (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
                    // Multiplication by 1 or 0 will never overflow
                    | (hir::BinOpKind::Mul, 0 | 1)
                    => true,
                    _ => false,
                },
                (Some(_), Some(_)) => {
                    matches!((lhs_ref_counter, rhs_ref_counter), (0, 0))
                },
            }
        } else {
            false
        };
        if !has_valid_op {
            self.issue_lint(cx, expr);
        }
    }

    /// There are some integer methods like `wrapping_div` that will panic depending on the
    /// provided input.
    fn manage_method_call<'tcx>(
        &mut self,
        args: &'tcx [hir::Expr<'_>],
        cx: &LateContext<'tcx>,
        expr: &'tcx hir::Expr<'_>,
        ps: &'tcx hir::PathSegment<'_>,
        receiver: &'tcx hir::Expr<'_>,
    ) {
        let Some(arg) = args.first() else {
            return;
        };
        if constant_simple(cx, cx.typeck_results(), receiver).is_some() {
            return;
        }
        let instance_ty = cx.typeck_results().expr_ty(receiver);
        if !Self::is_integral(instance_ty) {
            return;
        }
        self.manage_sugar_methods(cx, expr, receiver, ps, arg);
        if !self.disallowed_int_methods.contains(&ps.ident.name) {
            return;
        }
        let (actual_arg, _) = peel_hir_expr_refs(arg);
        match Self::literal_integer(cx, actual_arg) {
            None | Some(0) => self.issue_lint(cx, arg),
            Some(_) => {},
        }
    }

    fn manage_unary_ops<'tcx>(
        &mut self,
        cx: &LateContext<'tcx>,
        expr: &'tcx hir::Expr<'_>,
        un_expr: &'tcx hir::Expr<'_>,
        un_op: hir::UnOp,
    ) {
        let hir::UnOp::Neg = un_op else {
            return;
        };
        if constant(cx, cx.typeck_results(), un_expr).is_some() {
            return;
        }
        let ty = cx.typeck_results().expr_ty(expr).peel_refs();
        if self.has_allowed_unary(ty) {
            return;
        }
        let actual_un_expr = peel_hir_expr_refs(un_expr).0;
        if Self::literal_integer(cx, actual_un_expr).is_some() {
            return;
        }
        self.issue_lint(cx, expr);
    }

    fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool {
        is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
            || self.expr_span.is_some()
            || self.const_span.map_or(false, |sp| sp.contains(expr.span))
    }
}

impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
        if self.should_skip_expr(cx, expr) {
            return;
        }
        match &expr.kind {
            hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => {
                self.manage_bin_ops(cx, expr, op.node, lhs, rhs);
            },
            hir::ExprKind::MethodCall(ps, receiver, args, _) => {
                self.manage_method_call(args, cx, expr, ps, receiver);
            },
            hir::ExprKind::Unary(un_op, un_expr) => {
                self.manage_unary_ops(cx, expr, un_expr, *un_op);
            },
            _ => {},
        }
    }

    fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
        let body_owner = cx.tcx.hir().body_owner(body.id());
        let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());

        let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
        if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind {
            let body_span = cx.tcx.hir().span_with_body(body_owner);
            if let Some(span) = self.const_span
                && span.contains(body_span)
            {
                return;
            }
            self.const_span = Some(body_span);
        }
    }

    fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
        let body_owner = cx.tcx.hir().body_owner(body.id());
        let body_span = cx.tcx.hir().span(body_owner);
        if let Some(span) = self.const_span
            && span.contains(body_span)
        {
            return;
        }
        self.const_span = None;
    }

    fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if Some(expr.span) == self.expr_span {
            self.expr_span = None;
        }
    }
}
