// 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( /* needsCloudScopes */ false))

	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
}
