package server

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

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/httpz"
)

const (
	readHeaderTimeout = 10 * time.Second
	idleTimeout       = 1 * time.Minute
)

type server struct {
	listenerGracePeriod time.Duration
	shutdownGracePeriod time.Duration
	// CORS
	allowedOrigins []string
	// Authorization
	provider *oidcProvider
	// Payload decode handler
	decodeHandler http.Handler
}

func (s *server) Run(ctx context.Context, listener net.Listener) error {
	srv := &http.Server{
		Handler:           http.HandlerFunc(s.handle),
		ReadHeaderTimeout: readHeaderTimeout,
		IdleTimeout:       idleTimeout,
	}
	return httpz.RunServer(ctx, srv, listener, s.listenerGracePeriod, s.shutdownGracePeriod)
}

func (s *server) handle(w http.ResponseWriter, r *http.Request) {
	// Setup CORS
	header := w.Header()
	header[httpz.AccessControlAllowOriginHeader] = s.allowedOrigins
	header[httpz.AccessControlAllowCredentialsHeader] = []string{"true"}
	header[httpz.AccessControlAllowHeadersHeader] = []string{httpz.AuthorizationHeader, httpz.ContentTypeHeader, temporalNamespaceHeaderName}

	if r.Method == http.MethodOptions {
		// Handling CORS preflight requests
		return
	}

	// Authorization
	if err := s.provider.authorize(r); err != nil {
		http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return
	}

	// handle decoding payload
	s.decodeHandler.ServeHTTP(w, r)
}
