/*
	Keep track of Skia rolls into Google3.

	Rolls are added/updated by POST/PUT request with webhook authentication.
*/

package main

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"sync"
	"time"

	"github.com/go-chi/chi/v5"
	"go.skia.org/infra/autoroll/go/config"
	"go.skia.org/infra/autoroll/go/modes"
	"go.skia.org/infra/autoroll/go/recent_rolls"
	"go.skia.org/infra/autoroll/go/state_machine"
	"go.skia.org/infra/autoroll/go/status"
	"go.skia.org/infra/autoroll/go/strategy"
	"go.skia.org/infra/go/autoroll"
	"go.skia.org/infra/go/cleanup"
	"go.skia.org/infra/go/gitiles"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/jsonutils"
	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/go/webhook"
)

const (
	// issueUrlBase is the base URL for issues created by the Google3
	// autoroller.
	issueUrlBase = "https://goto.google.com/skia-autoroll-cl/"
)

// AutoRoller provides a handler for adding/updating Rolls, translating them into AutoRollIssue for
// storage in RecentRolls. It also manages an AutoRollStatusCache for status handlers.
type AutoRoller struct {
	cfg         *config.Config
	recent      *recent_rolls.RecentRolls
	status      *status.Cache
	childBranch string
	childRepo   *gitiles.Repo
	mtx         sync.Mutex
	liveness    metrics2.Liveness
}

// NewAutoRoller returns a Google3 AutoRoller.
func NewAutoRoller(ctx context.Context, cfg *config.Config, client *http.Client, statusDB status.DB) (*AutoRoller, error) {
	recent, err := recent_rolls.NewRecentRolls(ctx, recent_rolls.NewDatastoreRollsDB(ctx), cfg.RollerName)
	if err != nil {
		return nil, skerr.Wrap(err)
	}
	cache, err := status.NewCache(ctx, statusDB, cfg.RollerName)
	if err != nil {
		return nil, skerr.Wrap(err)
	}
	a := &AutoRoller{
		cfg:         cfg,
		recent:      recent,
		status:      cache,
		childBranch: cfg.GetGoogle3RepoManager().ChildBranch,
		childRepo:   gitiles.NewRepo(cfg.GetGoogle3RepoManager().ChildRepo, client),
		liveness:    metrics2.NewLiveness("last_autoroll_landed"),
	}

	if err := a.UpdateStatus(ctx, "", true); err != nil {
		return nil, skerr.Wrap(err)
	}
	return a, nil
}

// Start ensures DBs are closed when ctx is canceled.
func (a *AutoRoller) Start(ctx context.Context, tickFrequency, repoFrequency time.Duration) {
	go cleanup.Repeat(repoFrequency, func(ctx context.Context) {
		util.LogErr(a.UpdateStatus(ctx, "", true))
	}, nil)
}

// AddHandlers adds the AutoRoller's HTTP handlers to the chi.Router.
func (a *AutoRoller) AddHandlers(r chi.Router) {
	r.Post("/json/roll", a.rollHandler)
	r.Put("/json/roll", a.rollHandler)
}

// UpdateStatus based on RecentRolls. errorMsg will be set unless preserveLastError is true.
func (a *AutoRoller) UpdateStatus(ctx context.Context, errorMsg string, preserveLastError bool) error {
	a.mtx.Lock()
	defer a.mtx.Unlock()

	lastStatus := a.status.Get()

	recent := a.recent.GetRecentRolls()
	numFailures := 0
	lastSuccessRev := ""
	for _, roll := range recent {
		if roll.Succeeded() {
			lastSuccessRev = roll.RollingTo
			break
		}
		if lastStatus != nil && lastStatus.LastRoll != nil && lastStatus.LastRoll.Issue == roll.Issue {
			numFailures += lastStatus.AutoRollMiniStatus.NumFailedRolls
			lastSuccessRev = lastStatus.LastRollRev
			break
		}
		if roll.Failed() {
			numFailures++
		}
	}

	commitsNotRolled := 0
	if lastSuccessRev != "" {
		headRev, err := a.childRepo.Details(ctx, a.childBranch)
		if err != nil {
			return err
		}
		revs, err := a.childRepo.LogFirstParent(ctx, lastSuccessRev, headRev.Hash)
		if err != nil {
			return err
		}
		commitsNotRolled = len(revs)
	}

	lastRoll := a.recent.LastRoll()

	if preserveLastError {
		if lastStatus != nil {
			errorMsg = lastStatus.Error
		}
	} else if errorMsg != "" {
		var lastRollIssue int64 = 0
		if lastRoll != nil {
			lastRollIssue = lastRoll.Issue
		}
		sklog.Warningf("Last roll %d; errorMsg: %s", lastRollIssue, errorMsg)
	}

	currentRollRev := ""
	currentRoll := a.recent.CurrentRoll()
	if currentRoll != nil {
		currentRollRev = currentRoll.RollingTo
	}
	newStatus := &status.AutoRollStatus{
		AutoRollMiniStatus: status.AutoRollMiniStatus{
			CurrentRollRev:      currentRollRev,
			LastRollRev:         lastSuccessRev,
			Mode:                modes.ModeRunning,
			NumFailedRolls:      numFailures,
			NumNotRolledCommits: commitsNotRolled,
		},
		ChildName:       a.cfg.ChildDisplayName,
		CurrentRoll:     a.recent.CurrentRoll(),
		Error:           errorMsg,
		FullHistoryUrl:  "https://goto.google.com/skia-autoroll-history",
		IssueUrlBase:    issueUrlBase,
		LastRoll:        lastRoll,
		ParentName:      a.cfg.ParentDisplayName,
		Recent:          recent,
		Status:          state_machine.S_NORMAL_ACTIVE,
		ValidModes:      []string{modes.ModeRunning},
		ValidStrategies: []string{strategy.ROLL_STRATEGY_BATCH},
	}
	sklog.Infof("Updating status: %+v", newStatus)
	if err := a.status.Set(ctx, a.cfg.RollerName, newStatus); err != nil {
		return err
	}
	if lastRoll != nil && util.In(lastRoll.Result, []string{autoroll.ROLL_RESULT_DRY_RUN_SUCCESS, autoroll.ROLL_RESULT_SUCCESS}) {
		a.liveness.ManualReset(lastRoll.Modified)
	}
	return a.status.Update(ctx)
}

// AddOrUpdateIssue makes issue the current issue, handling any possible discrepancies due to
// missing previous requests. On error, returns an error safe for HTTP response.
func (a *AutoRoller) AddOrUpdateIssue(ctx context.Context, issue *autoroll.AutoRollIssue, method string) error {
	current := a.recent.CurrentRoll()

	// If we don't get an update to close the previous roll, close it automatically to avoid the error
	// "There is already an active roll. Cannot add another."
	if current != nil && current.Issue != issue.Issue {
		sklog.Warningf("Missing update to close %d. Closing automatically as failed.", current.Issue)
		current.Closed = true
		current.Result = autoroll.ROLL_RESULT_FAILURE
		if err := a.recent.Update(ctx, current); err != nil {
			sklog.Errorf("Failed to close current roll: %s", err)
			return errors.New("Failed to close current roll.")
		}
		current = nil
	}

	// If we don't see a roll until it's already closed, add it first to avoid the error "Cannot
	// insert a new roll which is already closed."
	if method == http.MethodPut && current == nil && issue.Closed {
		sklog.Warningf("Missing request to add %d before update marking closed. Automatically adding as in-progress.", issue.Issue)
		addIssue := new(autoroll.AutoRollIssue)
		*addIssue = *issue
		addIssue.Closed = false
		addIssue.Committed = false
		addIssue.Result = autoroll.ROLL_RESULT_IN_PROGRESS
		if err := a.recent.Add(ctx, addIssue); err != nil {
			sklog.Errorf("Failed to automatically add roll: %s", err)
			return errors.New("Failed to automatically add roll.")
		}
		current = a.recent.CurrentRoll()
	}

	if current == nil {
		if method != http.MethodPost {
			sklog.Warningf("Got %s instead of POST to add %d.", method, issue.Issue)
		}
		if err := a.recent.Add(ctx, issue); err != nil {
			sklog.Errorf("Failed to add roll: %s", err)
			return errors.New("Failed to add roll.")
		}
	} else {
		if method != http.MethodPut {
			sklog.Warningf("Got %s instead of PUT to update %d.", method, issue.Issue)
		}
		if err := a.recent.Update(ctx, issue); err != nil {
			sklog.Errorf("Failed to update roll: %s", err)
			return errors.New("Failed to update roll.")
		}
	}
	return nil
}

// Roll represents a Google3 AutoRoll attempt.
type Roll struct {
	ChangeListNumber jsonutils.Number `json:"changeListNumber"`
	CheckResults     []*CheckResult   `json:"checkResults"`
	// Closed indicates that the autoroller is finished with this CL. It does not correspond to any
	// property of the CL.
	Closed      bool           `json:"closed"`
	Created     jsonutils.Time `json:"created"`
	ErrorMsg    string         `json:"errorMsg"`
	Modified    jsonutils.Time `json:"modified"`
	Result      string         `json:"result"`
	RollingFrom string         `json:"rollingFrom"`
	RollingTo   string         `json:"rollingTo"`
	Subject     string         `json:"subject"`
	Submitted   bool           `json:"submitted"`
	// Deprecated.
	TestSummaryUrl string `json:"testSummaryUrl"`
}

// CheckResult represents a Google3 CL presubmit check.
type CheckResult struct {
	Name      string         `json:"name"`
	Result    string         `json:"result"`
	Status    string         `json:"status"`
	StartTime jsonutils.Time `json:"startTime"`
	Url       string         `json:"url"`
}

// AsIssue validates the Roll and generates an AutoRollIssue representing the same information. If
// invalid, returns an error safe for HTTP response.
func (roll Roll) AsIssue() (*autoroll.AutoRollIssue, error) {
	if util.TimeIsZero(time.Time(roll.Created)) || roll.RollingFrom == "" || roll.RollingTo == "" {
		return nil, errors.New("Missing parameter.")
	}
	if roll.Closed && roll.Result == autoroll.ROLL_RESULT_IN_PROGRESS {
		return nil, errors.New("Inconsistent parameters: result must be set.")
	}
	if roll.Submitted && !roll.Closed {
		return nil, errors.New("Inconsistent parameters: submitted but not closed.")
	}
	if !util.In(roll.Result, []string{autoroll.ROLL_RESULT_DRY_RUN_FAILURE, autoroll.ROLL_RESULT_IN_PROGRESS, autoroll.ROLL_RESULT_SUCCESS, autoroll.ROLL_RESULT_FAILURE}) {
		return nil, errors.New("Unsupported value for result.")
	}

	isDryRun := false
	cqFinished := false
	cqSuccess := false
	dryRunFinished := false
	dryRunSuccess := false
	switch roll.Result {
	case autoroll.ROLL_RESULT_DRY_RUN_SUCCESS:
		isDryRun = true
		dryRunFinished = true
		dryRunSuccess = true
	case autoroll.ROLL_RESULT_DRY_RUN_FAILURE:
		isDryRun = true
		dryRunFinished = true
	case autoroll.ROLL_RESULT_DRY_RUN_IN_PROGRESS:
		isDryRun = true
	case autoroll.ROLL_RESULT_SUCCESS:
		cqFinished = true
		cqSuccess = true
	case autoroll.ROLL_RESULT_FAILURE:
		cqFinished = true
	}

	tryResults := []*autoroll.TryResult{}
	// TestSummaryUrl is for legacy requests that do not specify CheckResults.
	if roll.TestSummaryUrl != "" {
		url, err := url.Parse(roll.TestSummaryUrl)
		if err != nil {
			sklog.Warningf("Invalid Roll in request; invalid testSummaryUrl parameter %q: %s", roll.TestSummaryUrl, err)
			return nil, errors.New("Invalid testSummaryUrl parameter.")
		}
		testStatus := autoroll.TRYBOT_STATUS_STARTED
		testResult := ""
		switch roll.Result {
		case autoroll.ROLL_RESULT_DRY_RUN_FAILURE, autoroll.ROLL_RESULT_FAILURE:
			testStatus = autoroll.TRYBOT_STATUS_COMPLETED
			testResult = autoroll.TRYBOT_RESULT_FAILURE
		case autoroll.ROLL_RESULT_SUCCESS:
			testStatus = autoroll.TRYBOT_STATUS_COMPLETED
			testResult = autoroll.TRYBOT_RESULT_SUCCESS
		case autoroll.ROLL_RESULT_IN_PROGRESS:
		}
		tryResults = []*autoroll.TryResult{
			{
				Builder:  "Test Summary",
				Category: autoroll.TRYBOT_CATEGORY_CQ,
				Created:  time.Time(roll.Created),
				Result:   testResult,
				Status:   testStatus,
				Url:      url.String(),
			},
		}
	}
	for _, r := range roll.CheckResults {
		url, _ := url.Parse(fmt.Sprintf("%s%d", issueUrlBase, roll.ChangeListNumber))
		if r.Url != "" {
			var err error
			url, err = url.Parse(r.Url)
			if err != nil {
				sklog.Warningf("Invalid Roll in request; invalid checkResults.url parameter %q: %s", r.Url, err)
				return nil, errors.New("Invalid checkResult.url parameter.")
			}
		}
		if !util.In(r.Status, []string{autoroll.TRYBOT_STATUS_STARTED, autoroll.TRYBOT_STATUS_COMPLETED, autoroll.TRYBOT_STATUS_SCHEDULED}) {
			return nil, errors.New("Unsupported value for checkResult.status.")
		}
		result := r.Result
		if r.Status == autoroll.TRYBOT_STATUS_COMPLETED {
			if !util.In(result, []string{autoroll.TRYBOT_RESULT_CANCELED, autoroll.TRYBOT_RESULT_SUCCESS, autoroll.TRYBOT_RESULT_FAILURE}) {
				return nil, errors.New("Unsupported value for checkResult.result.")
			}
		} else {
			result = ""
		}
		tryResults = append(tryResults, &autoroll.TryResult{
			Builder:  r.Name,
			Category: autoroll.TRYBOT_CATEGORY_CQ,
			Created:  time.Time(r.StartTime),
			Result:   result,
			Status:   r.Status,
			Url:      url.String(),
		})
	}
	return &autoroll.AutoRollIssue{
		Closed:         roll.Closed,
		Committed:      roll.Submitted,
		Created:        time.Time(roll.Created),
		CqFinished:     cqFinished,
		CqSuccess:      cqSuccess,
		DryRunFinished: dryRunFinished,
		DryRunSuccess:  dryRunSuccess,
		IsDryRun:       isDryRun,
		Issue:          int64(roll.ChangeListNumber),
		Modified:       time.Time(roll.Modified),
		Patchsets:      nil,
		Result:         roll.Result,
		RollingFrom:    roll.RollingFrom,
		RollingTo:      roll.RollingTo,
		Subject:        roll.Subject,
		TryResults:     tryResults,
	}, nil
}

// rollHandler parses the JSON body as a Roll and inserts/updates it into the AutoRoll DB. The
// request must be authenticated via the protocol implemented in the webhook package. Use a POST
// request for a new roll and a PUT request to update an existing roll.
func (a *AutoRoller) rollHandler(w http.ResponseWriter, r *http.Request) {
	data, err := webhook.AuthenticateRequest(r)
	if err != nil {
		httputils.ReportError(w, err, "Failed authentication.", http.StatusInternalServerError)
		return
	}
	roll := Roll{}
	if err := json.Unmarshal(data, &roll); err != nil {
		httputils.ReportError(w, err, "Failed to parse request.", http.StatusInternalServerError)
		return
	}
	issue, err := roll.AsIssue()
	if err != nil {
		httputils.ReportError(w, nil, err.Error(), http.StatusInternalServerError)
		return
	}
	ctx := context.Background()
	if err := a.AddOrUpdateIssue(ctx, issue, r.Method); err != nil {
		httputils.ReportError(w, nil, err.Error(), http.StatusInternalServerError)
		return
	}
	if err := a.UpdateStatus(ctx, roll.ErrorMsg, false); err != nil {
		httputils.ReportError(w, err, "Failed to set new status.", http.StatusInternalServerError)
		return
	}
}
