// Copyright 2021 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:cocoon_service/src/service/config.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:cocoon_service/src/service/github_service.dart';
import 'package:gcloud/db.dart';
import 'package:github/github.dart' as gh;
import 'package:github/hooks.dart';
import 'package:retry/retry.dart';

import '../model/appengine/branch.dart';
import '../model/gerrit/commit.dart';
import '../request_handling/exceptions.dart';
import 'gerrit_service.dart';
import 'logging.dart';

class RetryException implements Exception {}

/// A class to manage GitHub branches.
///
/// Track branch activities such as branch creation, and helps manage release branches.
class BranchService {
  BranchService({
    required this.config,
    required this.gerritService,
    this.retryOptions = const RetryOptions(),
  });

  final Config config;
  final GerritService gerritService;
  final RetryOptions retryOptions;

  /// Add a [CreateEvent] branch to Datastore.
  Future<void> handleCreateRequest(CreateEvent createEvent) async {
    log.info('the branch parsed from string request is ${createEvent.ref}');

    final String? refType = createEvent.refType;
    if (refType == 'tag') {
      log.info('create branch event was rejected because it is a tag');
      return;
    }
    final String? branch = createEvent.ref;
    if (branch == null) {
      log.warning('Branch is null, exiting early');
      return;
    }
    final String repository = createEvent.repository!.slug().fullName;
    final int lastActivity = createEvent.repository!.pushedAt!.millisecondsSinceEpoch;
    final bool forked = createEvent.repository!.isFork;

    if (forked) {
      log.info('create branch event was rejected because the branch is a fork');
      return;
    }

    final String id = '$repository/$branch';
    log.info('the id used to create branch key was $id');
    final DatastoreService datastore = DatastoreService.defaultProvider(config.db);
    final Key<String> key = datastore.db.emptyKey.append<String>(Branch, id: id);
    final Branch currentBranch = Branch(key: key, lastActivity: lastActivity);
    try {
      await datastore.lookupByValue<Branch>(currentBranch.key);
    } on KeyNotFoundException {
      log.info('create branch event was successful since the key is unique');
      await datastore.insert(<Branch>[currentBranch]);
    } catch (e) {
      log.severe('Unexpected exception was encountered while inserting branch into database: $e');
    }
  }

  /// Creates a flutter/recipes branch that aligns to a flutter/flutter branch.
  ///
  /// Take the example repo history:
  ///   flutter/flutter: A -> B -> C -> D -> E
  ///   flutter/recipes: V -> W -> X -> Y -> Z
  ///
  /// If flutter/flutter branches at C, this finds the flutter/recipes commit that should be used for C.
  /// The best guess for a flutter/recipes commit that aligns with C is whatever was the most recently committed
  /// before C was committed.
  ///
  /// Once the flutter/recipes commit is found, it is branched to match flutter/flutter.
  ///
  /// Generally, this should work. However, some edge cases may require CPs. Such as when commits land in a
  /// short timespan, and require the release manager to CP onto the recipes branch (in the case of reverts).
  Future<void> branchFlutterRecipes(String branch) async {
    final gh.RepositorySlug recipesSlug = gh.RepositorySlug('flutter', 'recipes');
    if ((await gerritService.branches('${recipesSlug.owner}-review.googlesource.com', recipesSlug.name,
            filterRegex: branch))
        .contains(branch)) {
      // subString is a regex, and can return multiple matches
      log.warning('$branch already exists for $recipesSlug');
      throw BadRequestException('$branch already exists');
    }
    final Iterable<GerritCommit> recipeCommits =
        await gerritService.commits(recipesSlug, Config.defaultBranch(recipesSlug));
    log.info('$recipesSlug commits: $recipeCommits');
    final GithubService githubService = await config.createDefaultGitHubService();
    final List<gh.RepositoryCommit> githubCommits = await retryOptions.retry(
      () async => await githubService.listCommits(Config.flutterSlug, branch, null),
      retryIf: (Exception e) => e is gh.GitHubError,
    );
    log.info('${Config.flutterSlug} branch commits: $githubCommits');
    for (GerritCommit recipeCommit in recipeCommits) {
      if (recipeCommit.author!.time!.isBefore(githubCommits.first.commit!.committer!.date!)) {
        final String revision = recipeCommit.commit!;
        return await gerritService.createBranch(recipesSlug, branch, revision);
      }
    }

    throw InternalServerError('Failed to find a revision to branch Flutter recipes for $branch');
  }

  /// Returns a Map that contains the latest google3 roll, beta, and stable branches.
  ///
  /// Latest beta and stable branches are retrieved based on 'beta' and 'stable' tags. Dev branch is retrived
  /// as the latest flutter candidate branch.
  Future<List<Map<String, String>>> getReleaseBranches(
      {required gh.GitHub github, required gh.RepositorySlug slug}) async {
    final String betaSha = (await github.repositories.getBranch(slug, 'beta')).commit!.sha!;
    final String stableSha = (await github.repositories.getBranch(slug, 'stable')).commit!.sha!;

    List<gh.Branch> branches = await github.repositories.listBranches(slug).toList();
    final String devName = await _getDevBranch(github: github, slug: slug, branches: branches);
    final String betaName = branches.where(((gh.Branch b) => b.commit!.sha == betaSha)).single.name!;
    final String stableName = branches.where(((gh.Branch b) => b.commit!.sha == stableSha)).single.name!;

    return <Map<String, String>>[
      {"branch": stableName, "name": "stable"},
      {"branch": betaName, "name": "beta"},
      {"branch": devName, "name": "dev"}
    ];
  }

  /// Retrieve the latest canidate branch from all candidate branches.
  Future<String> _getDevBranch({
    required gh.GitHub github,
    required gh.RepositorySlug slug,
    required List<gh.Branch> branches,
  }) async {
    final RegExp candidateBranchName = RegExp(r'flutter-\d+\.\d+-candidate\.\d+');
    List<gh.Branch> devBranches = branches.where((gh.Branch b) => candidateBranchName.hasMatch(b.name!)).toList();
    devBranches.sort((b, a) => (_versionSum(a.name!)).compareTo(_versionSum(b.name!)));
    String devBranchName = devBranches.take(1).single.name!;
    return devBranchName;
  }

  /// Helper function to convert candidate branch versions to numbers for comparison.
  int _versionSum(String tagOrBranchName) {
    List<String> digits = tagOrBranchName.replaceAll(r'flutter|candidate', '0').split(RegExp(r'\.|\-'));
    int versionSum = 0;
    for (String digit in digits) {
      int? d = int.tryParse(digit);
      if (d == null) {
        continue;
      }
      versionSum = versionSum * 100 + d;
    }
    return versionSum;
  }
}
