// Copyright 2019 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:buildbucket/buildbucket_pb.dart' as bbv2;
import 'package:cocoon_service/src/model/luci/user_data.dart';
import 'package:cocoon_service/src/request_handling/subscription_handler_v2.dart';
import 'package:cocoon_service/src/service/github_checks_service_v2.dart';
import 'package:cocoon_service/src/service/luci_build_service_v2.dart';
import 'package:cocoon_service/src/service/scheduler_v2.dart';
import 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../model/appengine/commit.dart';
import '../model/ci_yaml/ci_yaml.dart';
import '../model/ci_yaml/target.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../service/config.dart';
import '../service/logging.dart';

/// An endpoint for listening to LUCI status updates for scheduled builds.
///
/// [ScheduleBuildRequest.notify] property is set to tell LUCI to use this
/// PubSub topic. LUCI then publishes updates about build status to that topic,
/// which we listen to on the github-updater subscription. When new messages
/// arrive, they are posted to this web service.
///
/// The PubSub subscription is set up here:
/// https://console.cloud.google.com/cloudpubsub/subscription/detail/build-bucket-presubmit-sub?project=flutter-dashboard
///
/// This endpoint is responsible for updating GitHub with the status of
/// completed builds from LUCI.
@immutable
class PresubmitLuciSubscriptionV2 extends SubscriptionHandlerV2 {
  /// Creates an endpoint for listening to LUCI status updates.
  const PresubmitLuciSubscriptionV2({
    required super.cache,
    required super.config,
    required this.scheduler,
    required this.luciBuildService,
    required this.githubChecksService,
    AuthenticationProvider? authProvider,
  }) : super(subscriptionName: 'build-bucket-presubmit-sub');

  final LuciBuildServiceV2 luciBuildService;
  final GithubChecksServiceV2 githubChecksService;
  final SchedulerV2 scheduler;

  @override
  Future<Body> post() async {
    if (message.data == null) {
      log.info('no data in message');
      return Body.empty;
    }

    final bbv2.PubSubCallBack pubSubCallBack = bbv2.PubSubCallBack();
    pubSubCallBack.mergeFromProto3Json(jsonDecode(message.data!) as Map<String, dynamic>);

    final bbv2.BuildsV2PubSub buildsV2PubSub = pubSubCallBack.buildPubsub;

    if (!buildsV2PubSub.hasBuild()) {
      log.info('no build information in message');
      return Body.empty;
    }

    final bbv2.Build build = buildsV2PubSub.build;

    final String builderName = build.builder.builder;

    final List<bbv2.StringPair> tags = build.tags;

    log.fine('Available tags: ${tags.toString()}');

    // Skip status update if we can not get the sha tag.
    if (tags.where((element) => element.key == 'buildset').isEmpty) {
      log.warning('Buildset tag not included, skipping Status Updates');
      return Body.empty;
    }

    log.fine('Setting status (${build.status.toString()}) for $builderName');

    if (!pubSubCallBack.hasUserData()) {
      log.info('No user data was found in this request');
      return Body.empty;
    }

    Map<String, dynamic> userDataMap = <String, dynamic>{};
    try {
      userDataMap = json.decode(String.fromCharCodes(pubSubCallBack.userData));
      log.info('User data was not base64 encoded.');
    } on FormatException {
      userDataMap = UserData.decodeUserDataBytes(pubSubCallBack.userData);
      log.info('Decoding base64 encoded user data.');
    }

    if (userDataMap.containsKey('repo_owner') && userDataMap.containsKey('repo_name')) {
      final RepositorySlug slug =
          RepositorySlug(userDataMap['repo_owner'] as String, userDataMap['repo_name'] as String);

      bool rescheduled = false;
      if (githubChecksService.taskFailed(build.status)) {
        final int currentAttempt = githubChecksService.currentAttempt(tags);
        final int maxAttempt = await _getMaxAttemptV2(
          userDataMap,
          slug,
          builderName,
        );
        if (currentAttempt < maxAttempt) {
          rescheduled = true;
          log.fine('Rerunning failed task: $builderName');
          await luciBuildService.rescheduleBuild(
            builderName: builderName,
            build: build,
            rescheduleAttempt: currentAttempt + 1,
            userDataMap: userDataMap,
          );
        }
      }
      await githubChecksService.updateCheckStatus(
        build: build,
        userDataMap: userDataMap,
        luciBuildService: luciBuildService,
        slug: slug,
        rescheduled: rescheduled,
      );
    } else {
      log.info('This repo does not support checks API');
    }
    return Body.empty;
  }

  Future<int> _getMaxAttemptV2(
    Map<String, dynamic> userData,
    RepositorySlug slug,
    String builderName,
  ) async {
    final Commit commit = Commit(
      branch: userData['commit_branch'] as String,
      repository: slug.fullName,
      sha: userData['commit_sha'] as String,
    );
    late CiYaml ciYaml;
    if (commit.branch == Config.defaultBranch(commit.slug)) {
      ciYaml = await scheduler.getCiYaml(commit, validate: true);
    } else {
      ciYaml = await scheduler.getCiYaml(commit);
    }

    // Do not block on the target not found.
    if (!ciYaml.presubmitTargets.any((element) => element.value.name == builderName)) {
      // do not reschedule
      log.warning('Did not find builder with name: $builderName in ciYaml for ${commit.sha}');
      final List<String> availableBuilderList = ciYaml.presubmitTargets.map((Target e) => e.value.name).toList();
      log.warning('ciYaml presubmit targets found: $availableBuilderList');
      return 1;
    }

    final Target target = ciYaml.presubmitTargets.where((element) => element.value.name == builderName).single;
    final Map<String, Object> properties = target.getProperties();
    if (!properties.containsKey('presubmit_max_attempts')) {
      return 1;
    }
    return properties['presubmit_max_attempts'] as int;
  }
}
