// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// auto-submit applies the 'Commit-Queue+2' label to Gerrit changes authored by the user
// that are ready to be submitted
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"

	"dawn.googlesource.com/dawn/tools/src/auth"
	"dawn.googlesource.com/dawn/tools/src/dawn"
	"dawn.googlesource.com/dawn/tools/src/gerrit"
	"dawn.googlesource.com/dawn/tools/src/git"
	"go.chromium.org/luci/auth/client/authcli"
)

const (
	toolName       = "auto-submit"
	cqEmailAccount = "dawn-scoped@luci-project-accounts.iam.gserviceaccount.com"
)

var (
	repoFlag    = flag.String("repo", "dawn", "the repo")
	userFlag    = flag.String("user", defaultUser(), "user name / email")
	verboseFlag = flag.Bool("v", false, "verbose mode")
	dryrunFlag  = flag.Bool("dry", false, "dry mode. Don't apply any labels")
	authFlags   = authcli.Flags{}
)

func defaultUser() string {
	if gitExe, err := exec.LookPath("git"); err == nil {
		if g, err := git.New(gitExe); err == nil {
			if cwd, err := os.Getwd(); err == nil {
				if r, err := g.Open(cwd); err == nil {
					if cfg, err := r.Config(nil); err == nil {
						return cfg["user.email"]
					}
				}
			}
		}
	}
	return ""
}

func main() {
	authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())

	flag.Usage = func() {
		out := flag.CommandLine.Output()
		fmt.Fprintf(out,
			`%v applies the 'Commit-Queue+2' label to Gerrit changes authored by the user that are ready to be submitted.

The tool monitors Gerrit changes authored by the user, looking for changes that have the labels
'Kokoro+1', 'Auto-Submit +1' and 'Code-Review +2' and applies the 'Commit-Queue +2' label.
`, toolName)
		fmt.Fprintf(out, "\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	if err := run(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	user := *userFlag
	if user == "" {
		return fmt.Errorf("Missing required 'user' flag")
	}

	ctx := context.Background()
	auth, err := authFlags.Options()
	if err != nil {
		return err
	}

	g, err := gerrit.New(ctx, auth, dawn.GerritURL)
	if err != nil {
		return err
	}

	app := app{Gerrit: g, user: user}

	log.Println("Monitoring for changes ready to be submitted...")

	for {
		err := app.submitReadyChanges()
		if err != nil {
			fmt.Println("error: ", err)
			time.Sleep(time.Minute * 10)
		}
		time.Sleep(time.Minute * 5)
	}
}

type app struct {
	*gerrit.Gerrit
	user string // User account of changes to submit
}

func (a *app) submitReadyChanges() error {
	if *verboseFlag {
		log.Println("Scanning for changes to submit...")
	}

	changes, _, err := a.QueryChangesWith(
		gerrit.QueryExtraData{
			Labels:           true,
			Messages:         true,
			CurrentRevision:  true,
			DetailedAccounts: true,
			Submittable:      true,
		},
		"status:open",
		"author:"+a.user,
		"-is:wip",
		"label:auto-submit",
		"label:kokoro",
		"repo:"+*repoFlag)
	if err != nil {
		return fmt.Errorf("failed to query changes: %w", err)
	}

	for _, change := range changes {
		// Returns true if the change has the label with the given value
		hasLabel := func(name string, value int) bool {
			if label, ok := change.Labels[name]; ok {
				for _, vote := range label.All {
					if vote.Value == value {
						return true
					}
				}
			}
			return false
		}

		isReadyToSubmit := true &&
			change.Submittable &&
			hasLabel("Kokoro", 1) &&
			hasLabel("Auto-Submit", 1) &&
			hasLabel("Code-Review", 2) &&
			!hasLabel("Code-Review", -1) &&
			!hasLabel("Code-Review", -2)
		if !isReadyToSubmit {
			// Change is not ready to be submitted
			continue
		}

		if hasLabel("Commit-Queue", 2) {
			// Change already in the process of submitting
			continue
		}

		submittedTogether, err := a.ChangesSubmittedTogether(change.ChangeID)
		if err != nil {
			return fmt.Errorf("failed to query changes submitted together: %w", err)
		}
		if len(submittedTogether) > 1 { // Include the change itself
			// Change has unsubmitted parents
			if *verboseFlag {
				log.Printf("%v has %v unsubmitted parents", change.ChangeID, len(submittedTogether)-1)
			}
			continue
		}

		switch parseCQStatus(change) {
		case cqUnknown, cqPassed:
			if *dryrunFlag {
				log.Printf("Would submit %v: %v... (--dry)\n", change.ChangeID, change.Subject)
				continue
			}

			log.Printf("Submitting %v: %v...\n", change.ChangeID, change.Subject)
			err := a.AddLabel(change.ChangeID, change.CurrentRevision, "Auto submitting change", "Commit-Queue", 2)
			if err != nil {
				return fmt.Errorf("failed to set Commit-Queue label: %w", err)
			}

		case cqFailed:
			if *verboseFlag {
				log.Printf("Change failed CQ: %v: %v...\n", change.ChangeID, change.Subject)
			}
		}
	}

	return nil
}

// CQ result status enumerator
type cqStatus int

// CQ result status enumerator values
const (
	cqUnknown cqStatus = iota
	cqPassed
	cqFailed
)

// Attempt to parse the CQ result from the latest patchset's messages from CQ
func parseCQStatus(change gerrit.ChangeInfo) cqStatus {
	currentPatchset := change.Revisions[change.CurrentRevision].Number
	for _, msg := range change.Messages {
		if msg.RevisionNumber != currentPatchset {
			continue
		}
		if msg.Author.Email == cqEmailAccount {
			if strings.Contains(msg.Message, "This CL has failed the run") {
				return cqFailed
			}
			if strings.Contains(msg.Message, "This CL has passed the run") {
				return cqPassed
			}
		}
	}
	return cqUnknown
}
