package middleware

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

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

// Timeout middleware wraps the context with a deadline
// MOD-P1-007: Fixed goroutine leak by ensuring cleanup on timeout
func Timeout(timeout time.Duration) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Create a context with timeout
		ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
		defer cancel() // Always cancel to free resources

		// Replace the request context
		c.Request = c.Request.WithContext(ctx)

		// Create a channel to signal completion of the handler
		done := make(chan struct{})

		// MOD-P1-007: Launch handler in goroutine with proper cleanup
		go func() {
			defer func() {
				// Ensure channel is closed even if handler panics
				close(done)
			}()
			c.Next()
		}()

		select {
		case <-done:
			// Handler completed within timeout
			return
		case <-ctx.Done():
			// Timeout exceeded
			// MOD-P1-007: Abort the request and ensure handler chain stops
			// Note: We abort immediately without waiting for goroutine to avoid race conditions.
			// The context cancellation (via defer cancel()) will signal the handler to stop.
			// If handler tries to write after timeout, it's the handler's responsibility to check context.
			c.AbortWithStatusJSON(http.StatusGatewayTimeout, gin.H{
				"error":   "Request Timeout",
				"message": "The request took too long to process.",
			})
			// Return immediately - context cancellation will stop the handler goroutine
			// The defer cancel() ensures resources are cleaned up
			return
		}
	}
}
