package hostctx

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/constants"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/models"
)

const (
	ContextKeyUser              = "user"
	ContextKeySystemPermissions = "system_permissions"
)

// CurrentUser extracts the cross-repo user session shape from gin context.
// Hosts that store a different internal auth type should pass an explicit
// provider to the handler constructor instead of relying on this default.
func CurrentUser(c *gin.Context) *models.UserSession {
	if c == nil {
		return nil
	}
	user, ok := c.Get(ContextKeyUser)
	if !ok {
		return nil
	}
	switch v := user.(type) {
	case *models.UserSession:
		return v
	case models.UserSession:
		return &v
	default:
		return nil
	}
}

func MustCurrentUser(c *gin.Context) *models.UserSession {
	user := CurrentUser(c)
	if user == nil {
		panic("hostctx.MustCurrentUser: authenticated user not installed")
	}
	return user
}

func SystemPermissions(c *gin.Context) map[string]bool {
	if c == nil {
		return nil
	}
	value, ok := c.Get(ContextKeySystemPermissions)
	if !ok {
		return nil
	}
	perms, ok := value.(map[string]bool)
	if !ok {
		return nil
	}
	return perms
}

// RequirePermission is a tiny local test/receiver gate. Production NexusCRM may
// still use its own middleware before mounting these handlers.
func RequirePermission(perm constants.Permission) gin.HandlerFunc {
	return func(c *gin.Context) {
		if _, exists := c.Get(ContextKeyUser); !exists {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "USER_NOT_FOUND"})
			return
		}
		perms := SystemPermissions(c)
		if perms == nil {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "PERMISSIONS_NOT_LOADED"})
			return
		}
		if !perms[string(perm)] {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
				"error":      "MISSING_PERMISSION",
				"permission": perm,
			})
			return
		}
		c.Next()
	}
}
