package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"sort"
	"strings"
	"time"

	"go.skia.org/infra/autoroll/go/status"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/ds"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/tree_status/go/types"
	"golang.org/x/oauth2"
	"google.golang.org/api/option"
)

// Autoroller - describes an autoroller to query autoroll_status with.
// Eg: ID: "skia-autoroll", Host: "autoroll.skia.org".
type Autoroller struct {
	ID   string
	Host string
}

var (
	// nameToAutoroller is a map of autoroller display names to their ID and hosts.
	nameToAutoroller = map[string]*Autoroller{
		"ANGLE":       {ID: "angle-skia-autoroll", Host: "autoroll.skia.org"},
		"Android":     {ID: "android-master-autoroll", Host: "skia-autoroll.corp.goog"},
		"Chrome":      {ID: "skia-autoroll", Host: "autoroll.skia.org"},
		"Google3":     {ID: "google3-autoroll", Host: "skia-autoroll.corp.goog"},
		"Flutter":     {ID: "skia-flutter-autoroll", Host: "autoroll.skia.org"},
		"Skcms":       {ID: "skcms-skia-autoroll", Host: "autoroll.skia.org"},
		"SwiftShader": {ID: "swiftshader-skia-autoroll", Host: "autoroll.skia.org"},
	}

	// Channel that will determine which rollers need to be watched.
	// Entries will look like this: "Android, Chrome, Flutter".
	rollersToWatch = make(chan string, 1)
)

func getAutorollersSnapshot(ctx context.Context, db status.DB) ([]*types.AutorollerSnapshot, error) {
	autorollersSnapshot := []*types.AutorollerSnapshot{}
	for name, autoroller := range nameToAutoroller {
		s, err := db.Get(ctx, autoroller.ID)
		if err != nil {
			return nil, fmt.Errorf("Could not get the status of %s: %s", autoroller.ID, err)
		}
		snapshot := &types.AutorollerSnapshot{
			DisplayName: name,
			NumFailed:   s.AutoRollMiniStatus.NumFailedRolls,
			Url:         fmt.Sprintf("https://%s/r/%s", autoroller.Host, autoroller.ID),
		}
		autorollersSnapshot = append(autorollersSnapshot, snapshot)
	}
	sort.Slice(autorollersSnapshot, func(i, j int) bool {
		return autorollersSnapshot[i].DisplayName < autorollersSnapshot[j].DisplayName
	})
	return autorollersSnapshot, nil
}

func StartWatchingAutorollers(rollers string) {
	rollersToWatch <- rollers
}

func StopWatchingAutorollers() {
	// Empty the RollersToWatch channel.
L:
	for {
		select {
		case <-rollersToWatch:
		default:
			break L
		}
	}
}

func AutorollersInit(ctx context.Context, ts oauth2.TokenSource) (status.DB, error) {
	if err := ds.InitWithOpt(common.PROJECT_ID, ds.AUTOROLL_NS, option.WithTokenSource(ts)); err != nil {
		return nil, skerr.Wrapf(err, "Failed to initialize Cloud Datastore for autorollers")
	}
	db := status.NewDatastoreDB()

	// Start goroutine to watch for rollers.
	go func() {
		for {
			rollers := <-rollersToWatch
			sklog.Infof("Checking for rollers: %s", rollers)
			if rollers == "" {
				continue
			}
			rollsLanded := true
			rollerNames := strings.Split(rollers, ", ")
			for _, rollerName := range rollerNames {
				roller := nameToAutoroller[rollerName]
				s, err := db.Get(ctx, roller.ID)
				if err != nil {
					sklog.Errorf("Could not get status of %s: %s\n", roller, err)
					// Continue so that we can try again.
					rollsLanded = false
					continue
				}
				if s.AutoRollMiniStatus.NumFailedRolls == 0 {
					sklog.Infof("Roller %s has 0 NumFailedRolls\n", roller)
					rollsLanded = rollsLanded && true
					continue
				} else {
					sklog.Infof("Roller %s has %d NumFailedRolls. Continue the loop.\n", roller, s.AutoRollMiniStatus.NumFailedRolls)
					rollsLanded = false
					continue
				}
			}
			if rollsLanded {
				// Send status notification.
				rollerText := "roller"
				if len(rollerNames) > 1 {
					rollerText = fmt.Sprintf("%ss", rollerText)
				}
				message := fmt.Sprintf("Open: %s %s landed", rollers, rollerText)
				sklog.Infof("Sending status notification with message: \"%s\"", message)
				if err := AddStatus(message, "tree-status@skia.org", OPEN_STATE, ""); err != nil {
					sklog.Infof("Failed to add automated message to the datastore: %s", err)
				}
			} else {
				rollersToWatch <- rollers
				sklog.Info("Sleeping for 10 seconds")
				time.Sleep(10 * time.Second)
			}
		}
	}()

	return db, nil
}

// HTTP Handlers.

func (srv *Server) autorollersHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	as, err := getAutorollersSnapshot(r.Context(), srv.autorollDB)
	if err != nil {
		httputils.ReportError(w, err, "Failed to get autoroll statuses.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(as); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}
