// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command pushback is a service that monitors a set of GitHub repositories
// for incoming Pull Requests, replies with contribution instructions, and
// closes the request. This is for projects that don't use Pull Requests.
package main

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

	"cloud.google.com/go/compute/metadata"
)

const (
	authMetadataKey   = "pushback-credentials"
	secretMetadataKey = "pushback-webhook-secret"
	pollInterval      = 30 * time.Minute
)

var repos = []string{
	"golang/arch",
	"golang/benchmarks",
	"golang/blog",
	"golang/build",
	"golang/crypto",
	"golang/debug",
	"golang/example",
	"golang/exp",
	"golang/gddo",
	"golang/go",
	"golang/gofrontend",
	"golang/image",
	"golang/mobile",
	"golang/net",
	"golang/oauth2",
	"golang/playground",
	"golang/perf",
	"golang/proposal",
	"golang/review",
	"golang/sublime-build",
	"golang/sublime-config",
	"golang/sync",
	"golang/talks",
	"golang/term",
	"golang/text",
	"golang/time",
	"golang/tools",
	"golang/tour",
}

// keepOpen represents PRs that shouldn't be automatically closed
// by pushback. These PRs are dummy PRs telling users that Only
// Gerrit CLs are accepted to increase the awareness that the Go
// projects cannot accept PRs.
var keepOpen = []struct {
	repo string
	id   int
}{
	{"golang/go", 19117},
	{"golang/oauth2", 218},
}

func main() {
	go poll()
	http.HandleFunc("/webhook", webhook)
	http.HandleFunc("/_ah/health", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "OK")
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}

const debug = false

func logErr(w io.Writer, desc string, err error) {
	log.Println(desc, err)
	if debug {
		fmt.Fprintln(w, desc, err)
	}
}

func poll() {
	ticker := time.NewTicker(pollInterval)
	for {
		for _, repo := range repos {
			if err := pollRepo(repo); err != nil {
				log.Printf("polling repo %v: %v", repo, err)
			}
		}
		<-ticker.C
	}
}

func pollRepo(repo string) error {
	v := url.Values{"q": {fmt.Sprintf("type:pr state:open repo:%v", repo)}}
	u := fmt.Sprintf("https://api.github.com/search/issues?%v", v.Encode())
	body, err := doRequest("GET", u, nil)
	if err != nil {
		return err
	}
	var results struct {
		Items []struct {
			Number int
		}
	}
	if err := json.Unmarshal(body, &results); err != nil {
		return err
	}

	for _, r := range results.Items {
		if err := closePR(repo, r.Number); err != nil {
			log.Printf("closing pr %v#%v: %v", repo, r.Number, err)
		}
	}
	return nil
}

func webhook(w http.ResponseWriter, r *http.Request) {
	if r.Header.Get("X-Github-Event") != "pull_request" {
		// Only handle pull request notifications.
		return
	}
	body, err := validate(r)
	if err != nil {
		http.Error(w, "Forbidden", http.StatusForbidden)
		logErr(w, "Error validating request:", err)
		return
	}
	var req struct {
		Action     string
		Number     int
		Repository struct {
			Full_Name string
		}
	}
	if err := json.Unmarshal(body, &req); err != nil {
		http.Error(w, "Bad request", http.StatusBadRequest)
		logErr(w, "Error decoding request:", err)
		return
	}
	if req.Action != "opened" {
		// Only handle "opened" actions.
		return
	}
	if err := closePR(req.Repository.Full_Name, req.Number); err != nil {
		http.Error(w, "Server error", http.StatusInternalServerError)
		logErr(w, "Error closing PR:", err)
		return
	}
	fmt.Fprintln(w, "OK")
}

// validate compares the signature in the request header with the body.
func validate(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(secretMetadataKey)
	if err != nil {
		return nil, err
	}
	body, err = ioutil.ReadAll(r.Body)
	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
}

// closePR posts a helpful message before closing the specified pull request.
// Placeholder PRs are skipped.
func closePR(repo string, id int) error {
	for _, ko := range keepOpen {
		if repo == ko.repo && id == ko.id {
			// This is a placeholder issue to remind people
			// that we don't use pull requests; don't close it.
			return nil
		}
	}

	// Post the comment.
	url := fmt.Sprintf("https://api.github.com/repos/%v/issues/%v/comments", repo, id)
	if _, err := doRequest("POST", url, bytes.NewReader(messageJSON)); err != nil {
		return fmt.Errorf("POST to %v: %v", url, err)
	}

	// Close the issue.
	url = fmt.Sprintf("https://api.github.com/repos/%v/pulls/%v", repo, id)
	if _, err := doRequest("PATCH", url, strings.NewReader(`{"state":"closed"}`)); err != nil {
		return fmt.Errorf("PATCH to %v: %v", url, err)
	}

	return nil
}

// doRequest makes an authenticated request to the GitHub API.
func doRequest(method, url string, body io.Reader) ([]byte, error) {
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil, err
	}

	// These values are cached, so we can fetch them every time.
	userpass, err := metadata.ProjectAttributeValue(authMetadataKey)
	if err != nil {
		return nil, err
	}
	p := strings.SplitN(userpass, ":", 2)
	if len(p) != 2 {
		return nil, errors.New("bad authentication data")
	}
	req.SetBasicAuth(p[0], p[1])

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	respBody, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, err
	}
	if resp.StatusCode/100 != 2 {
		return respBody, fmt.Errorf("Bad response: %v\nBody:\n%s", resp.Status, respBody)
	}
	return respBody, nil

}

const message = `
Hi! Thanks for the PR!

Unfortunately, the Go project doesn't use GitHub's Pull Requests,
so we can't accept your contribution this way.
We instead use a code review system called Gerrit.

The good news is, I'm here to help.

From here, you have two options:

1. Read our [Contribution Guidelines](https://golang.org/doc/contribute.html) to learn how to send a change with Gerrit.
2. Or, [create an issue](https://golang.org/issue/new) about the issue this PR addresses, so that someone else can fix it.

I'm going to close this Pull Request now.
Please don't be offended! :-)

Thanks again,

GopherBot (on behalf of the Go Team)
`

var messageJSON []byte

func init() {
	var err error
	messageJSON, err = json.Marshal(struct {
		Body string `json:"body"`
	}{message})
	if err != nil {
		panic(err)
	}
}
