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

import 'package:cocoon_service/cocoon_service.dart';
import 'package:github/github.dart';

import '../proto/internal/scheduler.pb.dart' as pb;
import 'target.dart';

/// This is a wrapper class around S[pb.SchedulerConfig].
///
/// See //CI_YAML.md for high level documentation.
class CiYaml {
  /// Creates [CiYaml] from a [RepositorySlug], [branch], [pb.SchedulerConfig] and an optional [CiYaml] of tip of tree CiYaml.
  ///
  /// If [totConfig] is passed, the validation will verify no new targets have been added that may temporarily break the LUCI infrastructure (such as new prod or presubmit targets).
  CiYaml({
    required this.slug,
    required this.branch,
    required this.config,
    CiYaml? totConfig,
  }) {
    _validate(config, branch, totSchedulerConfig: totConfig?.config);
  }

  /// The underlying protobuf that contains the raw data from .ci.yaml.
  pb.SchedulerConfig config;

  /// The [RepositorySlug] that [config] is from.
  final RepositorySlug slug;

  /// The git branch currently being scheduled against.
  final String branch;

  /// Gets all [Target] that run on presubmit for this config.
  List<Target> get presubmitTargets {
    final Iterable<Target> presubmitTargets =
        _targets.where((Target target) => target.value.presubmit && !target.value.bringup);

    final List<Target> enabledTargets = _filterEnabledTargets(presubmitTargets);
    if (enabledTargets.isEmpty) {
      throw Exception('$branch is not enabled for this .ci.yaml.\nAdd it to run tests against this PR.');
    }
    return enabledTargets;
  }

  /// Gets all [Target] that run on postsubmit for this config.
  List<Target> get postsubmitTargets {
    final Iterable<Target> postsubmitTargets = _targets.where((Target target) => target.value.postsubmit);

    return _filterEnabledTargets(postsubmitTargets);
  }

  /// Filters [targets] to those that should be started immediately.
  ///
  /// Targets with a dependency are triggered when there dependency pushes a notification that it has finished.
  /// This shouldn't be confused for targets that have the property named dependency, which is used by the
  /// flutter_deps recipe module on LUCI.
  List<Target> getInitialTargets(List<Target> targets) {
    Iterable<Target> initialTargets = targets.where((Target target) => target.value.dependencies.isEmpty).toList();
    if (branch != Config.defaultBranch(slug)) {
      // Filter out bringup targets for release branches
      initialTargets = initialTargets.where((Target target) => !target.value.bringup);
    }

    return initialTargets.toList();
  }

  Iterable<Target> get _targets => config.targets.map((pb.Target target) => Target(
        schedulerConfig: config,
        value: target,
        slug: slug,
      ));

  /// Filter [targets] to only those that are expected to run for [branch].
  ///
  /// A [Target] is expected to run if:
  ///   1. [Target.enabledBranches] exists and matches [branch].
  ///   2. Otherwise, [config.enabledBranches] matches [branch].
  List<Target> _filterEnabledTargets(Iterable<Target> targets) {
    final List<Target> filteredTargets = <Target>[];

    // 1. Add targets with local definition
    final Iterable<Target> overrideBranchTargets =
        targets.where((Target target) => target.value.enabledBranches.isNotEmpty);
    final Iterable<Target> enabledTargets = overrideBranchTargets
        .where((Target target) => enabledBranchesMatchesCurrentBranch(target.value.enabledBranches, branch));
    filteredTargets.addAll(enabledTargets);

    // 2. Add targets with global definition (this is the majority of targets)
    if (enabledBranchesMatchesCurrentBranch(config.enabledBranches, branch)) {
      final Iterable<Target> defaultBranchTargets =
          targets.where((Target target) => target.value.enabledBranches.isEmpty);
      filteredTargets.addAll(defaultBranchTargets);
    }

    return filteredTargets;
  }

  /// Whether any of the possible [RegExp] in [enabledBranches] match [branch].
  static bool enabledBranchesMatchesCurrentBranch(List<String> enabledBranches, String branch) {
    final List<String> regexes = <String>[];
    for (String enabledBranch in enabledBranches) {
      // Prefix with start of line and suffix with end of line
      regexes.add('^$enabledBranch\$');
    }
    final String rawRegexp = regexes.join('|');
    final RegExp regexp = RegExp(rawRegexp);

    return regexp.hasMatch(branch);
  }

  /// Validates [pb.SchedulerConfig] extracted from [CiYaml] files.
  ///
  /// A [pb.SchedulerConfig] file is considered good if:
  ///   1. It has at least one [pb.Target] in [pb.SchedulerConfig.targets]
  ///   2. It has at least one [branch] in [pb.SchedulerConfig.enabledBranches]
  ///   3. If a second [pb.SchedulerConfig] is passed in,
  ///   we compare the current list of [pb.Target] inside the current [pb.SchedulerConfig], i.e., [schedulerConfig],
  ///   with the list of [pb.Target] from tip of the tree [pb.SchedulerConfig], i.e., [totSchedulerConfig].
  ///   If a [pb.Target] is indentified as a new target compared to target list from tip of the tree, The new target
  ///   should have its field [pb.Target.bringup] set to true.
  ///   4. no cycle should exist in the dependency graph, as tracked by map [targetGraph]
  ///   5. [pb.Target] should not depend on self
  ///   6. [pb.Target] cannot have more than 1 dependency
  ///   7. [pb.Target] should depend on target that already exist in depedency graph, and already recorded in map [targetGraph]
  void _validate(pb.SchedulerConfig schedulerConfig, String branch, {pb.SchedulerConfig? totSchedulerConfig}) {
    if (schedulerConfig.targets.isEmpty) {
      throw const FormatException('Scheduler config must have at least 1 target');
    }

    if (schedulerConfig.enabledBranches.isEmpty) {
      throw const FormatException('Scheduler config must have at least 1 enabled branch');
    }

    final Map<String, List<pb.Target>> targetGraph = <String, List<pb.Target>>{};
    final List<String> exceptions = <String>[];
    final Set<String> totTargets = <String>{};
    if (totSchedulerConfig != null) {
      for (pb.Target target in totSchedulerConfig.targets) {
        totTargets.add(target.name);
      }
    }
    // Construct [targetGraph]. With a one scan approach, cycles in the graph
    // cannot exist as it only works forward.
    for (final pb.Target target in schedulerConfig.targets) {
      if (targetGraph.containsKey(target.name)) {
        exceptions.add('ERROR: ${target.name} already exists in graph');
      } else {
        // a new build without "bringup: true"
        // link to wiki - https://github.com/flutter/flutter/wiki/Reducing-Test-Flakiness#adding-a-new-devicelab-test
        if (totTargets.isNotEmpty && !totTargets.contains(target.name) && target.bringup != true) {
          exceptions.add(
              'ERROR: ${target.name} is a new builder added. it needs to be marked bringup: true\nIf ci.yaml wasn\'t changed, try `git fetch upstream && git merge upstream/master`');
          continue;
        }
        targetGraph[target.name] = <pb.Target>[];
        // Add edges
        if (target.dependencies.isNotEmpty) {
          if (target.dependencies.length != 1) {
            exceptions
                .add('ERROR: ${target.name} has multiple dependencies which is not supported. Use only one dependency');
          } else {
            if (target.dependencies.first == target.name) {
              exceptions.add('ERROR: ${target.name} cannot depend on itself');
            } else if (targetGraph.containsKey(target.dependencies.first)) {
              targetGraph[target.dependencies.first]!.add(target);
            } else {
              exceptions.add('ERROR: ${target.name} depends on ${target.dependencies.first} which does not exist');
            }
          }
        }
      }

      /// Check the dependencies for the current target if it is viable and to
      /// be added to graph. Temporarily this is only being done on non-release
      /// branches.
      if (branch == Config.defaultBranch(slug)) {
        final String? dependencyJson = target.properties['dependencies'];
        if (dependencyJson != null) {
          DependencyValidator.hasVersion(dependencyJsonString: dependencyJson);
        }
      }
    }
    _checkExceptions(exceptions);
  }

  void _checkExceptions(List<String> exceptions) {
    if (exceptions.isNotEmpty) {
      final String fullException = exceptions.reduce((String exception, _) => exception + '\n');
      throw FormatException(fullException);
    }
  }
}

/// Class to verify the version of the dependencies in the ci.yaml config file
/// for each target we are going to execute.
class DependencyValidator {
  /// dependencyJsonString is guaranteed to be non empty as it must be found
  /// before this method is called.
  ///
  /// Checks a dependency string for a pinned version.
  /// If a version is found then it must not be empty or 'latest.'
  static void hasVersion({required String dependencyJsonString}) {
    final List<String> exceptions = <String>[];

    /// Decoded will contain a list of maps for the dependencies found.
    List<dynamic> decoded = json.decode(dependencyJsonString) as List<dynamic>;

    for (Map<String, dynamic> depMap in decoded) {
      if (!depMap.containsKey('version')) {
        exceptions.add('ERROR: dependency ${depMap['dependency']} must have a version.');
      } else {
        String version = depMap['version'] as String;
        if (version.isEmpty || version == 'latest') {
          exceptions
              .add('ERROR: dependency ${depMap['dependency']} must have a non empty, non "latest" version supplied.');
        }
      }
    }

    if (exceptions.isNotEmpty) {
      final String fullException = exceptions.reduce((String exception, _) => exception + '\n');
      throw FormatException(fullException);
    }
  }
}
