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

import 'package:cocoon_service/cocoon_service.dart';
import 'package:cocoon_service/src/model/ci_yaml/ci_yaml.dart';
import 'package:cocoon_service/src/model/proto/internal/scheduler.pbserver.dart' as pb;
import 'package:github/github.dart';
import 'package:http/http.dart' as http;
import 'package:process/process.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';

import 'common.dart';

/// List of repositories that have supported .ci.yaml config files.
final List<SupportedConfig> configs = <SupportedConfig>[
  SupportedConfig(RepositorySlug('flutter', 'cocoon'), 'main'),
  SupportedConfig(RepositorySlug('flutter', 'engine'), 'main'),
  SupportedConfig(RepositorySlug('flutter', 'flutter')),
  SupportedConfig(RepositorySlug('flutter', 'packages'), 'main'),
  SupportedConfig(RepositorySlug('flutter', 'plugins'), 'main'),
];

Future<void> main() async {
  for (final SupportedConfig config in configs) {
    test('validate config file of $config', () async {
      final String configContent = await githubFileContent(
        config.slug,
        kCiYamlPath,
        httpClientProvider: () => http.Client(),
        ref: config.branch,
      );
      final YamlMap configYaml = loadYaml(configContent) as YamlMap;
      final pb.SchedulerConfig currentSchedulerConfig = pb.SchedulerConfig()..mergeFromProto3Json(configYaml);
      try {
        CiYaml(
          slug: config.slug,
          branch: Config.defaultBranch(config.slug),
          config: currentSchedulerConfig,
        );
      } on FormatException catch (e) {
        fail(e.message);
      }
    });

    test('validate enabled branches of $config', () async {
      final String configContent = await githubFileContent(
        config.slug,
        kCiYamlPath,
        httpClientProvider: () => http.Client(),
        ref: config.branch,
      );
      final YamlMap configYaml = loadYaml(configContent) as YamlMap;
      final pb.SchedulerConfig schedulerConfig = pb.SchedulerConfig()..mergeFromProto3Json(configYaml);

      final List<String> githubBranches = getBranchesForRepository(config.slug);

      final Map<String, bool> validEnabledBranches = <String, bool>{};
      // Add config wide enabled branches
      for (String enabledBranch in schedulerConfig.enabledBranches) {
        validEnabledBranches[enabledBranch] = false;
      }
      // Add all target specific enabled branches
      for (pb.Target target in schedulerConfig.targets) {
        for (String enabledBranch in target.enabledBranches) {
          validEnabledBranches[enabledBranch] = false;
        }
      }

      // N^2 scan to verify all enabled branch patterns match an exist branch on the repo.
      for (String enabledBranch in validEnabledBranches.keys) {
        for (String githubBranch in githubBranches) {
          if (CiYaml.enabledBranchesMatchesCurrentBranch(<String>[enabledBranch], githubBranch)) {
            validEnabledBranches[enabledBranch] = true;
          }
        }
      }

      if (config.slug.name == 'engine') {
        print(githubBranches);
        print(validEnabledBranches);
      }

      // Verify the enabled branches
      for (String enabledBranch in validEnabledBranches.keys) {
        expect(validEnabledBranches[enabledBranch], isTrue,
            reason: '$enabledBranch does not match to a branch in ${config.slug.fullName}');
      }
    }, skip: config.slug.name == 'flutter');
  }
}

/// Gets all branches for [slug].
///
/// Internally, uses the git on path to get the branches from the remote for [slug].
List<String> getBranchesForRepository(RepositorySlug slug) {
  const ProcessManager processManager = LocalProcessManager();
  final ProcessResult result =
      processManager.runSync(<String>['git', 'ls-remote', '--head', 'https://github.com/${slug.fullName}']);
  final List<String> lines = (result.stdout as String).split('\n');

  final List<String> githubBranches = <String>[];
  for (String line in lines) {
    if (line.isEmpty) {
      continue;
    }
    // Lines follow the format of `$sha\t$ref`
    final String ref = line.split('\t')[1];
    final String branch = ref.replaceAll('refs/heads/', '');
    githubBranches.add(branch);
  }

  return githubBranches;
}
