// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

// Package webug implements a web-based debug/troubleshooting/introspection
// system for the BMDB. It's optimized for use by developers and trained
// operators, prioritizing information density, fast navigation and heavy
// interlinking.
package webug

import (
	"context"
	"embed"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"regexp"
	"sync"
	"time"

	"github.com/cenkalti/backoff/v4"
	"k8s.io/klog/v2"

	"source.monogon.dev/cloud/bmaas/bmdb"
	"source.monogon.dev/cloud/bmaas/bmdb/reflection"
)

var (
	//go:embed templates/*.gohtml
	templateFS embed.FS
	templates  = template.Must(template.New("base.gohtml").Funcs(templateFuncs).ParseFS(templateFS, "templates/*"))
)

// server holds the state of an active webug interface.
type server struct {
	// connection pool to BMDB.
	conn *bmdb.Connection
	// schema retrieved from BMDB.
	schema *reflection.Schema
	// muSchema locks schema for updates.
	muSchema sync.RWMutex
	// strictConsistency, when enabled, makes webug render its views with the
	// freshest available data, potentially conflicting with online
	// transactions. This should only be enabled during testing, as it tends to
	// clog up the database query planner and make everything slow.
	strictConsistency bool
}

// curSchema returns the current cached BMDB schema.
func (s *server) curSchema() *reflection.Schema {
	s.muSchema.Lock()
	defer s.muSchema.Unlock()
	return s.schema
}

// schemaWorker runs a background goroutine which attempts to update the server's
// cached BMDB schema every hour.
func (s *server) schemaWorker(ctx context.Context) {
	t := time.NewTicker(time.Hour)
	defer t.Stop()

	for {
		// Wait for the timer to tick, or for the context to expire.
		select {
		case <-ctx.Done():
			klog.Infof("Schema fetch worker exiting: %v", ctx.Err())
			return
		case <-t.C:
		}

		// Time to check the schema. Do that in an exponential backoff loop until
		// successful.
		bo := backoff.NewExponentialBackOff()
		bo.MaxElapsedTime = 0
		var schema *reflection.Schema
		err := backoff.Retry(func() error {
			var err error
			schema, err = s.conn.Reflect(ctx)
			if err != nil {
				klog.Warningf("Failed to fetch new schema: %v", err)
				return err
			}
			return nil
		}, backoff.WithContext(bo, ctx))
		// This will only happen due to context expiration.
		if err != nil {
			klog.Errorf("Giving up on schema fetch: %v", err)
			continue
		}

		// Swap the current schema if necessary.
		cur := s.curSchema().Version
		newVer := schema.Version
		if cur != newVer {
			klog.Infof("Got new schema: %s -> %s", cur, newVer)
			s.muSchema.Lock()
			s.schema = schema
			s.muSchema.Unlock()
		}
	}
}

// Register webug on an HTTP mux, using a BMDB connection pool.
//
// The given context will be used not only to time out the registration call, but
// also used to run a BMDB schema fetching goroutine that will attempt to fetch
// newer versions of the schema every hour.
//
// This is a low-level function useful when tying webug into an existing web
// application. If you just want to run webug on a separate port that's
// configured by flags, use Config and Config.RegisterFlags.
func Register(ctx context.Context, conn *bmdb.Connection, mux *http.ServeMux, enableStrictConsistency bool) error {
	schema, err := conn.Reflect(ctx)
	if err != nil {
		return fmt.Errorf("could not get BMDB schema for webug: %w", err)
	}
	s := server{
		conn:              conn,
		schema:            schema,
		strictConsistency: enableStrictConsistency,
	}
	go s.schemaWorker(ctx)

	type route struct {
		pattern *regexp.Regexp
		handler func(w http.ResponseWriter, r *http.Request, args ...string)
	}

	routes := []route{
		{regexp.MustCompile(`^/$`), s.viewMachines},
		{regexp.MustCompile(`^/machine/([a-fA-F0-9\-]+)$`), s.viewMachineDetail},
		{regexp.MustCompile(`^/provider/([^/]+)/([^/]+)$`), s.viewProviderRedirect},
		{regexp.MustCompile(`^/session/([^/]+)`), s.viewSession},
	}

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		for _, route := range routes {
			match := route.pattern.FindStringSubmatch(r.URL.Path)
			if match == nil {
				continue
			}
			route.handler(w, r, match[1:]...)
			return
		}
		http.NotFound(w, r)
	})
	return nil
}

// Config describes the webug interface configuration. This should be embedded
// inside your component's Config object.
//
// To configure, either set values or call RegisterFlags before flag.Parse.
//
// To run after configuration, call Start.
type Config struct {
	// If set, start a webug interface on an HTTP listener bound to the given address.
	WebugListenAddress string

	// Enables strict consistency
	WebugDBFetchStrict bool
}

// RegisterFlags for webug interface.
func (c *Config) RegisterFlags() {
	flag.StringVar(&c.WebugListenAddress, "webug_listen_address", "", "Address to start BMDB webug on. If not set, webug will not be started.")
	flag.BoolVar(&c.WebugDBFetchStrict, "webug_dbfetch_strict", false, "Enables strict consistency")
}

// Start the webug interface in the foreground if enabled. The returned error
// will be either a configuration/connection error returned as soon as possible,
// or a context expiration error.
//
// The given context will be used for all connections from the webug interface to
// the given BMDB connection.
func (c *Config) Start(ctx context.Context, conn *bmdb.Connection) error {
	if c.WebugListenAddress == "" {
		return nil
	}
	mux := http.NewServeMux()
	if err := Register(ctx, conn, mux, c.WebugDBFetchStrict); err != nil {
		return err
	}

	klog.Infof("Webug listening at %s", c.WebugListenAddress)
	return http.ListenAndServe(c.WebugListenAddress, mux)
}
