package permission

import (
	"context"
	"time"

	"gateway/internal/svc"
	"gateway/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type ReloadPolicyLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewReloadPolicyLogic returns the policy reload logic.
func NewReloadPolicyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ReloadPolicyLogic {
	return &ReloadPolicyLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// ReloadPolicy forces a Casbin LoadPolicy on this pod and broadcasts a
// Pub/Sub event so other pods follow. Empty tenant_id reloads the
// caller's tenant; "*" reloads every tenant.
func (l *ReloadPolicyLogic) ReloadPolicy(req *types.PolicyReloadReq) (*types.PolicyReloadData, error) {
	if l.svcCtx.PermissionRBAC == nil {
		return nil, errb.SysNotImplemented("casbin enforcer not configured")
	}
	tenant := req.TenantID
	if tenant == "" {
		actor, err := ActorFromContext(l.ctx)
		if err != nil {
			return nil, errb.AuthUnauthorized(err.Error()).WithCause(err)
		}
		tenant = actor.TenantID
	}
	if tenant == "*" {
		if err := l.svcCtx.PermissionRBAC.LoadAllPolicies(l.ctx); err != nil {
			return nil, err
		}
	} else if err := l.svcCtx.PermissionRBAC.LoadPolicy(l.ctx, tenant); err != nil {
		return nil, err
	}
	if err := l.svcCtx.PermissionRBAC.BroadcastReload(l.ctx, tenant); err != nil {
		l.Errorf("permission: broadcast reload tenant=%s: %v", tenant, err)
	}
	return &types.PolicyReloadData{
		Tenant: tenant,
		TS:     time.Now().UnixMilli(),
	}, nil
}
