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

package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"strconv"
	"time"

	"cloud.google.com/go/storage"
	"google.golang.org/api/option"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/gcs"
	"go.skia.org/infra/go/gcs/gcsclient"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/task_driver/go/lib/auth_steps"
	"go.skia.org/infra/task_driver/go/lib/checkout"
	"go.skia.org/infra/task_driver/go/td"
)

const (
	g3CanaryBucketName = "g3-compile-tasks"

	InfraFailureErrorMsg    = "Your run failed due to unknown infrastructure failures. Ask the Infra Gardener to investigate (or directly ping rmistry@)."
	MissingApprovalErrorMsg = "To run the G3 tryjob, changes must be either owned and authored by Googlers or approved (Code-Review+1) by Googlers."
	MergeConflictErrorMsg   = "G3 tryjob failed because the change is causing a merge conflict when applying it to the Skia hash in G3."

	PatchingInformation = "Tip: If needed, could try patching in the CL into a local G3 client with \"g4 patch\" and then hacking on it."
)

type CanaryStatusType string

const (
	ExceptionStatus       CanaryStatusType = "exception"
	MissingApprovalStatus CanaryStatusType = "missing_approval"
	MergeConflictStatus   CanaryStatusType = "merge_conflict"
	FailureStatus         CanaryStatusType = "failure"
	SuccessStatus         CanaryStatusType = "success"
)

type G3CanaryTask struct {
	Issue    int              `json:"issue"`
	Patchset int              `json:"patchset"`
	Status   CanaryStatusType `json:"status"`
	Result   string           `json:"result"`
	Error    string           `json:"error"`
	CL       int              `json:"cl"`
}

func main() {
	var (
		projectId = flag.String("project_id", "", "ID of the Google Cloud project.")
		taskId    = flag.String("task_id", "", "ID of this task.")
		taskName  = flag.String("task_name", "", "Name of the task.")
		output    = flag.String("o", "", "If provided, dump a JSON blob of step data to the given file. Prints to stdout if '-' is given.")
		local     = flag.Bool("local", true, "True if running locally (as opposed to on the bots)")

		checkoutFlags = checkout.SetupFlags(nil)
	)
	ctx := td.StartRun(projectId, taskId, taskName, output, local)
	defer td.EndRun(ctx)

	rs, err := checkout.GetRepoState(checkoutFlags)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
	if rs.Issue == "" || rs.Patchset == "" {
		td.Fatalf(ctx, "This task driver should be run only as a try bot")
	}

	// Create token source with scope for GCS access.
	ts, err := auth_steps.Init(ctx, *local, auth.SCOPE_USERINFO_EMAIL, auth.SCOPE_FULL_CONTROL)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
	client := httputils.DefaultClientConfig().WithTokenSource(ts).Client()
	store, err := storage.NewClient(ctx, option.WithHTTPClient(client))
	if err != nil {
		td.Fatalf(ctx, "Failed to create storage service client: %s", err)
	}
	gcsClient := gcsclient.New(store, g3CanaryBucketName)

	taskFileName := fmt.Sprintf("%s-%s.json", rs.Issue, rs.Patchset)
	taskStoragePath := fmt.Sprintf("gs://%s/%s", g3CanaryBucketName, taskFileName)

	err = td.Do(ctx, td.Props("Trigger new task if not already running"), func(ctx context.Context) error {
		if _, err := gcsClient.GetFileContents(ctx, taskFileName); err != nil {
			if err == storage.ErrObjectNotExist {
				// The task is not already running. Create a new file to trigger a new run.
				if err := triggerCanaryRoll(ctx, rs.Issue, rs.Patchset, taskFileName, taskStoragePath, gcsClient); err != nil {
					td.Fatal(ctx, fmt.Errorf("Could not trigger canary roll for %s/%s: %s", rs.Issue, rs.Patchset, err))
				}
			} else {
				return fmt.Errorf("Could not read %s: %s", taskStoragePath, err)
			}
		} else {
			fmt.Printf("G3 canary task for %s/%s already exists\n", rs.Issue, rs.Patchset)
		}
		return nil
	})
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	defer func() {
		// Cleanup the storage file after the task finishes.
		if err := gcsClient.DeleteFile(ctx, taskFileName); err != nil {
			sklog.Errorf("Could not delete %s: %s", taskStoragePath, err)
		}
	}()

	// Add documentation link for canary rolls.
	td.StepText(ctx, "Canary roll doc", "https://goto.google.com/autoroller-canary-bots")

	// Wait for the canary roll to finish.
	if err := waitForCanaryRoll(ctx, taskFileName, taskStoragePath, gcsClient); err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
}

func triggerCanaryRoll(ctx context.Context, issue, patchset, taskFileName, taskStoragePath string, gcsClient gcs.GCSClient) error {
	ctx = td.StartStep(ctx, td.Props("Trigger canary roll"))
	defer td.EndStep(ctx)

	i, err := strconv.Atoi(issue)
	if err != nil {
		return fmt.Errorf("Could not convert %s to int: %s", issue, err)
	}
	p, err := strconv.Atoi(patchset)
	if err != nil {
		return fmt.Errorf("Could not convert %s to int: %s", patchset, err)
	}
	newTask := G3CanaryTask{
		Issue:    i,
		Patchset: p,
	}
	taskJson, err := json.Marshal(newTask)
	if err != nil {
		return fmt.Errorf("Could not encode task to JSON: %s", err)
	}
	if err := gcsClient.SetFileContents(ctx, taskFileName, gcs.FILE_WRITE_OPTS_TEXT, taskJson); err != nil {
		return fmt.Errorf("Could not write task to %s: %s", taskStoragePath, err)
	}
	fmt.Printf("G3 canary task for %s/%s has been successfully added to %s\n", issue, patchset, taskStoragePath)
	return nil
}

func waitForCanaryRoll(parentCtx context.Context, taskFileName, taskStoragePath string, gcsClient gcs.GCSClient) error {
	ctx := td.StartStep(parentCtx, td.Props("Wait for canary roll"))
	defer td.EndStep(ctx)

	// For writing to the step's log stream.
	stdout := td.NewLogStream(ctx, "stdout", td.SeverityInfo)
	// Lets add the roll link only once to step data.
	addedRollLinkStepData := false
	for {
		// Read task status from storage.
		contents, err := gcsClient.GetFileContents(ctx, taskFileName)
		if err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not read contents of %s: %s", taskStoragePath, err))
		}
		var task G3CanaryTask
		if err := json.Unmarshal(contents, &task); err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not unmarshal %s: %s", taskStoragePath, err))
		}

		var rollStatus string
		if task.CL == 0 {
			rollStatus = "Waiting for Canary roll to start"
		} else {
			clLink := fmt.Sprintf("http://cl/%d", task.CL)
			if !addedRollLinkStepData {
				// Add the roll link to both the current step and it's parent.
				td.StepText(ctx, "Canary roll CL", clLink)
				td.StepText(parentCtx, "Canary roll CL", clLink)
				addedRollLinkStepData = true
			}
			rollStatus = fmt.Sprintf("Canary roll [ %s ] has status %s", clLink, task.Result)
		}
		if _, err := stdout.Write([]byte(rollStatus)); err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not write to stdout: %s", err))
		}

		switch task.Status {
		case "":
			// Still waiting for the task.
			time.Sleep(30 * time.Second)
			continue
		case ExceptionStatus:
			if task.Error == "" {
				return td.FailStep(ctx, fmt.Errorf("Run failed with: %s", task.Error))
			} else {
				// Use a general purpose error message.
				return td.FailStep(ctx, errors.New(InfraFailureErrorMsg))
			}
		case MissingApprovalStatus:
			return td.FailStep(ctx, errors.New(MissingApprovalErrorMsg))
		case MergeConflictStatus:
			return td.FailStep(ctx, errors.New(MergeConflictErrorMsg))
		case FailureStatus:
			return td.FailStep(ctx, fmt.Errorf("Run failed G3 TAP.\n%s", PatchingInformation))
		case SuccessStatus:
			// Run passed G3 TAP.
			return nil
		}
	}
}
