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

import 'package:cocoon_server/logging.dart';
import 'package:crypto/crypto.dart';
import 'package:github/github.dart';
import 'package:shelf/shelf.dart';

import '../request_handling/pubsub.dart';
import '../requests/exceptions.dart';
import '../server/request_handler.dart';
import '../service/config.dart';
import 'github_pull_request_event.dart';

/// Handler for processing GitHub webhooks.
///
/// On events where an 'autosubmit' label was added to a pull request,
/// check if the pull request is mergable and publish to pubsub.
class GithubWebhook extends RequestHandler {
  const GithubWebhook({required super.config, this.pubsub = const PubSub()});

  final PubSub pubsub;

  static const String pullRequest = 'pull_request';
  static const String labels = 'labels';
  static const String action = 'action';
  static const String sender = 'sender';

  static const String eventTypeHeader = 'X-GitHub-Event';
  static const String signatureHeader = 'X-Hub-Signature';

  @override
  Future<Response> post(Request request) async {
    final reqHeader = request.headers;
    log.info('Header: $reqHeader');

    final gitHubEvent = request.headers[GithubWebhook.eventTypeHeader];

    if (gitHubEvent == null ||
        request.headers[GithubWebhook.signatureHeader] == null) {
      throw const BadRequestException('Missing required headers.');
    }
    final requestBytes = await request
        .read()
        .expand((bodyBytes) => bodyBytes)
        .toList();
    final hmacSignature = request.headers[GithubWebhook.signatureHeader];
    if (!await _validateRequest(hmacSignature, requestBytes)) {
      log.info('User is forbidden');
      throw const Forbidden();
    }

    var hasAutosubmit = false;
    var hasRevertLabel = false;
    final rawBody = utf8.decode(requestBytes);
    final body = json.decode(rawBody) as Map<String, dynamic>;

    if (!body.containsKey(GithubWebhook.pullRequest) ||
        !(body[GithubWebhook.pullRequest] as Map<String, dynamic>).containsKey(
          GithubWebhook.labels,
        )) {
      return Response.ok(jsonEncode(<String, String>{}));
    }

    final pullRequest = PullRequest.fromJson(
      body[GithubWebhook.pullRequest] as Map<String, dynamic>,
    );
    final action = body[GithubWebhook.action] as String;
    final sender = User.fromJson(
      body[GithubWebhook.sender] as Map<String, dynamic>,
    );

    hasAutosubmit = pullRequest.labels!.any(
      (label) => label.name == Config.kAutosubmitLabel,
    );
    hasRevertLabel = pullRequest.labels!.any(
      (label) =>
          label.name == Config.kRevertLabel ||
          label.name == Config.kRevertOfLabel,
    );

    // Check for revert label first.
    if (hasRevertLabel) {
      log.info('Found pull request with the revert label.');
      await pubsub.publish(
        config.pubsubRevertRequestTopic,
        GithubPullRequestEvent(
          pullRequest: pullRequest,
          action: action,
          sender: sender,
        ),
      );
    } else if (hasAutosubmit) {
      log.info('Found pull request with autosubmit label.');
      await pubsub.publish(config.pubsubPullRequestTopic, pullRequest);
    }

    return Response.ok(rawBody);
  }

  Future<bool> _validateRequest(
    String? signature,
    List<int> requestBody,
  ) async {
    final rawKey = await config.getWebhookKey();
    final List<int> key = utf8.encode(rawKey);
    final hmac = Hmac(sha1, key);
    final digest = hmac.convert(requestBody);
    final bodySignature = 'sha1=$digest';
    return bodySignature == signature;
  }
}
