// 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 'dart:io';

import 'package:cocoon_service/src/model/appengine/branch.dart' as md;
import 'package:gcloud/db.dart';
import 'package:github/github.dart' show Branch, GitHub, RepositoryCommit, RepositorySlug;
import 'package:process/process.dart';

import '../request_handling/body.dart';
import '../request_handling/request_handler.dart';
import '../service/config.dart';
import '../service/datastore.dart';

/// Update and return currently active branches across all repos.
///
/// Returns all branches with associated key, branch name and repository name, for branches with recent commit acitivies
/// within the past [GetBranches.kActiveBranchActivityPeriod] days.
///
/// GET: /api/update-branches
///
///
/// Response: Status 200 OK
///[
///      {
///         "key":ahFmbHV0dGVyLWRhc2hib2FyZHIuCxIGQnJhbmNoIiJmbHV0dGVyL2ZsdXR0ZXIvYnJhbmNoLWNyZWF0ZWQtb2xkDKIBCVtkZWZhdWx0XQ,
///         "branch":{
///            "branch":"branch-created-old",
///            "repository":"flutter/flutter"
///         }
///      }
///     {
///        "key":ahFmbHV0dGVyLWRhc2hib2FyZHIuCxIGQnJhbmNoIiJmbHV0dGVyL2ZsdXR0ZXIvYnJhbmNoLWNyZWF0ZWQtbm93DKIBCVtkZWZhdWx0XQ,
///        "branch":{
///           "branch":"branch-created-now",
///           "repository":"flutter/flutter"
///        }
///     }
///]

class UpdateBranches extends RequestHandler<Body> {
  UpdateBranches({
    required super.config,
    this.datastoreProvider = DatastoreService.defaultProvider,
    this.processManager,
  });

  final DatastoreServiceProvider datastoreProvider;
  ProcessManager? processManager;

  static const Duration kActiveBranchActivityPeriod = Duration(days: 60);

  @override
  Future<Body> get() async {
    final DatastoreService datastore = datastoreProvider(config.db);

    await _updateBranchesForAllRepos(config, datastore);

    final List<md.Branch> branches = await datastore
        .queryBranches()
        .where((md.Branch b) =>
            DateTime.now().millisecondsSinceEpoch - b.lastActivity! < kActiveBranchActivityPeriod.inMilliseconds)
        .toList();
    return Body.forJson(branches);
  }

  Future<void> _updateBranchesForAllRepos(Config config, DatastoreService datastore) async {
    DateTime timeNow = DateTime.now();

    processManager ??= const LocalProcessManager();
    final Set<RepositorySlug> slugs = config.supportedRepos;
    for (RepositorySlug slug in slugs) {
      ProcessResult result =
          processManager!.runSync(['git', 'ls-remote', '--heads', 'git@github.com:flutter/${slug.name}']);
      // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- only a exit code of 0 is good for windows
      // for mac or linux, exit code in the range 0 to 255 is good
      if ((Platform.isWindows && result.exitCode != 0) ||
          ((Platform.isMacOS || Platform.isLinux) && result.exitCode < 0)) {
        throw const FormatException('returned exit code from git ls-remote is bad');
      }
      List<String> shaAndName = (result.stdout as String).trim().split(RegExp(' |\t|\r?\n'));
      List<String> branchShas = [];
      List<String> branchNames = [];
      for (int i = 0; i < shaAndName.length; i += 2) {
        branchShas.add(shaAndName[i]);
        branchNames.add(shaAndName[i + 1].replaceAll('refs/heads/', ''));
      }
      final GitHub github = await config.createGitHubClient(slug: slug);
      await _updateBranchesForRepo(branchShas, branchNames, github, slug, datastore, timeNow);
    }
    return;
  }

  Future<void> _updateBranchesForRepo(List<String> branchShas, List<String> branchNames, GitHub github,
      RepositorySlug slug, DatastoreService datastore, DateTime timeNow) async {
    List<md.Branch> updatedBranches = [];
    for (int i = 0; i < branchShas.length; i += 1) {
      final RepositoryCommit branchCommit = await github.repositories.getCommit(slug, branchShas[i]);
      int lastUpdate = branchCommit.commit!.committer!.date!.millisecondsSinceEpoch;
      if (lastUpdate > timeNow.subtract(kActiveBranchActivityPeriod).millisecondsSinceEpoch) {
        final String id = '${slug.fullName}/${branchNames[i]}';
        final Key<String> key = datastore.db.emptyKey.append<String>(Branch, id: id);
        updatedBranches.add(md.Branch(key: key, lastActivity: lastUpdate));
      }
    }
    await datastore.insert(updatedBranches);
  }
}
