package middleware

import (
	"net/http"
	"strings"
)

// CORS returns a middleware that adds Cross-Origin Resource Sharing headers to
// every response and handles OPTIONS preflight requests. It is designed for the
// Veylant dashboard (React SPA) which calls the proxy from a different origin.
//
// allowedOrigins is the list of permitted origins (e.g. ["http://localhost:3000",
// "https://dashboard.veylant.ai"]). An empty list disables CORS (no headers added).
// Pass ["*"] to allow any origin (development only — never use in production).
func CORS(allowedOrigins []string) func(http.Handler) http.Handler {
	if len(allowedOrigins) == 0 {
		// No origins configured — identity middleware.
		return func(next http.Handler) http.Handler { return next }
	}

	originSet := make(map[string]struct{}, len(allowedOrigins))
	wildcard := false
	for _, o := range allowedOrigins {
		if o == "*" {
			wildcard = true
		}
		originSet[o] = struct{}{}
	}

	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			origin := r.Header.Get("Origin")

			// Only set CORS headers when the request carries an Origin header.
			if origin != "" {
				_, allowed := originSet[origin]
				if wildcard || allowed {
					w.Header().Set("Access-Control-Allow-Origin", origin)
					w.Header().Set("Access-Control-Allow-Credentials", "true")
					w.Header().Add("Vary", "Origin")
				}
			}

			// Handle preflight (OPTIONS) — respond 204 and do not forward.
			if r.Method == http.MethodOptions && origin != "" {
				requestedMethod := r.Header.Get("Access-Control-Request-Method")
				requestedHeaders := r.Header.Get("Access-Control-Request-Headers")

				if requestedMethod != "" {
					w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
					if requestedHeaders != "" {
						// Echo the requested headers back (normalised to title-case).
						w.Header().Set("Access-Control-Allow-Headers", strings.ToTitle(requestedHeaders))
					} else {
						w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Request-Id")
					}
					w.Header().Set("Access-Control-Max-Age", "86400") // 24 h preflight cache
					w.WriteHeader(http.StatusNoContent)
					return
				}
			}

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