package metadata

import (
	"context"
	"fmt"

	apperrors "github.com/nexuscrm/kernel/pkg/errors"
)

type componentAdmissionKind string

const componentAdmissionKindPageLayout componentAdmissionKind = "page layout"

type componentAdmissionRestore func() error

type componentAdmissionRequest struct {
	kind         componentAdmissionKind
	componentID  string
	errorContext string
	admit        func(context.Context) (componentAdmissionRestore, error)
}

func (ms *MetadataService) admitComponentWrite(ctx context.Context, request componentAdmissionRequest) (componentAdmissionRestore, error) {
	if request.admit == nil {
		return nil, request.wrapError(apperrors.NewInternalError("component write admission did not provide an admit callback", nil))
	}

	restore, err := request.admit(ctx)
	if err != nil {
		return nil, request.wrapError(err)
	}
	if restore == nil {
		return nil, request.wrapError(request.missingRollbackRestoreError())
	}
	return restore, nil
}

func (request componentAdmissionRequest) missingRollbackRestoreError() error {
	if request.kind == componentAdmissionKindPageLayout {
		return apperrors.NewInternalError("field layout admission did not return a rollback restore", nil)
	}
	return apperrors.NewInternalError("component write admission did not return a rollback restore", nil)
}

func (request componentAdmissionRequest) wrapError(err error) error {
	context := request.errorContext
	if context == "" {
		context = fmt.Sprintf("failed to admit %s", request.kind)
		if request.componentID != "" {
			context = fmt.Sprintf("%s %s", context, request.componentID)
		}
	}
	return fmt.Errorf("%s: %w", context, err)
}
