// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/ast/ast.dart';

import '../analyzer.dart';

const _desc = r'No await no async.';

class UnnecessaryAsync extends LintRule {
  UnnecessaryAsync()
      : super(
          name: LintNames.unnecessary_async,
          description: _desc,
          state: const State.experimental(),
        );

  @override
  LintCode get lintCode => LinterLintCode.unnecessary_async;

  @override
  void registerNodeProcessors(
    NodeLintRegistry registry,
    LinterContext context,
  ) {
    var visitor = _Visitor(this);
    registry.addFunctionDeclaration(this, visitor);
    registry.addFunctionExpression(this, visitor);
    registry.addMethodDeclaration(this, visitor);
  }
}

class _HasAwaitVisitor extends RecursiveAstVisitor<void> {
  bool hasAwait = false;
  bool everyReturnHasValue = true;
  bool returnsOnlyFuture = true;

  @override
  void visitAwaitExpression(AwaitExpression node) {
    hasAwait = true;
    super.visitAwaitExpression(node);
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
    _updateWithExpression(node.expression);
    super.visitExpressionFunctionBody(node);
  }

  @override
  void visitForElement(ForElement node) {
    hasAwait |= node.awaitKeyword != null;
    super.visitForElement(node);
  }

  @override
  void visitForStatement(ForStatement node) {
    hasAwait |= node.awaitKeyword != null;
    super.visitForStatement(node);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    // Stop the recursion.
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    var expression = node.expression;
    if (expression != null) {
      _updateWithExpression(expression);
    } else {
      everyReturnHasValue = false;
    }

    super.visitReturnStatement(node);
  }

  void _updateWithExpression(Expression expression) {
    var type = expression.staticType;
    if (!(type is InterfaceType &&
        type.isDartAsyncFutureOrSubtype &&
        type.nullabilitySuffix == NullabilitySuffix.none)) {
      returnsOnlyFuture = false;
    }
  }
}

class _Visitor extends SimpleAstVisitor<void> {
  final LintRule rule;

  _Visitor(this.rule);

  @override
  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
    var element = node.declaredFragment!.element;

    _checkBody(
      body: node.functionExpression.body,
      returnType: element.returnType,
    );
  }

  @override
  void visitFunctionExpression(covariant FunctionExpressionImpl node) {
    // Here we handle only closures.
    if (node.parent is FunctionDeclaration) {
      return;
    }

    var bodyContext = node.body.bodyContext;

    _checkBody(
      body: node.body,
      returnType: bodyContext?.imposedType,
    );
  }

  @override
  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
    var element = node.declaredFragment!.element;

    _checkBody(
      body: node.body,
      returnType: element.returnType,
    );
  }

  void _checkBody({
    required FunctionBodyImpl body,
    required DartType? returnType,
  }) {
    var asyncKeyword = body.keyword;
    if (asyncKeyword == null || asyncKeyword.keyword != Keyword.ASYNC) {
      return;
    }

    if (body.star != null) {
      return;
    }

    var bodyContext = body.bodyContext;
    if (bodyContext == null) {
      return;
    }

    var visitor = _HasAwaitVisitor();
    body.accept(visitor);

    if (visitor.hasAwait) {
      return;
    }

    // If no imposed return type, then any type is OK.
    if (returnType == null) {
      rule.reportLintForToken(asyncKeyword);
      return;
    }

    // We don't have to return anything.
    // So, the generated `Future` is not necessary.
    if (returnType is VoidType) {
      rule.reportLintForToken(asyncKeyword);
      return;
    }

    // It is OK to return values into `FutureOr`.
    // So, wrapping values into `Future` is not necessary.
    if (returnType.isDartAsyncFutureOr) {
      rule.reportLintForToken(asyncKeyword);
      return;
    }

    // We handle only `Future<T>` below.
    if (!returnType.isDartAsyncFuture) {
      return;
    }

    // If the body may complete normally, we cannot remove `async`.
    // This would make the body return `null`.
    // And `null` is not the same as `Future.value(null)`.
    if (bodyContext.mayCompleteNormally) {
      return;
    }

    // If every `return` returns `Future`, we don't need wrapping.
    if (visitor.everyReturnHasValue && visitor.returnsOnlyFuture) {
      rule.reportLintForToken(asyncKeyword);
      return;
    }
  }
}

extension on InterfaceType {
  bool get isDartAsyncFutureOrSubtype {
    var typeProvider = element3.library2.typeProvider;
    return asInstanceOf2(typeProvider.futureElement2) != null;
  }
}
