package common

import (
	"context"
	"flag"
	"fmt"
	"net/http"
	"os"
	"runtime"
	"sort"

	"cloud.google.com/go/logging"
	"go.skia.org/infra/go/cleanup"
	"go.skia.org/infra/go/ephemeral_storage"
	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/sklog/cloudlogging"
	"go.skia.org/infra/go/sklog/sklogimpl"
	"golang.org/x/oauth2/google"
)

// FlagSet is the flag.FlagSet we use to parse command line flags.
// It defaults to flag.CommandLine, but can be over-ridden with
// FlagSetOpt.
var FlagSet *flag.FlagSet = flag.CommandLine

// Opt represents the initialization parameters for a single init service, where
// services are Prometheus, etc.
//
// Initializing flags, metrics, and logging, with two options for metrics, and
// another option for logging is complicated by the fact that some
// initializations are order dependent, and each app may want a different
// subset of options. The solution is to encapsulate each optional piece,
// prom, etc, into its own Opt, and then initialize each Opt in the
// right order.
//
// Not only are the Opts order dependent but initialization needs to be broken
// into two phases, preinit() and init().
//
// The desired order for all Opts is:
//
//	0 - base
//	1 - cloudlogging
//	3 - prometheus
//	4 - slog
//
// Construct the Opts that are desired and pass them to common.InitWith(), i.e.:
//
//	common.InitWith(
//		"skiaperf",
//		common.PrometheusOpt(promPort),
//		common.CloudLoggingOpt(),
//	)
type Opt interface {
	// order is the sort order that Opts are executed in.
	order() int
	preinit(appName string) error
	init(appName string) error
}

// optSlice is a utility type for sorting Opts by order().
type optSlice []Opt

func (p optSlice) Len() int           { return len(p) }
func (p optSlice) Less(i, j int) bool { return p[i].order() < p[j].order() }
func (p optSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// baseInitOpt is an Opt that is always constructed internally, added to any
// Opts passed into InitWith() and always runs first.
//
// Implements Opt.
type baseInitOpt struct{}

func (b *baseInitOpt) preinit(appName string) error {
	return FlagSet.Parse(os.Args[1:])
}

func (b *baseInitOpt) init(appName string) error {
	// Start logging ephemeral disk usage periodically.
	go ephemeral_storage.Start(context.Background())

	// Log all flags and their values.
	FlagSet.VisitAll(func(f *flag.Flag) {
		sklog.Infof("Flags: --%s=%v", f.Name, f.Value)
	})

	// Log all environment variables.
	for _, env := range os.Environ() {
		sklog.Infof("Env: %s", env)
	}

	// Use all cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Enable signal handling for the cleanup package.
	cleanup.Enable()

	// Record UID and GID.
	sklog.Infof("Running as %d:%d", os.Getuid(), os.Getgid())

	return nil
}

func (b *baseInitOpt) order() int {
	return 0
}

// cloudLoggingInitOpt implements Opt for cloud logging.
type cloudLoggingInitOpt struct {
	projectID string
	local     *bool
}

// CloudLogging creates an Opt to initialize cloud logging when passed to InitWith().
//
// Uses the instance service account for auth.
// No cloud logging is done if local is true.
func CloudLogging(local *bool, projectID string) Opt {
	return &cloudLoggingInitOpt{
		projectID: projectID,
		local:     local,
	}
}

func (o *cloudLoggingInitOpt) preinit(appName string) error {
	ctx := context.Background()
	if *o.local {
		return nil
	}
	ts, err := google.DefaultTokenSource(ctx, logging.WriteScope)
	if err != nil {
		return fmt.Errorf("problem getting authenticated token source: %s", err)
	}
	// Try to grab a token right away to confirm auth is set up correctly.
	_, err = ts.Token()
	if err != nil {
		return err
	}
	hostname, err := os.Hostname()
	if err != nil {
		return err
	}
	l, err := cloudlogging.New(ctx, o.projectID, appName, ts, map[string]string{"hostname": hostname})
	if err != nil {
		return err
	}
	sklogimpl.SetLogger(l)
	return nil
}

func (o *cloudLoggingInitOpt) init(appName string) error {
	return nil
}

func (o *cloudLoggingInitOpt) order() int {
	return 1
}

// metricsLoggingInitOpt implements Opt for logging with metrics.
type metricsLoggingInitOpt struct {
}

func (o *metricsLoggingInitOpt) preinit(appName string) error {
	return nil
}

func (o *metricsLoggingInitOpt) init(appName string) error {
	severities := sklogimpl.AllSeverities()
	metricLookup := make([]metrics2.Counter, len(severities))
	for _, sev := range severities {
		metricLookup[sev] = metrics2.GetCounter("num_log_lines", map[string]string{"level": sev.String()})
	}
	metricsCallback := func(severity sklogimpl.Severity) {
		metricLookup[severity].Inc(1)
	}
	sklogimpl.SetMetricsCallback(metricsCallback)
	return nil
}

func (o *metricsLoggingInitOpt) order() int {
	return 2
}

// promInitOpt implments Opt for Prometheus.
type promInitOpt struct {
	port *string
}

// PrometheusOpt creates an Opt to initialize Prometheus metrics when passed to InitWith().
func PrometheusOpt(port *string) Opt {
	return &promInitOpt{
		port: port,
	}
}

func (o *promInitOpt) preinit(appName string) error {
	metrics2.InitPrometheus(*o.port)
	return nil
}

var defaultServeMux http.ServeMux

func (o *promInitOpt) init(appName string) error {
	// App uptime.
	_ = metrics2.NewLiveness("uptime", nil)

	// Prometheus client loads "expvar" which automatically registers
	// "/debug/vars" in the default http handler, which exposes potentially
	// secret information. Since we can't register a new handler for
	// "/debug/vars" because that causes the http lib to panic, we need to
	// replace http.DefaultServeMux with a fresh handler, and since we do this
	// after init()'s have been called, we won't get the /debug/vars handler.
	// http://b/241539244
	http.DefaultServeMux = &defaultServeMux
	http.HandleFunc("/debug/vars", http.NotFound)
	return nil
}

func (o *promInitOpt) order() int {
	return 3
}

// flagSetInitOpt implments Opt for flag.FlagSet.
type flagSetInitOpt struct {
	flagSet *flag.FlagSet
}

// FlagSetOpt allows changing the flag.FlagSet used to parse command line arguments.
//
// If this Opt is not used then flag.CommandLine is used as the default.
func FlagSetOpt(flagSet *flag.FlagSet) Opt {
	return &flagSetInitOpt{
		flagSet: flagSet,
	}
}

func (o *flagSetInitOpt) preinit(appName string) error {
	FlagSet = o.flagSet
	return nil
}

func (o *flagSetInitOpt) init(appName string) error {
	return nil
}

func (o *flagSetInitOpt) order() int {
	return -1
}

// InitWith takes Opt's and initializes each service, where services are Prometheus, etc.
func InitWith(appName string, opts ...Opt) error {

	// Add baseInitOpt and metricsLoggingInitOpt.
	opts = append(opts, &baseInitOpt{}, &metricsLoggingInitOpt{})

	// Sort by order().
	sort.Sort(optSlice(opts))

	// Check for duplicate Opts.
	for i := 0; i < len(opts)-1; i++ {
		if opts[i].order() == opts[i+1].order() {
			return fmt.Errorf("only one of each type of Opt can be used")
		}
	}

	// Run all preinit's.
	for _, o := range opts {
		if err := o.preinit(appName); err != nil {
			return err
		}
	}

	// Run all init's.
	for _, o := range opts {
		if err := o.init(appName); err != nil {
			return err
		}
	}
	sklog.Flush()
	return nil
}

// InitWithMust calls InitWith and fails fatally if an error is encountered.
func InitWithMust(appName string, opts ...Opt) {
	if err := InitWith(appName, opts...); err != nil {
		sklog.Fatalf("Failed to initialize: %s", err)
	}
}
