package restapi

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// withCORS returns a gin middleware that handles browser CORS preflight and
// attaches Access-Control-Allow-* response headers when the request's Origin
// is on the configured allow-list. Origins are compared exactly: scheme,
// host, and port must match. An empty allow-list disables the middleware —
// requests pass through untouched. Requests without an Origin header always
// pass through, the middleware only acts when a browser actually asks.
//
// The middleware mounts before the anti-abuse layer so OPTIONS preflights
// do not count against the rate-limit buckets for the eventual real call.
func withCORS(allowedOrigins []string) gin.HandlerFunc {
	allowed := make(map[string]struct{}, len(allowedOrigins))
	for _, origin := range allowedOrigins {
		allowed[origin] = struct{}{}
	}
	if len(allowed) == 0 {
		return func(c *gin.Context) { c.Next() }
	}
	return func(c *gin.Context) {
		origin := c.GetHeader("Origin")
		if origin == "" {
			c.Next()
			return
		}
		if _, ok := allowed[origin]; !ok {
			c.Next()
			return
		}
		c.Header("Access-Control-Allow-Origin", origin)
		c.Header("Vary", "Origin")
		c.Header("Access-Control-Allow-Credentials", "true")
		if c.Request.Method == http.MethodOptions {
			c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
			if reqHeaders := c.GetHeader("Access-Control-Request-Headers"); reqHeaders != "" {
				c.Header("Access-Control-Allow-Headers", reqHeaders)
			} else {
				c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
			}
			c.Header("Access-Control-Max-Age", "3600")
			c.AbortWithStatus(http.StatusNoContent)
			return
		}
		c.Next()
	}
}
