package httputil

import (
	"net/http"
	"slices"
	"strings"

	"kjol/appenv"
)

// CorsConfig configures CorsMiddleware. AllowedDomains is consulted only outside
// development (in development every origin is allowed). BundleVersion, when set,
// is called to stamp the X-Bundle-Version header on /api/ responses; leave it nil
// to skip that header.
type CorsConfig struct {
	AllowedDomains []string
	BundleVersion  func() string
}

// CorsMiddleware returns middleware that applies CORS headers to all requests.
// It is a constructor (not the middleware itself) so the app can inject its
// allowed domains and bundle-version source without this package importing app
// config or handlers.
func CorsMiddleware(cfg CorsConfig) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			origin := r.Header.Get("Origin")

			if appenv.Environment != appenv.EnvTypeDevelopment {
				if len(cfg.AllowedDomains) > 0 && slices.Contains(cfg.AllowedDomains, origin) {
					w.Header().Set("Access-Control-Allow-Origin", origin)
				}
			} else {
				w.Header().Set("Access-Control-Allow-Origin", "*")
			}

			w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
			w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
			w.Header().Set("Access-Control-Expose-Headers", "X-Bundle-Version")
			w.Header().Set("Access-Control-Allow-Credentials", "true")

			if cfg.BundleVersion != nil {
				if version := cfg.BundleVersion(); version != "" && strings.HasPrefix(r.URL.Path, "/api/") {
					w.Header().Set("X-Bundle-Version", version)
				}
			}

			// Handle preflight OPTIONS request
			if r.Method == http.MethodOptions {
				w.WriteHeader(http.StatusNoContent)
				return
			}

			next.ServeHTTP(w, r)
		})
	}
}
