package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"
	"sort"
	"time"

	"cloud.google.com/go/pubsub"
	"github.com/go-chi/chi/v5"
	"github.com/unrolled/secure"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"

	"go.skia.org/infra/am/go/audit"
	"go.skia.org/infra/am/go/incident"
	"go.skia.org/infra/am/go/note"
	"go.skia.org/infra/am/go/reminder"
	"go.skia.org/infra/am/go/silence"
	"go.skia.org/infra/am/go/types"
	"go.skia.org/infra/email/go/emailclient"
	"go.skia.org/infra/go/alerts"
	"go.skia.org/infra/go/allowed"
	"go.skia.org/infra/go/alogin"
	"go.skia.org/infra/go/alogin/proxylogin"
	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/baseapp"
	"go.skia.org/infra/go/ds"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/pubsub/sub"
	"go.skia.org/infra/go/roles"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
)

// flags
var (
	assignGroup  = flag.String("assign_group", "google/skia-root@google.com", "The chrome infra auth group to use for users incidents can be assigned to.")
	host         = flag.String("host", "am.skia.org", "HTTP service host")
	namespace    = flag.String("namespace", "", "The Cloud Datastore namespace, such as 'alert-manager'.")
	internalPort = flag.String("internal_port", ":9000", "HTTP internal service address (e.g., ':9000') for unauthenticated in-cluster requests.")
	project      = flag.String("project", "skia-public", "The Google Cloud project name.")

	silenceRecentlyExpiredDuration = flag.Duration("recently_expired_duration", 2*time.Hour, "Incidents with silences that recently expired within this duration are shown with an icon.")
)

const (
	// expireDuration is the time to wait before expiring an incident.
	expireDuration = 5 * time.Minute

	// Constants for sending reminder emails.
	reminderNumThreshold       = 10
	reminderDurationThreshold  = 600
	reminderDurationPercentage = 0.60

	numPubSubReceiverGoRoutines = 10
)

// server is the state of the server.
type server struct {
	incidentStore *incident.Store
	silenceStore  *silence.Store
	templates     *template.Template
	assign        allowed.Allow // A list of people that incidents can be assigned to.
	alogin        *proxylogin.ProxyLogin
}

// See baseapp.Constructor.
func New() (baseapp.App, error) {
	var assign allowed.Allow
	ctx := context.Background()

	ts, err := google.DefaultTokenSource(ctx, pubsub.ScopePubSub, auth.ScopeUserinfoEmail, "https://www.googleapis.com/auth/datastore")
	if err != nil {
		return nil, err
	}

	if !*baseapp.Local {
		client := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()
		assign, err = allowed.NewAllowedFromChromeInfraAuth(client, *assignGroup)
		if err != nil {
			return nil, err
		}
	} else {
		assign = allowed.NewAllowedFromList([]string{"betty@example.org", "fred@example.org", "barney@example.org", "wilma@example.org"})
	}

	if *namespace == "" {
		return nil, fmt.Errorf("The --namespace flag is required. See infra/DATASTORE.md for format details.\n")
	}
	if !*baseapp.Local && !util.In(*namespace, []string{ds.ALERT_MANAGER_NS}) {
		return nil, fmt.Errorf("When running in prod the datastore namespace must be a known value.")
	}
	if err := ds.InitWithOpt(*project, *namespace, option.WithTokenSource(ts)); err != nil {
		return nil, fmt.Errorf("Failed to init Cloud Datastore: %s", err)
	}

	sub, err := sub.New(ctx, *baseapp.Local, *project, alerts.TOPIC, numPubSubReceiverGoRoutines)
	if err != nil {
		return nil, skerr.Wrapf(err, "Failed to create subscription.")
	}

	srv := &server{
		incidentStore: incident.NewStore(ds.DS, []string{"kubernetes_pod_name", "instance", "pod_template_hash", "pod", "exported_pod", "uid"}),
		silenceStore:  silence.NewStore(ds.DS),
		assign:        assign,
		alogin:        proxylogin.NewWithDefaults(),
	}
	srv.loadTemplates()

	// Start goroutine to send reminders to active alert owners.
	reminder.StartReminderTicker(srv.incidentStore, srv.silenceStore, emailclient.New())

	// livenesses gets populated as notifications arrive.
	livenesses := map[string]metrics2.Liveness{}

	// Process all incoming PubSub requests.
	go func() {
		for {
			err := sub.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
				msg.Ack()
				var m map[string]string
				if err := json.Unmarshal(msg.Data, &m); err != nil {
					sklog.Error(err)
					return
				}
				if m[alerts.TYPE] == alerts.TYPE_HEALTHZ {
					location := m[alerts.LOCATION]
					sklog.Infof("healthz received: %q", location)
					if l, ok := livenesses[m[alerts.LOCATION]]; ok {
						l.Reset()
					} else {
						livenesses[location] = metrics2.NewLiveness("alert_to_pubsub_alive", map[string]string{alerts.LOCATION: location})
					}
				} else {
					if _, err := srv.incidentStore.AlertArrival(m); err != nil {
						sklog.Errorf("Error processing alert: %s", err)
					}
				}
			})
			if err != nil {
				sklog.Errorf("Failed receiving pubsub message: %s", err)
			}
		}
	}()

	// This is really just a backstop in case we miss a resolved event for the incident.
	go func() {
		for range time.Tick(1 * time.Minute) {
			ins, err := srv.incidentStore.GetAll()
			if err != nil {
				sklog.Errorf("Failed to load incidents: %s", err)
				continue
			}
			now := time.Now()
			for _, in := range ins {
				// If it was last updated too long ago then it should be archived.
				if time.Unix(in.LastSeen, 0).Add(expireDuration).Before(now) {
					if _, err := srv.incidentStore.Archive(in.Key); err != nil {
						sklog.Errorf("Failed to archive incident: %s", err)
					}
				}
			}
		}
	}()

	srv.startInternalServer()

	return srv, nil
}

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

func (srv *server) mainHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	if *baseapp.Local {
		srv.loadTemplates()
	}
	if err := srv.templates.ExecuteTemplate(w, "index.html", map[string]string{
		"Nonce": secure.CSPNonce(r.Context()),
	}); err != nil {
		sklog.Errorf("Failed to expand template: %s", err)
	}
}

type addNoteRequest struct {
	Text string `json:"text"`
	Key  string `json:"key"`
}

// 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 = string(srv.alogin.LoggedInAs(r))
	}
	return user
}

func (srv *server) addNoteHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req addNoteRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode add note request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "add-note", req, srv.alogin)

	note := note.Note{
		Text:   req.Text,
		TS:     time.Now().Unix(),
		Author: srv.user(r),
	}
	in, err := srv.incidentStore.AddNote(req.Key, note)
	if err != nil {
		httputils.ReportError(w, err, "Failed to add incident note.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) addSilenceNoteHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req addNoteRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode add note request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "add-silence-note", req, srv.alogin)

	note := note.Note{
		Text:   req.Text,
		TS:     time.Now().Unix(),
		Author: srv.user(r),
	}
	in, err := srv.silenceStore.AddNote(req.Key, note)
	if err != nil {
		httputils.ReportError(w, err, "Failed to add silence note.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

type delNoteRequest struct {
	Index int    `json:"index"`
	Key   string `json:"key"`
}

func (srv *server) delNoteHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req delNoteRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode add note request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "del-note", req, srv.alogin)
	in, err := srv.incidentStore.DeleteNote(req.Key, req.Index)
	if err != nil {
		httputils.ReportError(w, err, "Failed to del incident note.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) delSilenceNoteHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req delNoteRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode add note request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "del-silence-note", req, srv.alogin)
	in, err := srv.silenceStore.DeleteNote(req.Key, req.Index)
	if err != nil {
		httputils.ReportError(w, err, "Failed to del silence note.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

type TakeRequest struct {
	Key string `json:"key"`
}

func (srv *server) takeHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req TakeRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode take request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "take", req, srv.alogin)

	in, err := srv.incidentStore.Assign(req.Key, srv.user(r))
	if err != nil {
		httputils.ReportError(w, err, "Failed to assign.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

type StatsResponseSlice types.StatsResponse

func (p StatsResponseSlice) Len() int           { return len(p) }
func (p StatsResponseSlice) Less(i, j int) bool { return p[i].Num > p[j].Num }
func (p StatsResponseSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

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

	var req types.StatsRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode stats request.", http.StatusInternalServerError)
		return
	}
	ins, err := srv.incidentStore.GetRecentlyResolvedInRange(req.Range)
	if err != nil {
		httputils.ReportError(w, err, "Failed to query for Incidents.", http.StatusInternalServerError)
	}
	count := map[string]*types.Stat{}
	for _, in := range ins {
		if stat, ok := count[in.ID]; !ok {
			count[in.ID] = &types.Stat{
				Num:      1,
				Incident: in,
			}
		} else {
			stat.Num += 1
		}
	}
	ret := types.StatsResponse{}
	for _, v := range count {
		ret = append(ret, v)
	}
	sort.Sort(StatsResponseSlice(ret))
	if err := json.NewEncoder(w).Encode(ret); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

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

	var req types.IncidentsInRangeRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode incident range request.", http.StatusInternalServerError)
		return
	}
	ret, err := srv.incidentStore.GetRecentlyResolvedInRangeWithID(req.Range, req.Incident.ID)
	if err != nil {
		httputils.ReportError(w, err, "Failed to query for incidents.", http.StatusInternalServerError)
	}
	if err := json.NewEncoder(w).Encode(ret); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

type AssignRequest struct {
	Key   string `json:"key"`
	Email string `json:"email"`
}

func (srv *server) assignHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req AssignRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode take request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "assign", req, srv.alogin)
	in, err := srv.incidentStore.Assign(req.Key, req.Email)
	if err != nil {
		httputils.ReportError(w, err, "Failed to assign.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(in); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

type AssignMultipleRequest struct {
	Keys  []string `json:"keys"`
	Email string   `json:"email"`
}

func (srv *server) assignMultipleHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req AssignMultipleRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode assign multiple request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "assign multiple", req, srv.alogin)

	for _, k := range req.Keys {
		if _, err := srv.incidentStore.Assign(k, req.Email); err != nil {
			httputils.ReportError(w, err, "Failed to assign multiple.", http.StatusInternalServerError)
			return
		}
	}

	ins, err := srv.getActiveAndRecentlyResolvedIncidents()
	if err != nil {
		httputils.ReportError(w, err, "Failed to load incidents.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(ins); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) getActiveAndRecentlyResolvedIncidents() ([]incident.Incident, error) {
	ins, err := srv.incidentStore.GetAll()
	if err != nil {
		return nil, fmt.Errorf("Failed to load incidents: %s", err)
	}
	recents, err := srv.incidentStore.GetRecentlyResolved()
	if err != nil {
		return nil, fmt.Errorf("Failed to load recents: %s", err)
	}
	ins = append(ins, recents...)
	return ins, nil
}

func (srv *server) emailsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	emails := srv.assign.Emails()
	sort.Strings(emails)
	if err := json.NewEncoder(w).Encode(&emails); err != nil {
		sklog.Errorf("Failed to encode emails: %s", err)
	}
}

func (srv *server) silencesHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	silences, err := srv.silenceStore.GetAll()
	if err != nil {
		httputils.ReportError(w, err, "Failed to load recents.", http.StatusInternalServerError)
		return
	}
	if silences == nil {
		silences = []silence.Silence{}
	}
	recents, err := srv.silenceStore.GetRecentlyArchived(0)
	if err != nil {
		httputils.ReportError(w, err, "Failed to load recents.", http.StatusInternalServerError)
		return
	}
	silences = append(silences, recents...)
	if err := json.NewEncoder(w).Encode(silences); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) auditLogsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	logs, err := audit.GetLogs(r.Context())
	if err != nil {
		httputils.ReportError(w, err, "Failed to load audit logs.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(logs); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) incidentHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	ins, err := srv.getActiveAndRecentlyResolvedIncidents()
	if err != nil {
		httputils.ReportError(w, err, "Failed to load incidents.", http.StatusInternalServerError)
		return
	}

	idsToRecentlyExpiredSilences := map[string]bool{}
	archivedSilences, err := srv.silenceStore.GetRecentlyArchived(*silenceRecentlyExpiredDuration)
	if err != nil {
		httputils.ReportError(w, err, "Failed to load archived silences.", http.StatusInternalServerError)
	}
	if len(archivedSilences) > 0 {
		for _, i := range ins {
			idsToRecentlyExpiredSilences[i.ID] = i.IsSilenced(archivedSilences, false)
		}
	}
	resp := types.IncidentsResponse{
		Incidents:                    ins,
		IdsToRecentlyExpiredSilences: idsToRecentlyExpiredSilences,
	}
	if err := json.NewEncoder(w).Encode(resp); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) recentIncidentsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	id := r.FormValue("id")
	key := r.FormValue("key")
	ins, err := srv.incidentStore.GetRecentlyResolvedForID(id, key)
	if err != nil {
		httputils.ReportError(w, err, "Failed to load incidents.", http.StatusInternalServerError)
		return
	}

	// Get recently archived silences to see if the incident recently expired.
	archivedSilences, err := srv.silenceStore.GetRecentlyArchived(*silenceRecentlyExpiredDuration)
	if err != nil {
		httputils.ReportError(w, err, "Failed to load archived silences.", http.StatusInternalServerError)
		return
	}
	recentlyExpired := false
	if len(ins) > 0 {
		recentlyExpired = ins[0].IsSilenced(archivedSilences, false)
	}

	resp := types.RecentIncidentsResponse{
		Incidents:              ins,
		Flaky:                  incident.AreIncidentsFlaky(ins, reminderNumThreshold, reminderDurationThreshold, reminderDurationPercentage),
		RecentlyExpiredSilence: recentlyExpired,
	}
	if err := json.NewEncoder(w).Encode(resp); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) saveSilenceHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req silence.Silence
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode silence creation request.", http.StatusInternalServerError)
		return
	}
	if err := req.ValidateRegexes(); err != nil {
		httputils.ReportError(w, err, "Silence has invalid regex.", http.StatusInternalServerError)
		return
	}

	audit.Log(r, "create-silence", req, srv.alogin)
	silence, err := srv.silenceStore.Put(&req)
	if err != nil {
		httputils.ReportError(w, err, "Failed to create silence.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(silence); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) archiveSilenceHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req silence.Silence
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode silence creation request.", http.StatusInternalServerError)
		return
	}
	if err := req.ValidateRegexes(); err != nil {
		httputils.ReportError(w, err, "Silence has invalid regex.", http.StatusInternalServerError)
		return
	}

	audit.Log(r, "archive-silence", req, srv.alogin)
	silence, err := srv.silenceStore.Archive(req.Key)
	if err != nil {
		httputils.ReportError(w, err, "Failed to archive silence.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(silence); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) reactivateSilenceHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var req silence.Silence
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httputils.ReportError(w, err, "Failed to decode silence reactivation request.", http.StatusInternalServerError)
		return
	}
	if err := req.ValidateRegexes(); err != nil {
		httputils.ReportError(w, err, "Silence has invalid regex.", http.StatusInternalServerError)
		return
	}

	audit.Log(r, "reactivate-silence", req, srv.alogin)
	silence, err := srv.silenceStore.Reactivate(req.Key, req.Duration, srv.user(r))
	if err != nil {
		httputils.ReportError(w, err, "Failed to reactivate silence.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(silence); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

func (srv *server) deleteSilenceHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var sil silence.Silence
	if err := json.NewDecoder(r.Body).Decode(&sil); err != nil {
		httputils.ReportError(w, err, "Failed to decode silence deletion request.", http.StatusInternalServerError)
		return
	}
	audit.Log(r, "delete-silence", sil, srv.alogin)
	if err := srv.silenceStore.Delete(sil.Key); err != nil {
		httputils.ReportError(w, err, "Failed to delete silence.", http.StatusInternalServerError)
		return
	}
	if err := json.NewEncoder(w).Encode(sil); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

// newSilenceHandler creates and returns a new Silence pre-populated with good defaults.
func (srv *server) newSilenceHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	s := silence.New(srv.user(r))
	if err := json.NewEncoder(w).Encode(s); err != nil {
		sklog.Errorf("Failed to send response: %s", err)
	}
}

// See baseapp.App.
func (srv *server) AddHandlers(r chi.Router) {
	r.HandleFunc("/", srv.mainHandler)
	r.HandleFunc(("/_/login/status"), alogin.LoginStatusHandler(srv.alogin))

	// GETs
	r.Get("/_/emails", srv.emailsHandler)
	r.Get("/_/incidents", srv.incidentHandler)
	r.Get("/_/new_silence", srv.newSilenceHandler)
	r.Get("/_/recent_incidents", srv.recentIncidentsHandler)
	r.Get("/_/silences", srv.silencesHandler)

	// POSTs
	r.Post("/_/add_note", srv.addNoteHandler)
	r.Post("/_/add_silence_note", srv.addSilenceNoteHandler)
	r.Post("/_/archive_silence", srv.archiveSilenceHandler)
	r.Post("/_/assign", srv.assignHandler)
	r.Post("/_/assign_multiple", srv.assignMultipleHandler)
	r.Post("/_/audit_logs", srv.auditLogsHandler)
	r.Post("/_/del_note", srv.delNoteHandler)
	r.Post("/_/del_silence_note", srv.delSilenceNoteHandler)
	r.Post("/_/del_silence", srv.deleteSilenceHandler)
	r.Post("/_/reactivate_silence", srv.reactivateSilenceHandler)
	r.Post("/_/save_silence", srv.saveSilenceHandler)
	r.Post("/_/take", srv.takeHandler)
	r.Post("/_/stats", srv.statsHandler)
	r.Post("/_/incidents_in_range", srv.incidentsInRangeHandler)
}

// See baseapp.App.
func (srv *server) AddMiddleware() []func(http.Handler) http.Handler {
	ret := []func(http.Handler) http.Handler{}
	if !*baseapp.Local {
		ret = append(ret, alogin.ForceRoleMiddleware(srv.alogin, roles.Viewer))
	}
	return ret
}

func (srv *server) startInternalServer() {
	// Internal endpoints that are only accessible from within the cluster.
	unprotected := chi.NewRouter()
	unprotected.Get("/_/incidents", srv.incidentHandler)
	unprotected.Get("/_/silences", srv.silencesHandler)
	go func() {
		sklog.Fatal(http.ListenAndServe(*internalPort, unprotected))
	}()
}

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