// 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 GithubService githubService,
    required gh.RepositorySlug slug,
  }) async {
    List<gh.Branch> branches = await githubService.github.repositories.listBranches(slug).toList();
    final String latestCandidateBranch = await _getLatestCandidateBranch(
      github: githubService.github,
      slug: slug,
      branches: branches,
    );

    final String betaName = await _getBranchNameFromFile(
      githubService: githubService,
      slug: slug,
      branchName: "beta",
    );
    final String stableName = await _getBranchNameFromFile(
      githubService: githubService,
      slug: slug,
      branchName: "stable",
    );
    return <Map<String, String>>[
      {
        "branch": stableName,
        "name": "stable",
      },
      {
        "branch": betaName,
        "name": "beta",
      },
      {
        "branch": latestCandidateBranch,
        "name": "latestCandidateBranch",
      }
    ];
  }

  Future<String> _getBranchNameFromFile({
    required GithubService githubService,
    required gh.RepositorySlug slug,
    required String branchName,
  }) async {
    return (await githubService.getFileContent(
      slug,
      'bin/internal/release-candidate-branch.version',
      ref: branchName,
    ))
        .trim();
  }

  /// Retrieve the latest canidate branch from all candidate branches.
  Future<String> _getLatestCandidateBranch({
    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;
  }
}
