use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::fulfill_or_allowed;
use clippy_utils::source::snippet;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
use rustc_span::symbol::Symbol;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for struct constructors where the order of the field
    /// init in the constructor is inconsistent with the order in the
    /// struct definition.
    ///
    /// ### Why is this bad?
    /// Since the order of fields in a constructor doesn't affect the
    /// resulted instance as the below example indicates,
    ///
    /// ```no_run
    /// #[derive(Debug, PartialEq, Eq)]
    /// struct Foo {
    ///     x: i32,
    ///     y: i32,
    /// }
    /// let x = 1;
    /// let y = 2;
    ///
    /// // This assertion never fails:
    /// assert_eq!(Foo { x, y }, Foo { y, x });
    /// ```
    ///
    /// inconsistent order can be confusing and decreases readability and consistency.
    ///
    /// ### Example
    /// ```no_run
    /// struct Foo {
    ///     x: i32,
    ///     y: i32,
    /// }
    /// let x = 1;
    /// let y = 2;
    ///
    /// Foo { y, x };
    /// ```
    ///
    /// Use instead:
    /// ```no_run
    /// # struct Foo {
    /// #     x: i32,
    /// #     y: i32,
    /// # }
    /// # let x = 1;
    /// # let y = 2;
    /// Foo { x, y };
    /// ```
    #[clippy::version = "1.52.0"]
    pub INCONSISTENT_STRUCT_CONSTRUCTOR,
    pedantic,
    "the order of the field init is inconsistent with the order in the struct definition"
}

impl_lint_pass!(InconsistentStructConstructor => [
    INCONSISTENT_STRUCT_CONSTRUCTOR,
]);

pub struct InconsistentStructConstructor {
    check_inconsistent_struct_field_initializers: bool,
}

impl InconsistentStructConstructor {
    pub fn new(conf: &'static Conf) -> Self {
        Self {
            check_inconsistent_struct_field_initializers: conf.check_inconsistent_struct_field_initializers,
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        let ExprKind::Struct(_, fields, _) = expr.kind else {
            return;
        };
        let all_fields_are_shorthand = fields.iter().all(|f| f.is_shorthand);
        let applicability = if all_fields_are_shorthand {
            Applicability::MachineApplicable
        } else if self.check_inconsistent_struct_field_initializers {
            Applicability::MaybeIncorrect
        } else {
            return;
        };
        if !expr.span.from_expansion()
            && let ty = cx.typeck_results().expr_ty(expr)
            && let Some(adt_def) = ty.ty_adt_def()
            && adt_def.is_struct()
            && let Some(local_def_id) = adt_def.did().as_local()
            && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id)
            && let Some(variant) = adt_def.variants().iter().next()
        {
            let mut def_order_map = FxHashMap::default();
            for (idx, field) in variant.fields.iter().enumerate() {
                def_order_map.insert(field.name, idx);
            }

            if is_consistent_order(fields, &def_order_map) {
                return;
            }

            let span = field_with_attrs_span(cx.tcx, fields.first().unwrap())
                .with_hi(field_with_attrs_span(cx.tcx, fields.last().unwrap()).hi());

            if !fulfill_or_allowed(cx, INCONSISTENT_STRUCT_CONSTRUCTOR, Some(ty_hir_id)) {
                span_lint_and_then(
                    cx,
                    INCONSISTENT_STRUCT_CONSTRUCTOR,
                    span,
                    "struct constructor field order is inconsistent with struct definition field order",
                    |diag| {
                        let msg = if all_fields_are_shorthand {
                            "try"
                        } else {
                            "if the field evaluation order doesn't matter, try"
                        };
                        let sugg = suggestion(cx, fields, &def_order_map);
                        diag.span_suggestion(span, msg, sugg, applicability);
                    },
                );
            }
        }
    }
}

// Check whether the order of the fields in the constructor is consistent with the order in the
// definition.
fn is_consistent_order<'tcx>(fields: &'tcx [hir::ExprField<'tcx>], def_order_map: &FxHashMap<Symbol, usize>) -> bool {
    let mut cur_idx = usize::MIN;
    for f in fields {
        let next_idx = def_order_map[&f.ident.name];
        if cur_idx > next_idx {
            return false;
        }
        cur_idx = next_idx;
    }

    true
}

fn suggestion<'tcx>(
    cx: &LateContext<'_>,
    fields: &'tcx [hir::ExprField<'tcx>],
    def_order_map: &FxHashMap<Symbol, usize>,
) -> String {
    let ws = fields
        .windows(2)
        .map(|w| {
            let w0_span = field_with_attrs_span(cx.tcx, &w[0]);
            let w1_span = field_with_attrs_span(cx.tcx, &w[1]);
            let span = w0_span.between(w1_span);
            snippet(cx, span, " ")
        })
        .collect::<Vec<_>>();

    let mut fields = fields.to_vec();
    fields.sort_unstable_by_key(|field| def_order_map[&field.ident.name]);
    let field_snippets = fields
        .iter()
        .map(|field| snippet(cx, field_with_attrs_span(cx.tcx, field), ".."))
        .collect::<Vec<_>>();

    assert_eq!(field_snippets.len(), ws.len() + 1);

    let mut sugg = String::new();
    for i in 0..field_snippets.len() {
        sugg += &field_snippets[i];
        if i < ws.len() {
            sugg += &ws[i];
        }
    }
    sugg
}

fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span {
    if let Some(attr) = tcx.hir_attrs(field.hir_id).first() {
        field.span.with_lo(attr.span().lo())
    } else {
        field.span
    }
}
