package middleware

import (
	"context"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/pingcap-inc/nexuscrm-api-host/hostruntime"
	apihostmiddleware "github.com/pingcap-inc/nexuscrm-api-host/middleware"
)

const DefaultPermCacheTTL = apihostmiddleware.DefaultPermCacheTTL

// PermissionCache adapts api-host's system/custom cache to backend wiring. It
// deliberately exposes invalidation and warm operations only; object and field
// authorization stays request-scoped in nexuscrm-permissions.
type PermissionCache struct {
	inner *apihostmiddleware.PermissionCache
}

func NewPermissionCache(ttl time.Duration) *PermissionCache {
	return &PermissionCache{inner: apihostmiddleware.NewPermissionCache(ttl)}
}

func (pc *PermissionCache) WarmUser(ctx context.Context, userID, profileID string, permSvc hostruntime.PermissionProvider, requestContext hostruntime.PermissionRequestContext) {
	if pc == nil || pc.inner == nil {
		return
	}
	pc.inner.WarmUser(ctx, userID, profileID, permSvc, requestContext)
}

func (pc *PermissionCache) WarmUserAsync(sourceCtx context.Context, requestID, userID, profileID string, permSvc hostruntime.PermissionProvider, requestContext hostruntime.PermissionRequestContext) {
	if pc == nil || pc.inner == nil {
		return
	}
	pc.inner.WarmUserAsync(sourceCtx, requestID, userID, profileID, permSvc, requestContext)
}

func (pc *PermissionCache) Invalidate() {
	if pc == nil || pc.inner == nil {
		return
	}
	pc.inner.Invalidate()
}

func (pc *PermissionCache) InvalidateUser(userID string) {
	if pc == nil || pc.inner == nil {
		return
	}
	pc.inner.InvalidateUser(userID)
}

func PermissionLoader(permSvc hostruntime.PermissionProvider, cache *PermissionCache, requestContext hostruntime.PermissionRequestContext) gin.HandlerFunc {
	var inner *apihostmiddleware.PermissionCache
	if cache != nil {
		inner = cache.inner
	}
	return apihostmiddleware.PermissionLoaderWithSessionContext(permSvc, inner, requestContext, backendSessionContextWriter{})
}

func RequirePermission(perm constants.Permission) gin.HandlerFunc {
	return apihostmiddleware.RequirePermissionWithSessionContext(backendSessionContextWriter{}, string(perm))
}

func RequireAnyPermission(perms ...constants.Permission) gin.HandlerFunc {
	keys := make([]string, 0, len(perms))
	for _, perm := range perms {
		keys = append(keys, string(perm))
	}
	return apihostmiddleware.RequireAnyPermissionWithSessionContext(backendSessionContextWriter{}, keys...)
}
