package main

import (
	"flag"
	"math/rand"
	"net/http"
	"os"

	"gitlab.com/uafrica/go-utils/api"
	"gitlab.com/uafrica/go-utils/audit"
	"gitlab.com/uafrica/go-utils/errors"
	"gitlab.com/uafrica/go-utils/examples/core/app"
	"gitlab.com/uafrica/go-utils/examples/core/db"
	"gitlab.com/uafrica/go-utils/logger"
)

func main() {
	logger.SetGlobalLevel(logger.LevelDebug)
	logger.SetGlobalFormat(logger.NewConsole())

	localPort := flag.Int("port", 0, "Run with local HTTP server in this port (default: Run as lambda)")
	flag.Parse()

	api.New("uafrica-request-id", app.ApiRoutes()).
		WithStarter("db", db.Connector("core")).
		WithCheck("claims", claimsChecker{}).
		WithCheck("maintenance", maint{}).
		WithCheck("rate", rateLimiter{}).
		WithCORS(cors{}).
		WithAuditor(audit.File(os.Stdout)).
		WithLocalPort(localPort, app.QueueRoutes()). //if nil will still run as lambda
		Run()
}

type claimsChecker struct{}

type Claims struct {
	AccountID int64
	UserID    int64
}

func (claimsChecker) Check(ctx api.Context) (interface{}, error) {
	//then extract auth claim and check against the db ...
	claims := Claims{
		UserID:    1,
		AccountID: 13,
	}

	//set it in the API context (can be retrieved with api.Context.ClaimGet())
	ctx.ClaimSet("AccountID", claims.AccountID)
	ctx.ClaimSet("UserID", claims.UserID)

	//return the struct (can be retrieved with service.Context.Get()/Value())
	return claims, nil
}

type maint struct{}

//for maintenance mode, put a message in environment variable MAINTENANCE_MODE
//then than message will be displayed in the response. Clear the variable to
//proceed normal operation
func (m maint) Check(ctx api.Context) (interface{}, error) {
	msg := os.Getenv("MAINTENANCE_MODE")
	if msg != "" {
		return nil, errors.HTTP(http.StatusTeapot, errors.Errorf("maintenance mode"), "maintenance mode")
	}
	return nil, nil //not maint mode
}

type rateLimiter struct{}

func (r rateLimiter) Check(ctx api.Context) (interface{}, error) {
	if rand.Intn(10) < 2 {
		return nil, errors.Errorf("rate limited")
	}
	return nil, nil //not limited
}

type cors struct{}

func (cors) CORS() map[string]string {
	return map[string]string{
		"Access-Control-Allow-Origin":  "*",
		"Access-Control-Allow-Headers": "Content-Type, Accept",
	}
}