// Copyright 2019 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:github/github.dart';
import 'package:meta/meta.dart';

import '../model/appengine/commit.dart';
import '../model/appengine/github_build_status_update.dart';
import '../model/appengine/stage.dart';
import '../model/appengine/task.dart';
import 'datastore.dart';

/// Function signature for a [BuildStatusService] provider.
typedef BuildStatusServiceProvider = BuildStatusService Function(DatastoreService datastoreService);

/// Branches that are used to calculate the tree status.
const Set<String> defaultBranches = <String>{'refs/heads/main', 'refs/heads/master'};

/// Class that calculates the current build status.
class BuildStatusService {
  const BuildStatusService(this.datastoreService);

  final DatastoreService datastoreService;

  /// Creates and returns a [DatastoreService] using [db] and [maxEntityGroups].
  static BuildStatusService defaultProvider(DatastoreService datastoreService) {
    return BuildStatusService(datastoreService);
  }

  @visibleForTesting
  static const int numberOfCommitsToReferenceForTreeStatus = 20;

  /// Calculates and returns the "overall" status of the Flutter build.
  ///
  /// This calculation operates by looking for the most recent success or
  /// failure for every (non-flaky) task in the manifest.
  ///
  /// Take the example build dashboard below:
  /// ✔ = passed, ✖ = failed, ☐ = new, ░ = in progress, s = skipped
  /// +---+---+---+---+
  /// | A | B | C | D |
  /// +---+---+---+---+
  /// | ✔ | ☐ | ░ | s |
  /// +---+---+---+---+
  /// | ✔ | ░ | ✔ | ✖ |
  /// +---+---+---+---+
  /// | ✔ | ✖ | ✔ | ✔ |
  /// +---+---+---+---+
  /// This build will fail because of Task B only. Task D is not included in
  /// the latest commit status, so it does not impact the build status.
  /// Task B fails because its last known status was to be failing, even though
  /// there is currently a newer version that is in progress.
  ///
  /// Tree status is only for [defaultBranches].
  Future<BuildStatus?> calculateCumulativeStatus(RepositorySlug slug) async {
    final List<CommitStatus> statuses = await retrieveCommitStatus(
      limit: numberOfCommitsToReferenceForTreeStatus,
      slug: slug,
    ).toList();
    if (statuses.isEmpty) {
      return BuildStatus.failure();
    }

    final Map<String, bool> tasksInProgress = _findTasksRelevantToLatestStatus(statuses);
    if (tasksInProgress.isEmpty) {
      return BuildStatus.failure();
    }

    final List<String> failedTasks = <String>[];
    for (CommitStatus status in statuses) {
      for (Stage stage in status.stages) {
        for (Task task in stage.tasks) {
          /// If a task [isRelevantToLatestStatus] but has not run yet, we look
          /// for a previous run of the task from the previous commit.
          final bool isRelevantToLatestStatus = tasksInProgress.containsKey(task.name);

          /// Tasks that are not relevant to the latest status will have a
          /// null value in the map.
          final bool taskInProgress = tasksInProgress[task.name] ?? true;

          if (isRelevantToLatestStatus && taskInProgress) {
            if (task.isFlaky! || _isSuccessful(task)) {
              /// This task no longer needs to be checked to see if it causing
              /// the build status to fail.
              tasksInProgress[task.name!] = false;
            } else if (_isFailed(task) || _isRerunning(task)) {
              failedTasks.add(task.name!);

              /// This task no longer needs to be checked to see if its causing
              /// the build status to fail since its been
              /// added to the failedTasks list.
              tasksInProgress[task.name!] = false;
            }
          }
        }
      }
    }
    return failedTasks.isNotEmpty ? BuildStatus.failure(failedTasks) : BuildStatus.success();
  }

  /// Creates a map of the tasks that need to be checked for the build status.
  ///
  /// This is based on the most recent [CommitStatus] and all of its tasks.
  Map<String, bool> _findTasksRelevantToLatestStatus(List<CommitStatus> statuses) {
    final Map<String, bool> tasks = <String, bool>{};

    for (Stage stage in statuses.first.stages) {
      for (Task task in stage.tasks) {
        tasks[task.name!] = true;
      }
    }

    return tasks;
  }

  /// Retrieves the comprehensive status of every task that runs per commit.
  ///
  /// The returned stream will be ordered by most recent commit first, then
  /// the next newest, and so on.
  Stream<CommitStatus> retrieveCommitStatus({
    required int limit,
    int? timestamp,
    String? branch,
    required RepositorySlug slug,
  }) async* {
    await for (Commit commit in datastoreService.queryRecentCommits(
      limit: limit,
      timestamp: timestamp,
      branch: branch,
      slug: slug,
    )) {
      final List<Stage> stages = await datastoreService.queryTasksGroupedByStage(commit);
      yield CommitStatus(commit, stages);
    }
  }

  bool _isFailed(Task task) {
    return task.status == Task.statusFailed || task.status == Task.statusInfraFailure;
  }

  bool _isSuccessful(Task task) {
    return task.status == Task.statusSucceeded;
  }

  bool _isRerunning(Task task) {
    return task.attempts! > 1 && (task.status == Task.statusInProgress || task.status == Task.statusNew);
  }
}

/// Class that holds the status for all tasks corresponding to a particular
/// commit.
///
/// Tasks may still be running, and thus their status is subject to change.
/// Put another way, this class holds information that is a snapshot in time.
@immutable
class CommitStatus {
  /// Creates a new [CommitStatus].
  const CommitStatus(this.commit, this.stages);

  /// The commit against which all the tasks in [stages] are run.
  final Commit commit;

  /// The partitioned stages, each of which holds a bucket of tasks that
  /// belong in the stage.
  final List<Stage> stages;
}

@immutable
class BuildStatus {
  const BuildStatus._(this.value, [this.failedTasks = const <String>[]])
      : assert(value == GithubBuildStatusUpdate.statusSuccess || value == GithubBuildStatusUpdate.statusFailure);
  factory BuildStatus.success() => const BuildStatus._(GithubBuildStatusUpdate.statusSuccess);
  factory BuildStatus.failure([List<String> failedTasks = const <String>[]]) =>
      BuildStatus._(GithubBuildStatusUpdate.statusFailure, failedTasks);

  final String value;
  final List<String> failedTasks;

  bool get succeeded {
    return value == GithubBuildStatusUpdate.statusSuccess;
  }

  String get githubStatus => value;

  @override
  int get hashCode {
    int hash = 17;
    hash = hash * 31 + value.hashCode;
    hash = hash * 31 + failedTasks.hashCode;
    return hash;
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other is BuildStatus) {
      if (value != other.value) {
        return false;
      }
      if (other.failedTasks.length != failedTasks.length) {
        return false;
      }
      for (int i = 0; i < failedTasks.length; ++i) {
        if (failedTasks[i] != other.failedTasks[i]) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  @override
  String toString() => '$value $failedTasks';
}
