package persistence

import (
	"context"
	"errors"
	"strings"
)

// RequestPermissionSetAuthoringAdvance joins a compatible Records write to
// the canonical PermissionSet revision authority. It does not create another
// command: Records still owns its existing transaction and replay outcome.
// The caller must already hold the definition's parent lock, before child
// mutation. Repeated changed rows coalesce per root and SQL attempt.
func (authority *PermissionStateAuthority) RequestPermissionSetAuthoringAdvance(ctx context.Context, permissionSetID string) error {
	if err := authority.RequestAdvanceIfChanged(ctx, true); err != nil {
		return err
	}
	if strings.TrimSpace(permissionSetID) == "" {
		return abortPermissionStateTransaction(ctx, errors.New("permission authoring revision requires a root identity"))
	}
	attempt := permissionStateAttemptFromContext(ctx)
	attempt.mu.Lock()
	defer attempt.mu.Unlock()
	if attempt.authoringAdvanced[permissionSetID] {
		return nil
	}
	// Use the same root lock and sole revision writer as aggregate Save. The
	// repository deliberately has no direct-writer coordinator here: this
	// authority already requested Permission State on the owning transaction.
	repository := NewPermissionRepository(authority.transactions.db.DB())
	aggregate, found, err := repository.LockPermissionSetAuthoring(ctx, permissionSetID)
	if err != nil {
		return abortPermissionStateTransaction(ctx, err)
	}
	if !found {
		// A root cascade may already have removed/deleted the root. There is
		// no readable authoring snapshot to invalidate in that case.
		return nil
	}
	ownedCtx := withPermissionStateDirectWriter(ctx, "nexuscrm-persistence/perm_system.go#PermissionRepository.AdvancePermissionSetAuthoringRevision")
	if _, err := repository.AdvancePermissionSetAuthoringRevision(ownedCtx, permissionSetID, aggregate.Revision); err != nil {
		return abortPermissionStateTransaction(ctx, err)
	}
	if attempt.authoringAdvanced == nil {
		attempt.authoringAdvanced = make(map[string]bool)
	}
	attempt.authoringAdvanced[permissionSetID] = true
	return nil
}
