package rest

import (
	"errors"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/nexuscrm/backend/internal/host/adapters/apihost/rest/requestctx"
	"github.com/nexuscrm/kernel/pkg/apierr"
	"github.com/nexuscrm/shared/pkg/models"
)

// GetUserFromContext extracts the authenticated user from gin.Context
func GetUserFromContext(c *gin.Context) *models.UserSession {
	return requestctx.GetUserFromContext(c)
}

// MustGetUser extracts the authenticated user from the request context.
// Panics if user is nil — only use in routes protected by requireAuth middleware.
func MustGetUser(c *gin.Context) *models.UserSession {
	return requestctx.MustGetUser(c)
}

// RespondAppError sends a standardised JSON error using pkg/apierr
// It delegates to the GlobalErrorHandler by appending the error to the context.
func RespondAppError(c *gin.Context, err error) {
	// In TestMode, render generic API errors immediately so unit tests can verify
	// status without the middleware. Neutral engine-condition errors are owned by the
	// active API dialect's projector (installed at route-group mount); they fall through
	// to GlobalErrorHandler, which fails closed if a dialect did not project. App-blind
	// L0 no longer projects domain errors into Salesforce v63 wire skin.
	if gin.Mode() == gin.TestMode {
		var apiErr *apierr.Error
		if errors.As(err, &apiErr) {
			c.JSON(apiErr.Status, apiErr)
			return
		}
	}
	// Let GlobalErrorHandler middleware handle it
	c.Error(err)
}

// RequireParam validates that a URL parameter is not empty. Returns the value if
// valid, or empty string and sends a neutral 400 error. The active API dialect's
// projector (installed at route-group mount) owns any wire-specific error skin;
// app-blind L0 emits only a neutral envelope.
func RequireParam(c *gin.Context, paramName string) (string, bool) {
	value := c.Param(paramName)
	if value == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": paramName + " is required"})
		return "", false
	}
	return value, true
}
