// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"hash"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"cloud.google.com/go/compute/metadata"
	"golang.org/x/build/cmd/pubsubhelper/pubsubtypes"
)

func handleGithubWebhook(w http.ResponseWriter, r *http.Request) {
	if r.TLS == nil {
		http.Error(w, "HTTPS required", http.StatusBadRequest)
		return
	}
	body, err := validateGithubRequest(w, r)
	if err != nil {
		log.Printf("failed to validate github webhook request: %v", err)
		// But send a 200 OK anyway, so they don't queue up on
		// Github's side if they're real.
		return
	}

	var payload githubWebhookPayload
	if err := json.Unmarshal(body, &payload); err != nil {
		log.Printf("error unmarshalling payload: %v; payload=%s", err, body)
		// But send a 200 OK anyway. Our fault.
		return
	}
	back, _ := json.MarshalIndent(payload, "", "\t")
	log.Printf("github verified webhook: %s", back)

	if payload.Repository == nil || payload.Issue == nil {
		// Ignore.
		return
	}

	f := strings.Split(payload.Repository.FullName, "/")
	if len(f) != 2 {
		log.Printf("bogus repository name %q", payload.Repository.FullName)
		return
	}
	owner, repo := f[0], f[1]

	publish(&pubsubtypes.Event{
		GitHub: &pubsubtypes.GitHubEvent{
			Action:      payload.Action,
			RepoOwner:   owner,
			Repo:        repo,
			IssueNumber: payload.Issue.Number,
		},
	})

}

// validate compares the signature in the request header with the body.
func validateGithubRequest(w http.ResponseWriter, r *http.Request) (body []byte, err error) {
	// Decode signature header.
	sigHeader := r.Header.Get("X-Hub-Signature")
	sigParts := strings.SplitN(sigHeader, "=", 2)
	if len(sigParts) != 2 {
		return nil, fmt.Errorf("Bad signature header: %q", sigHeader)
	}
	var h func() hash.Hash
	switch alg := sigParts[0]; alg {
	case "sha1":
		h = sha1.New
	case "sha256":
		h = sha256.New
	default:
		return nil, fmt.Errorf("Unsupported hash algorithm: %q", alg)
	}
	gotSig, err := hex.DecodeString(sigParts[1])
	if err != nil {
		return nil, err
	}

	// Compute expected signature.
	key, err := metadata.ProjectAttributeValue("pubsubhelper-webhook-secret")
	if err != nil {
		return nil, err
	}
	body, err = ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 5<<20))
	if err != nil {
		return nil, err
	}
	mac := hmac.New(h, []byte(key))
	mac.Write(body)
	expectSig := mac.Sum(nil)

	if !hmac.Equal(gotSig, expectSig) {
		return nil, fmt.Errorf("Invalid signature %X, want %x", gotSig, expectSig)
	}
	return body, nil
}

type githubWebhookPayload struct {
	Action     string            `json:"action"`
	Repository *githubRepository `json:"repository"`
	Issue      *githubIssue      `json:"issue"`
}

type githubRepository struct {
	FullName string `json:"full_name"` // "golang/go"
}

type githubIssue struct {
	URL    string `json:"url"`    // https://api.github.com/repos/baxterthehacker/public-repo/issues/2
	Number int    `json:"number"` // 2
}
