use rustc_ast::node_id::NodeMap;
use rustc_ast::*;
use rustc_hir as hir;
use rustc_hir::{HirId, Target, find_attr};
use rustc_middle::span_bug;
use rustc_span::Span;

use super::{LoweringContext, MoveExprInitializerFinder, MoveExprState};
use crate::FnDeclKind;
use crate::diagnostics::{ClosureCannotBeStatic, CoroutineTooManyParameters};

impl<'hir> LoweringContext<'_, 'hir> {
    // Entry point for `ExprKind::Closure`. Plain closures go through
    // `lower_expr_plain_closure_with_move_exprs`, which can wrap the lowered
    // closure in `let` initializers for `move(...)`. Coroutine closures keep the
    // existing coroutine-specific path and reject `move(...)` for now.
    pub(super) fn lower_expr_closure_expr(
        &mut self,
        e: &Expr,
        closure: &Closure,
    ) -> hir::Expr<'hir> {
        let expr_hir_id = self.lower_node_id(e.id);
        let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e));

        match closure.coroutine_kind {
            // FIXME(TaKO8Ki): Support `move(expr)` in coroutine closures too.
            // For the first step, we only support plain closures.
            Some(coroutine_kind) => hir::Expr {
                hir_id: expr_hir_id,
                kind: self.lower_expr_coroutine_closure(
                    &closure.binder,
                    closure.capture_clause,
                    e.id,
                    expr_hir_id,
                    coroutine_kind,
                    closure.constness,
                    &closure.fn_decl,
                    &closure.body,
                    closure.fn_decl_span,
                    closure.fn_arg_span,
                ),
                span: self.lower_span(e.span),
            },
            None => self.lower_expr_plain_closure_with_move_exprs(
                expr_hir_id,
                attrs,
                &closure.binder,
                closure.capture_clause,
                e.id,
                closure.constness,
                closure.movability,
                &closure.fn_decl,
                &closure.body,
                closure.fn_decl_span,
                closure.fn_arg_span,
                e.span,
            ),
        }
    }

    /// Lowers a plain closure expression and wraps it in an outer block if the
    /// closure body used `move(...)`.
    ///
    /// The lowering is split this way because `move(...)` initializers must be
    /// evaluated before the closure is created, but the closure body must still
    /// lower each `move(...)` occurrence as a use of the synthetic local that
    /// will be introduced by that outer block. For example:
    ///
    /// ```ignore (illustrative)
    /// || (move(move(foo.clone()))).len()
    /// ```
    ///
    /// first lowers the closure body roughly as `|| __move_expr_1.len()` while
    /// recording two occurrences:
    ///
    /// ```ignore (illustrative)
    /// move(foo.clone()) -> __move_expr_0
    /// move(move(foo.clone())) -> __move_expr_1
    /// ```
    ///
    /// This method then lowers the recorded initializers in order and builds the
    /// surrounding block:
    ///
    /// ```ignore (illustrative)
    /// {
    ///     let __move_expr_0 = foo.clone();
    ///     let __move_expr_1 = __move_expr_0;
    ///     || __move_expr_1.len()
    /// }
    /// ```
    fn lower_expr_plain_closure_with_move_exprs(
        &mut self,
        expr_hir_id: HirId,
        attrs: &[hir::Attribute],
        binder: &ClosureBinder,
        capture_clause: CaptureBy,
        closure_id: NodeId,
        constness: Const,
        movability: Movability,
        decl: &FnDecl,
        body: &Expr,
        fn_decl_span: Span,
        fn_arg_span: Span,
        whole_span: Span,
    ) -> hir::Expr<'hir> {
        let (closure_kind, move_expr_state) = self.lower_expr_closure(
            attrs,
            binder,
            capture_clause,
            closure_id,
            constness,
            movability,
            decl,
            body,
            fn_decl_span,
            fn_arg_span,
        );

        if move_expr_state.occurrences.is_empty() {
            return hir::Expr {
                hir_id: expr_hir_id,
                kind: closure_kind,
                span: self.lower_span(whole_span),
            };
        }

        let initializers = MoveExprInitializerFinder::collect(body)
            .into_iter()
            .map(|initializer| (initializer.id, initializer.expr))
            .collect::<NodeMap<_>>();
        let mut stmts = Vec::with_capacity(move_expr_state.occurrences.len());
        let mut initializer_bindings = NodeMap::default();
        for occurrence in &move_expr_state.occurrences {
            // Evaluate the expression inside `move(...)` before creating the
            // closure and store it in a synthetic local:
            // `|| move(foo).bar` becomes roughly
            // `let __move_expr_0 = foo; || __move_expr_0.bar`.
            let expr = initializers[&occurrence.id];
            let init = if initializer_bindings.is_empty() {
                self.lower_expr(expr)
            } else {
                // Earlier entries cover nested `move(...)` expressions that
                // appear inside this initializer, as in
                // `move(move(foo.clone()))`.
                let (init, _) = self.with_move_expr_bindings(
                    Some(MoveExprState {
                        bindings: initializer_bindings.clone(),
                        occurrences: Vec::new(),
                    }),
                    |this| this.lower_expr(expr),
                );
                init
            };
            stmts.push(self.stmt_let_pat(
                None,
                expr.span,
                Some(init),
                occurrence.pat,
                hir::LocalSource::Normal,
            ));
            initializer_bindings.insert(occurrence.id, (occurrence.ident, occurrence.binding));
        }

        let closure_expr = self.arena.alloc(hir::Expr {
            hir_id: expr_hir_id,
            kind: closure_kind,
            span: self.lower_span(whole_span),
        });

        let stmts = self.arena.alloc_from_iter(stmts);
        let block = self.block_all(whole_span, stmts, Some(closure_expr));
        self.expr(whole_span, hir::ExprKind::Block(block, None))
    }

    // Lowers the actual plain closure node and body. The body is lowered while a
    // `MoveExprState` is active, so `move(...)` occurrences become synthetic
    // local uses and the caller can later add the matching initializers.
    fn lower_expr_closure(
        &mut self,
        attrs: &[hir::Attribute],
        binder: &ClosureBinder,
        capture_clause: CaptureBy,
        closure_id: NodeId,
        constness: Const,
        movability: Movability,
        decl: &FnDecl,
        body: &Expr,
        fn_decl_span: Span,
        fn_arg_span: Span,
    ) -> (hir::ExprKind<'hir>, MoveExprState<'hir>) {
        let closure_def_id = self.local_def_id(closure_id);
        let (binder_clause, generic_params) = self.lower_closure_binder(binder);

        let ((body_id, closure_kind), move_expr_state) =
            self.with_new_scopes(fn_decl_span, move |this| {
                let mut coroutine_kind = find_attr!(
                    attrs,
                    Coroutine => hir::CoroutineKind::Coroutine(Movability::Movable)
                );

                this.with_move_expr_bindings(Some(MoveExprState::default()), |this| {
                    // FIXME(contracts): Support contracts on closures?
                    let body_id = this.lower_fn_body(decl, None, |this| {
                        this.coroutine_kind = coroutine_kind;
                        let e = this.lower_expr_mut(body);
                        coroutine_kind = this.coroutine_kind;
                        e
                    });
                    let coroutine_option = this.closure_movability_for_fn(
                        decl,
                        fn_decl_span,
                        coroutine_kind,
                        movability,
                    );
                    (body_id, coroutine_option)
                })
            });
        let Some(move_expr_state) = move_expr_state else {
            span_bug!(fn_decl_span, "plain closure lowering did not return `move(...)` state");
        };
        let explicit_captures: &'hir [hir::ExplicitCapture] = self.arena.alloc_from_iter(
            move_expr_state.occurrences.iter().filter_map(|occurrence| {
                occurrence
                    .explicit_capture
                    .then_some(hir::ExplicitCapture { var_hir_id: occurrence.binding })
            }),
        );

        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
        // Lower outside new scope to preserve `is_in_loop_condition`.
        let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);

        let c = self.arena.alloc(hir::Closure {
            def_id: closure_def_id,
            binder: binder_clause,
            capture_clause: self.lower_capture_clause(capture_clause),
            bound_generic_params,
            fn_decl,
            body: body_id,
            fn_decl_span: self.lower_span(fn_decl_span),
            fn_arg_span: Some(self.lower_span(fn_arg_span)),
            kind: closure_kind,
            constness: self.lower_constness(constness),
            explicit_captures,
        });

        (hir::ExprKind::Closure(c), move_expr_state)
    }

    fn closure_movability_for_fn(
        &mut self,
        decl: &FnDecl,
        fn_decl_span: Span,
        coroutine_kind: Option<hir::CoroutineKind>,
        movability: Movability,
    ) -> hir::ClosureKind {
        match coroutine_kind {
            Some(hir::CoroutineKind::Coroutine(_)) => {
                if decl.inputs.len() > 1 {
                    self.dcx().emit_err(CoroutineTooManyParameters { fn_decl_span });
                }
                hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(movability))
            }
            Some(
                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
                | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
                | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
            ) => {
                panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
            }
            None => {
                if movability == Movability::Static {
                    self.dcx().emit_err(ClosureCannotBeStatic { fn_decl_span });
                }
                hir::ClosureKind::Closure
            }
        }
    }

    fn lower_closure_binder<'c>(
        &mut self,
        binder: &'c ClosureBinder,
    ) -> (hir::ClosureBinder, &'c [GenericParam]) {
        let (binder, params) = match binder {
            ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
            ClosureBinder::For { span, generic_params } => {
                let span = self.lower_span(*span);
                (hir::ClosureBinder::For { span }, &**generic_params)
            }
        };

        (binder, params)
    }

    // Coroutine closures are lowered separately because they build a different
    // body shape. This path pushes `None` for `move_expr_bindings`, so any
    // `move(...)` in the coroutine body gets a targeted unsupported-position
    // error instead of being collected like a plain closure occurrence.
    fn lower_expr_coroutine_closure(
        &mut self,
        binder: &ClosureBinder,
        capture_clause: CaptureBy,
        closure_id: NodeId,
        closure_hir_id: HirId,
        coroutine_kind: CoroutineKind,
        constness: Const,
        decl: &FnDecl,
        body: &Expr,
        fn_decl_span: Span,
        fn_arg_span: Span,
    ) -> hir::ExprKind<'hir> {
        let closure_def_id = self.local_def_id(closure_id);
        let (binder_clause, generic_params) = self.lower_closure_binder(binder);

        let coroutine_desugaring = match coroutine_kind {
            CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
            CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
            CoroutineKind::AsyncGen { span, .. } => {
                span_bug!(span, "only async closures and `iter!` closures are supported currently")
            }
        };

        let body = self.with_new_scopes(fn_decl_span, |this| {
            let inner_decl =
                FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };

            // Transform `async |x: u8| -> X { ... }` into
            // `|x: u8| || -> X { ... }`.
            let body_id = this.lower_body(|this| {
                let ((parameters, expr), _) = this.with_move_expr_bindings(None, |this| {
                    this.lower_coroutine_body_with_moved_arguments(
                        &inner_decl,
                        |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
                        fn_decl_span,
                        body.span,
                        coroutine_kind,
                        hir::CoroutineSource::Closure,
                    )
                });

                this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);

                (parameters, expr)
            });
            body_id
        });

        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
        // We need to lower the declaration outside the new scope, because we
        // have to conserve the state of being inside a loop condition for the
        // closure argument types.
        let fn_decl =
            self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);

        if let Const::Yes(span) = constness {
            self.dcx().span_err(span, "const coroutines are not supported");
        }

        let c = self.arena.alloc(hir::Closure {
            def_id: closure_def_id,
            binder: binder_clause,
            capture_clause: self.lower_capture_clause(capture_clause),
            bound_generic_params,
            fn_decl,
            body,
            fn_decl_span: self.lower_span(fn_decl_span),
            fn_arg_span: Some(self.lower_span(fn_arg_span)),
            // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck
            // knows that a `FnDecl` output type like `-> &str` actually means
            // "coroutine that returns &str", rather than directly returning a `&str`.
            kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring),
            constness: self.lower_constness(constness),
            explicit_captures: &[],
        });
        hir::ExprKind::Closure(c)
    }
}
