package main

import (
	"context"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"

	"cloud.google.com/go/datastore"
	"github.com/gorilla/mux"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"

	"go.skia.org/infra/autoroll/go/status"
	"go.skia.org/infra/go/allowed"
	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/baseapp"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/login"
	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
)

// defaultSkiaRepo is the repo to default to when no repos have been specified.
// It is the main "skia.git" repo.
const defaultSkiaRepo = "skia"

// Flags
var (
	host               = flag.String("host", "tree-status.skia.org", "HTTP service host")
	modifyGroup        = flag.String("modify_group", "project-skia-committers", "The chrome infra auth group to use for who is allowed to change tree status.")
	chromeInfraAuthJWT = flag.String("chrome_infra_auth_jwt", "/var/secrets/skia-public-auth/key.json", "The JWT key for the service account that has access to chrome infra auth.")
	namespace          = flag.String("namespace", "tree-status-staging", "The Cloud Datastore namespace.")
	project            = flag.String("project", "skia-public", "The Google Cloud project name.")
	repos              = common.NewMultiStringFlag("repo", nil, "These repos will have tree status endpoints.")
	internalPort       = flag.String("internal_port", "", "HTTP internal service address (eg: ':8001' for unauthenticated in-cluster requests.")
)

var (
	// dsClient is the Cloud Datastore client to access tree statuses.
	dsClient *datastore.Client

	// repoNameRegex matches the format of supported repo names.
	repoNameRegex = "{repo:[0-9a-zA-Z._-]+}"
)

// Server is the state of the server.
type Server struct {
	templates  *template.Template
	modify     allowed.Allow // Who is allowed to modify tree status.
	autorollDB status.DB

	// skiaRepoSpecified is set to true when the main skia has been specified.
	// This boolean is used because the main skia repo requires support for
	// non-repo specified URLs (for backwards compatibility) and for watching
	// autorollers.
	skiaRepoSpecified bool
}

// See baseapp.Constructor.
func New() (baseapp.App, error) {
	ctx := context.Background()
	ts, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/datastore")
	if err != nil {
		return nil, skerr.Wrapf(err, "Problem setting up default token source")
	}

	dsClient, err = datastore.NewClient(context.Background(), *project, option.WithTokenSource(ts))
	if err != nil {
		return nil, skerr.Wrapf(err, "Failed to initialize Cloud Datastore for tree status")
	}

	// Check to see if the main skia repo has been specified. If it has been
	// specified then it will require special handling.
	skiaRepoSpecified := IsRepoSupported(defaultSkiaRepo)

	var autorollDB status.DB
	if skiaRepoSpecified {
		// Start watching for statuses with autorollers specified. Only supported for
		// the default repo (skia).
		autorollDB, err = AutorollersInit(ctx, defaultSkiaRepo, ts)
		if err != nil {
			return nil, skerr.Wrapf(err, "Could not init autorollers")
		}

		// Load the last status and whether autorollers need to be watched.
		s, err := GetLatestStatus(defaultSkiaRepo)
		if err != nil {
			return nil, skerr.Wrapf(err, "Could not find latest status")
		}
		if s.Rollers != "" {
			sklog.Infof("Last status has rollers that need to be watched: %s", s.Rollers)
			StartWatchingAutorollers(s.Rollers)
		}
	}

	var modify allowed.Allow
	if !*baseapp.Local {
		ts, err := auth.NewJWTServiceAccountTokenSource("", *chromeInfraAuthJWT, auth.ScopeUserinfoEmail)
		if err != nil {
			return nil, err
		}
		client := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()
		modify, err = allowed.NewAllowedFromChromeInfraAuth(client, *modifyGroup)
		if err != nil {
			return nil, err
		}
	} else {
		modify = allowed.NewAllowedFromList([]string{"barney@example.org"})
	}

	login.SimpleInitWithAllow(*baseapp.Port, *baseapp.Local, nil /* Admins not needed */, modify, nil /* Everyone is allowed to access */)

	srv := &Server{
		modify:            modify,
		autorollDB:        autorollDB,
		skiaRepoSpecified: skiaRepoSpecified,
	}
	srv.loadTemplates()
	liveness := metrics2.NewLiveness("alive", map[string]string{})
	fmt.Println(liveness)

	return srv, nil
}

func (srv *Server) loadTemplates() {
	blah := *baseapp.ResourcesDir
	srv.templates = template.Must(template.New("").Delims("{%", "%}").ParseFiles(
		filepath.Join(blah, "index.html"),
	))
}

// user returns the currently logged in user, or a placeholder if running locally.
func (srv *Server) user(r *http.Request) string {
	user := "barney@example.org"
	if !*baseapp.Local {
		user = login.LoggedInAs(r)
	}
	return user
}

// See baseapp.App.
func (srv *Server) AddHandlers(r *mux.Router) {
	// For login/logout.
	r.HandleFunc(login.DEFAULT_OAUTH2_CALLBACK, login.OAuth2CallbackHandler)
	r.HandleFunc("/logout/", login.LogoutHandler)
	r.HandleFunc("/loginstatus/", login.StatusHandler)

	// All endpoints that require authentication should be added to this router. The
	// rest of endpoints are left unauthenticated because they are accessed from various
	// places like: Skia infra apps, Gerrit plugin, Chrome extensions, presubmits, etc.
	appRouter := mux.NewRouter()

	if srv.skiaRepoSpecified {
		// If the main skia repo has been specified then leave default repo
		// handlers around for backwards compatibility.
		appRouter.HandleFunc("/", srv.treeStateDefaultRepoHandler).Methods("GET")
		r.HandleFunc("/current", httputils.CorsHandler(srv.bannerStatusHandler)).Methods("GET")
	}
	appRouter.HandleFunc("/_/get_autorollers", srv.autorollersHandler).Methods("POST")

	// Add repo-specific endpoints.
	appRouter.HandleFunc(fmt.Sprintf("/%s", repoNameRegex), srv.treeStateDefaultRepoHandler).Methods("GET")
	appRouter.HandleFunc(fmt.Sprintf("/%s/_/add_tree_status", repoNameRegex), srv.addStatusHandler).Methods("POST")
	appRouter.HandleFunc(fmt.Sprintf("/%s/_/recent_statuses", repoNameRegex), srv.recentStatusesHandler).Methods("POST")
	r.HandleFunc(fmt.Sprintf("/%s/current", repoNameRegex), httputils.CorsHandler(srv.bannerStatusHandler)).Methods("GET")

	if *internalPort != "" {
		internalRouter := mux.NewRouter()
		internalRouter.HandleFunc(fmt.Sprintf("/%s/current", repoNameRegex), httputils.CorsHandler(srv.bannerStatusHandler)).Methods("GET")
		internalRouter.HandleFunc("/current", srv.bannerStatusHandler).Methods("GET")

		go func() {
			sklog.Infof("Internal server on %q", *internalPort)
			sklog.Fatal(http.ListenAndServe(*internalPort, internalRouter))
		}()
	}

	// Use the appRouter as a handler and wrap it into middleware that enforces authentication.
	appHandler := http.Handler(appRouter)
	if !*baseapp.Local {
		appHandler = login.ForceAuth(appRouter, login.DEFAULT_OAUTH2_CALLBACK)
	}

	r.PathPrefix("/").Handler(appHandler)
}

// See baseapp.App.
func (srv *Server) AddMiddleware() []mux.MiddlewareFunc {
	return []mux.MiddlewareFunc{}
}

// IsRepoSupported is a utility function that returns true if the specified
// repo is a supported repo (i.e. has been specified in the repos flag).
func IsRepoSupported(repo string) bool {
	return util.In(repo, *repos)
}

func main() {
	// Parse flags to be able to send *host to baseapp.Serve
	flag.Parse()
	baseapp.Serve(New, []string{*host})
}
