package serverruntime

import (
	"context"
	"fmt"
	"sync"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	apihostdialect "github.com/pingcap-inc/nexuscrm-api-host/dialect"
	"github.com/pingcap-inc/nexuscrm-api-host/dialecttransport"
)

type systemPermissionCatalog interface {
	ListSystemPermissions(ctx context.Context) ([]models.SystemPermission, error)
}

// permissionResolverFromSystemCatalog binds the gin-free dialect door's
// declaration-time Gate validation to the host's authoritative row-backed
// permission catalog. It is lazy so an app-blind boot or an all-GateNone
// partition does not pay a DB read, but the first gated route validates against
// the live catalog and fails closed on catalog load errors.
func permissionResolverFromSystemCatalog(catalog systemPermissionCatalog) dialecttransport.PermissionResolver {
	var once sync.Once
	var provided map[constants.Permission]struct{}
	var loadErr error

	return func(permission apihostdialect.Permission) bool {
		if permission == "" {
			return false
		}

		once.Do(func() {
			if catalog == nil {
				loadErr = fmt.Errorf("system permission catalog is not configured")
				return
			}

			rows, err := catalog.ListSystemPermissions(context.Background())
			if err != nil {
				loadErr = err
				return
			}

			provided = make(map[constants.Permission]struct{}, len(rows))
			for _, row := range rows {
				if !row.IsActive {
					continue
				}
				if row.APIName == "" {
					continue
				}
				provided[constants.Permission(row.APIName)] = struct{}{}
			}
		})

		if loadErr != nil {
			panic(fmt.Sprintf("dialecttransport: failed to load system permission catalog for route gate validation: %v", loadErr))
		}

		_, ok := provided[constants.Permission(permission)]
		return ok
	}
}
