// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:gcloud/db.dart';
import 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../model/appengine/commit.dart';
import '../model/appengine/key_helper.dart';
import '../model/appengine/task.dart';
import '../model/ci_yaml/ci_yaml.dart';
import '../model/ci_yaml/target.dart';
import '../model/google/token_info.dart';
import '../request_handling/api_request_handler.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../service/config.dart';
import '../service/datastore.dart';
import '../service/logging.dart';
import '../service/luci_build_service.dart';
import '../service/scheduler.dart';

/// Reruns a postsubmit LUCI build.
///
/// Expects either [taskKeyParam] or a set of params that give enough detail to lookup a task in datastore.
@immutable
class ResetProdTask extends ApiRequestHandler<Body> {
  const ResetProdTask(
    Config config,
    AuthenticationProvider authenticationProvider,
    this.luciBuildService,
    this.scheduler, {
    @visibleForTesting DatastoreServiceProvider? datastoreProvider,
  })  : datastoreProvider = datastoreProvider ?? DatastoreService.defaultProvider,
        super(config: config, authenticationProvider: authenticationProvider);

  final DatastoreServiceProvider datastoreProvider;
  final LuciBuildService luciBuildService;
  final Scheduler scheduler;

  static const String branchParam = 'Branch';
  static const String taskKeyParam = 'Key';
  static const String ownerParam = 'Owner';
  static const String repoParam = 'Repo';
  static const String commitShaParam = 'Commit';
  static const String builderParam = 'Builder';

  @override
  Future<Body> post() async {
    final DatastoreService datastore = datastoreProvider(config.db);
    final String? encodedKey = requestData![taskKeyParam] as String?;
    String? gitBranch = requestData![branchParam] as String?;
    final String owner = requestData![ownerParam] as String? ?? 'flutter';
    final String? repo = requestData![repoParam] as String?;
    final String? sha = requestData![commitShaParam] as String?;
    final TokenInfo token = await tokenInfo(request!);
    final String? taskName = requestData![builderParam] as String?;

    RepositorySlug? slug;

    if (encodedKey != null && encodedKey.isNotEmpty) {
      // Check params required for dashboard.
      checkRequiredParameters(<String>[taskKeyParam]);
    } else {
      // Checks params required when this API is called with curl.
      checkRequiredParameters(<String>[commitShaParam, builderParam, repoParam]);
      slug = RepositorySlug(owner, repo!);
      gitBranch ??= Config.defaultBranch(slug);
    }

    final Task task = await _getTaskFromNamedParams(
      datastore: datastore,
      encodedKey: encodedKey,
      gitBranch: gitBranch,
      name: taskName,
      sha: sha,
      slug: slug,
    );
    final Commit commit = await _getCommitFromTask(datastore, task);

    final CiYaml ciYaml = await scheduler.getCiYaml(commit);
    final Target target = ciYaml.postsubmitTargets.singleWhere((Target target) => target.value.name == task.name);

    final Map<String, List<String>> tags = <String, List<String>>{
      'triggered_by': <String>[token.email!],
      'trigger_type': <String>['manual'],
    };
    final bool isRerunning = await luciBuildService.checkRerunBuilder(
      commit: commit,
      task: task,
      target: target,
      datastore: datastore,
      tags: tags,
      ignoreChecks: true,
    );
    if (isRerunning == false) {
      throw InternalServerError('Failed to rerun ${task.name}');
    }

    return Body.empty;
  }

  /// Retrieve [Task] from [DatastoreService] from either an encoded key or commit + task name info.
  ///
  /// If [encodedKey] is passed, [KeyHelper] will decode it directly and return the associated entity.
  ///
  /// Otherwise, [name], [gitBranch], [sha], and [slug] must be passed to find the [Task].
  Future<Task> _getTaskFromNamedParams({
    required DatastoreService datastore,
    String? encodedKey,
    String? gitBranch,
    String? name,
    String? sha,
    RepositorySlug? slug,
  }) async {
    if (encodedKey != null && encodedKey.isNotEmpty) {
      final Key<int> key = config.keyHelper.decode(encodedKey) as Key<int>;
      return datastore.lookupByValue<Task>(key);
    }

    final Key<String> commitKey = await _constructCommitKey(
      datastore: datastore,
      gitBranch: gitBranch!,
      sha: sha!,
      slug: slug!,
    );

    final Query<Task> query = datastore.db.query<Task>(ancestorKey: commitKey);
    final List<Task> initialTasks = await query.run().toList();
    log.fine('Found ${initialTasks.length} tasks for commit');
    final List<Task> tasks = <Task>[];
    log.fine('Searching for task with name=$name');
    for (Task task in initialTasks) {
      if (task.name == name) {
        tasks.add(task);
      }
    }

    if (tasks.length != 1) {
      log.severe('Found ${tasks.length} entries for builder $name');
      throw InternalServerError('Expected to find 1 task for $name, but found ${tasks.length}');
    }

    return tasks.single;
  }

  /// Construct the Datastore key for [Commit] that is the ancestor to this [Task].
  ///
  /// Throws [BadRequestException] if the given git branch does not exist in [CocoonConfig].
  Future<Key<String>> _constructCommitKey({
    required DatastoreService datastore,
    required String gitBranch,
    required String sha,
    required RepositorySlug slug,
  }) async {
    gitBranch = gitBranch.trim();
    sha = sha.trim();
    final List<String> flutterBranches = await config.flutterBranches;
    if (!flutterBranches.contains(gitBranch)) {
      throw BadRequestException('Failed to find flutter/flutter branch: $gitBranch\n'
          'If this is a valid branch, '
          'see https://github.com/flutter/cocoon/tree/master/app_dart#branching-support-for-flutter-repo');
    }
    final String id = '${slug.fullName}/$gitBranch/$sha';
    final Key<String> commitKey = datastore.db.emptyKey.append<String>(Commit, id: id);
    log.fine('Constructed commit key=$id');
    // Return the official key from Datastore for task lookups.
    final Commit commit = await datastore.lookupByValue<Commit>(commitKey);
    return commit.key;
  }

  /// Returns the [Commit] associated with [Task].
  Future<Commit> _getCommitFromTask(DatastoreService datastore, Task task) async {
    return (await datastore.lookupByKey<Commit>(<Key<dynamic>>[task.parentKey!])).single!;
  }
}
