package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	api "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api/grpc"
	"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/grpc"
	"google.golang.org/grpc/backoff"
	"google.golang.org/grpc/credentials/insecure"
)

type ProxyClientApp struct {
	LogLevel                 kernel.LogLevel `yaml:"log_level" env:"BH_LOG_LEVEL" env-default:"0" yaml-default:"0"`
	Port                     int             `yaml:"port" env:"PROXY_CLIENT_PORT"`
	AccessControlAllowOrigin string          `yaml:"access_control_allow_origin", env:"PROXY_CLIENT_CORS_ORIGIN`
	Endpoints                struct {
		Catalog string `yaml:"catalog" env:"CATALOG_ENDPOINT"`
	} `yaml:"endpoints" env:"PROXY_CLIENT_SERVICES"`
}

func (app *ProxyClientApp) Start(ctx context.Context) error {
	grpcMux := runtime.NewServeMux()
	err := api.RegisterCatalogHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Catalog, []grpc.DialOption{
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithConnectParams(grpc.ConnectParams{
			Backoff: backoff.Config{
				MaxDelay: time.Second * 3,
			},
			MinConnectTimeout: time.Second,
		}),
	})
	if err != nil {
		return err
	}

	kernel.TraceLog.Printf("%+v", app)

	httpServer := &http.Server{
		Addr:              fmt.Sprintf("0.0.0.0:%d", app.Port),
		ReadHeaderTimeout: time.Second,
		Handler: http.StripPrefix("/api", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			kernel.TraceLog.Printf("{ \"Client\": \"%s\", \"Path\":\"%s\", \"User-Agent\":\"%s\" } ", r.RemoteAddr, r.URL, r.UserAgent())
			// TODO: pull the allowed origin host names from the config file
			w.Header().Set("Access-Control-Allow-Origin", app.AccessControlAllowOrigin)
			grpcMux.ServeHTTP(w, r)
		})),
	}

	kernel.InfoLog.Printf("Starting HTTP proxy @ %q", httpServer.Addr)

	return httpServer.ListenAndServe()
}

func (app *ProxyClientApp) OnStop(ctx context.Context) {
}

func (app *ProxyClientApp) GetLogLevel() kernel.LogLevel { return app.LogLevel }

func main() {
	kernel.Run(context.Background(), &ProxyClientApp{
		LogLevel: kernel.LevelTrace,
		Port:     80,
	})
}
