use clippy_utils::attrs::span_contains_cfg;
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::span_contains_non_whitespace;
use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
use rustc_errors::Applicability;
use rustc_hir::def::DefKind::Ctor;
use rustc_hir::def::Res::Def;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node, Pat, PatKind, Path, QPath, Variant, VariantData};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::impl_lint_pass;
use rustc_span::{BytePos, Span};

declare_clippy_lint! {
    /// ### What it does
    /// Finds enum variants without fields that are declared with empty brackets.
    ///
    /// ### Why restrict this?
    /// Empty brackets after a enum variant declaration are redundant and can be omitted,
    /// and it may be desirable to do so consistently for style.
    ///
    /// However, removing the brackets also introduces a public constant named after the variant,
    /// so this is not just a syntactic simplification but an API change, and adding them back
    /// is a *breaking* API change.
    ///
    /// ### Example
    /// ```no_run
    /// enum MyEnum {
    ///     HasData(u8),
    ///     HasNoData(),       // redundant parentheses
    ///     NoneHereEither {}, // redundant braces
    /// }
    /// ```
    ///
    /// Use instead:
    /// ```no_run
    /// enum MyEnum {
    ///     HasData(u8),
    ///     HasNoData,
    ///     NoneHereEither,
    /// }
    /// ```
    #[clippy::version = "1.77.0"]
    pub EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
    restriction,
    "finds enum variants with empty brackets"
}

declare_clippy_lint! {
    /// ### What it does
    /// Finds structs without fields (a so-called "empty struct") that are declared with brackets.
    ///
    /// ### Why restrict this?
    /// Empty brackets after a struct declaration can be omitted,
    /// and it may be desirable to do so consistently for style.
    ///
    /// However, removing the brackets also introduces a public constant named after the struct,
    /// so this is not just a syntactic simplification but an API change, and adding them back
    /// is a *breaking* API change.
    ///
    /// ### Example
    /// ```no_run
    /// struct Cookie {}
    /// struct Biscuit();
    /// ```
    /// Use instead:
    /// ```no_run
    /// struct Cookie;
    /// struct Biscuit;
    /// ```
    #[clippy::version = "1.62.0"]
    pub EMPTY_STRUCTS_WITH_BRACKETS,
    restriction,
    "finds struct declarations with empty brackets"
}

impl_lint_pass!(EmptyWithBrackets => [
    EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
    EMPTY_STRUCTS_WITH_BRACKETS,
]);

#[derive(Debug)]
enum Usage {
    Unused { redundant_use_sites: Vec<Span> },
    Used,
    NoDefinition { redundant_use_sites: Vec<Span> },
}

#[derive(Default)]
pub struct EmptyWithBrackets {
    // Value holds `Usage::Used` if the empty tuple variant was used as a function
    empty_tuple_enum_variants: FxIndexMap<LocalDefId, Usage>,
}

impl LateLintPass<'_> for EmptyWithBrackets {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
        // FIXME: handle `struct $name {}`
        if let ItemKind::Struct(ident, generics, var_data) = &item.kind
            && !item.span.from_expansion()
            && !ident.span.from_expansion()
            && has_brackets(var_data)
            && let span_after_ident = item.span.with_lo(generics.span.hi())
            && has_no_fields(cx, var_data, span_after_ident)
        {
            span_lint_and_then(
                cx,
                EMPTY_STRUCTS_WITH_BRACKETS,
                span_after_ident,
                "found empty brackets on struct declaration",
                |diagnostic| {
                    diagnostic.span_suggestion_hidden(
                        span_after_ident,
                        "remove the brackets",
                        ";",
                        Applicability::Unspecified,
                    );
                },
            );
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'_>, variant: &Variant<'_>) {
        if !variant.span.from_expansion()
            && !variant.ident.span.from_expansion()
            && let span_after_ident = variant.span.with_lo(variant.ident.span.hi())
            && has_no_fields(cx, &variant.data, span_after_ident)
        {
            match variant.data {
                VariantData::Struct { .. } => {
                    self.add_enum_variant(variant.def_id);
                },
                VariantData::Tuple(.., local_def_id) => {
                    // Don't lint reachable tuple enums
                    if cx.effective_visibilities.is_reachable(variant.def_id) {
                        return;
                    }
                    self.add_enum_variant(local_def_id);
                },
                VariantData::Unit(..) => {},
            }
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if let Some((def_id, mut span)) = check_expr_for_enum_as_function(cx, expr) {
            if span.is_empty()
                && let Some(parentheses_span) = call_parentheses_span(cx.tcx, expr)
            {
                span = parentheses_span;
            }

            if span.is_empty() {
                // The parentheses are not redundant.
                self.empty_tuple_enum_variants.insert(def_id, Usage::Used);
            } else {
                // Do not count expressions from macro expansion as a redundant use site.
                if expr.span.from_expansion() {
                    return;
                }
                self.update_enum_variant_usage(def_id, span);
            }
        }
    }

    fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
        if !pat.span.from_expansion()
            && let Some((def_id, span)) = check_pat_for_enum_as_function(cx, pat)
        {
            self.update_enum_variant_usage(def_id, span);
        }
    }

    fn check_crate_post(&mut self, cx: &LateContext<'_>) {
        for (&local_def_id, usage) in &self.empty_tuple_enum_variants {
            // Ignore all variants with Usage::Used or Usage::NoDefinition
            let Usage::Unused { redundant_use_sites } = usage else {
                continue;
            };

            // Attempt to fetch the Variant from LocalDefId.
            let variant = if let Node::Variant(variant) = cx.tcx.hir_node_by_def_id(local_def_id) {
                variant
            } else if let Node::Variant(variant) = cx.tcx.hir_node_by_def_id(cx.tcx.local_parent(local_def_id)) {
                variant
            } else {
                continue;
            };

            // Span of the parentheses in variant definition
            let span = variant.span.with_lo(variant.ident.span.hi());
            let span_inner = span
                .with_lo(SpanRangeExt::trim_start(span, cx).start + BytePos(1))
                .with_hi(span.hi() - BytePos(1));
            if span_contains_non_whitespace(cx, span_inner, false) {
                continue;
            }
            span_lint_hir_and_then(
                cx,
                EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
                variant.hir_id,
                span,
                "enum variant has empty brackets",
                |diagnostic| {
                    if redundant_use_sites.is_empty() {
                        // If there's no redundant use sites, the definition is the only place to modify.
                        diagnostic.span_suggestion_hidden(
                            span,
                            "remove the brackets",
                            "",
                            Applicability::MaybeIncorrect,
                        );
                    } else {
                        let mut parentheses_spans: Vec<_> =
                            redundant_use_sites.iter().map(|span| (*span, String::new())).collect();
                        parentheses_spans.push((span, String::new()));
                        diagnostic.multipart_suggestion(
                            "remove the brackets",
                            parentheses_spans,
                            Applicability::MaybeIncorrect,
                        );
                    }
                },
            );
        }
    }
}

impl EmptyWithBrackets {
    fn add_enum_variant(&mut self, local_def_id: LocalDefId) {
        self.empty_tuple_enum_variants
            .entry(local_def_id)
            .and_modify(|entry| {
                // empty_tuple_enum_variants contains Usage::NoDefinition if the variant was called before
                // the definition was encountered. Now that there's a
                // definition, convert it to Usage::Unused.
                if let Usage::NoDefinition { redundant_use_sites } = entry {
                    *entry = Usage::Unused {
                        redundant_use_sites: redundant_use_sites.clone(),
                    };
                }
            })
            .or_insert_with(|| Usage::Unused {
                redundant_use_sites: vec![],
            });
    }

    fn update_enum_variant_usage(&mut self, def_id: LocalDefId, parentheses_span: Span) {
        match self.empty_tuple_enum_variants.entry(def_id) {
            IndexEntry::Occupied(mut e) => {
                if let Usage::Unused { redundant_use_sites } | Usage::NoDefinition { redundant_use_sites } = e.get_mut()
                {
                    redundant_use_sites.push(parentheses_span);
                }
            },
            IndexEntry::Vacant(e) => {
                // The variant isn't in the IndexMap which means its definition wasn't encountered yet.
                e.insert(Usage::NoDefinition {
                    redundant_use_sites: vec![parentheses_span],
                });
            },
        }
    }
}

fn has_brackets(var_data: &VariantData<'_>) -> bool {
    !matches!(var_data, VariantData::Unit(..))
}

fn has_no_fields(cx: &LateContext<'_>, var_data: &VariantData<'_>, braces_span: Span) -> bool {
    var_data.fields().is_empty() &&
    // there might still be field declarations hidden from the AST
    // (conditionally compiled code using #[cfg(..)])
    !span_contains_cfg(cx, braces_span)
}

// If expression HIR ID and callee HIR ID are same, returns the span of the parentheses, else,
// returns None.
fn call_parentheses_span(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> Option<Span> {
    if let Node::Expr(parent) = tcx.parent_hir_node(expr.hir_id)
        && let ExprKind::Call(callee, ..) = parent.kind
        && callee.hir_id == expr.hir_id
    {
        Some(parent.span.with_lo(expr.span.hi()))
    } else {
        None
    }
}

// Returns the LocalDefId of the variant being called as a function if it exists.
fn check_expr_for_enum_as_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(LocalDefId, Span)> {
    match expr.kind {
        ExprKind::Path(QPath::Resolved(
            _,
            Path {
                res: Def(Ctor(CtorOf::Variant, _), def_id),
                span,
                ..
            },
        )) => def_id.as_local().map(|id| (id, span.with_lo(expr.span.hi()))),
        ExprKind::Struct(qpath, ..)
            if let Def(DefKind::Variant, mut def_id) = cx.typeck_results().qpath_res(qpath, expr.hir_id) =>
        {
            let ty = cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
            if let ty::FnDef(ctor_def_id, _) = ty.kind() {
                def_id = *ctor_def_id;
            }

            def_id.as_local().map(|id| (id, qpath.span().with_lo(expr.span.hi())))
        },
        _ => None,
    }
}

fn check_pat_for_enum_as_function(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(LocalDefId, Span)> {
    match pat.kind {
        PatKind::TupleStruct(qpath, ..)
            if let Def(Ctor(CtorOf::Variant, _), def_id) = cx.typeck_results().qpath_res(&qpath, pat.hir_id) =>
        {
            def_id.as_local().map(|id| (id, qpath.span().with_lo(pat.span.hi())))
        },
        PatKind::Struct(qpath, ..)
            if let Def(DefKind::Variant, mut def_id) = cx.typeck_results().qpath_res(&qpath, pat.hir_id) =>
        {
            let ty = cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
            if let ty::FnDef(ctor_def_id, _) = ty.kind() {
                def_id = *ctor_def_id;
            }

            def_id.as_local().map(|id| (id, qpath.span().with_lo(pat.span.hi())))
        },
        _ => None,
    }
}
