package permissions

import (
	"context"
	"errors"
	"strings"

	appErrors "github.com/nexuscrm/kernel/pkg/errors"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/models"
	permissionsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/effectivepermissionsv1"
)

// ContractPermissionAdmin exposes permission administration through the neutral
// contract seam. It deliberately keeps transactions, PermissionSet locking, and
// cache invalidation inside AdminService.
type ContractPermissionAdmin struct {
	permissions *PermissionService
	admin       *AdminService
}

func NewContractPermissionAdmin(permissions *PermissionService, admin *AdminService) *ContractPermissionAdmin {
	return &ContractPermissionAdmin{permissions: permissions, admin: admin}
}

func (p *ContractPermissionAdmin) ListObjectPermissions(ctx context.Context, user *models.UserSession) ([]contract.ObjectAccessProjection, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	perms, err := p.permissions.ListEffectiveObjectPermissionsForUser(ctx, user.ID, user.ProfileID)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	return objectAccessProjections(ctx, p.permissions, user, perms), nil
}

func (p *ContractPermissionAdmin) ListSystemPermissionCatalog(ctx context.Context) ([]contract.CapabilityCatalogEntry, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	allPerms, err := p.permissions.ListSystemPermissions(ctx)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	out := make([]contract.CapabilityCatalogEntry, 0, len(allPerms))
	for _, sp := range allPerms {
		out = append(out, contract.CapabilityCatalogEntry{
			APIName:            sp.APIName,
			Label:              sp.Label,
			Category:           sp.Category,
			Description:        derefString(sp.Description),
			RequiresCapability: derefString(sp.RequiresPermission),
		})
	}
	return out, nil
}

func (p *ContractPermissionAdmin) GetPermissionSetSystemGrants(ctx context.Context, permSetID string) (map[string]bool, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	grants, err := p.permissions.GetPermissionSetGrants(ctx, permSetID)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	return grants, nil
}

func (p *ContractPermissionAdmin) SavePermissionSetSystemGrants(ctx context.Context, permSetID string, grants map[string]bool, actor *models.UserSession) error {
	if p == nil || p.admin == nil {
		return permissionAdminServerError("permission admin service is not configured")
	}
	return permissionAdminMutationError(p.admin.SaveSystemGrants(ctx, permSetID, grants, actor))
}

func (p *ContractPermissionAdmin) EffectivePermissions(ctx context.Context, viewer *models.UserSession, targetUserID string) (result *contract.EffectivePermissionsResult, resultErr error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	if viewer == nil {
		return nil, permissionAdminForbiddenError("You do not have permission to view another user's effective permissions.")
	}

	target := targetUserID
	if target == "" {
		target = viewer.ID
	}
	targetScope := "self"
	if target != viewer.ID {
		targetScope = "other"
	}
	totalPhase := startPermissionReadPhase(ctx, permissionReadOperationEffectivePermissions, "total", targetScope)
	defer func() {
		rows := 0
		if result != nil {
			rows = len(result.SystemPermissions) + len(result.CustomPermissions) +
				len(result.ObjectPermissions) + len(result.FieldPermissions) +
				len(result.ApplicationPermissions) + len(result.NavigationPermissions) +
				len(result.RecordTypePermissions)
		}
		if recovered := recover(); recovered != nil {
			totalPhase.completeWithOutcome(rows, "panic")
			panic(recovered)
		}
		totalPhase.complete(rows, resultErr)
	}()

	targetProfileID := viewer.ProfileID
	if target != viewer.ID {
		_, err := runPermissionReadPhase(
			ctx,
			permissionReadOperationEffectivePermissions,
			"target_authorization",
			targetScope,
			func(bool) int { return 0 },
			func() (bool, error) {
				if !p.permissions.CheckSystemPermission(ctx, viewer, string(constants.PermViewSetup)) {
					return false, permissionAdminForbiddenError("You do not have permission to view another user's effective permissions.")
				}
				return true, nil
			},
		)
		if err != nil {
			return nil, err
		}

		profileID, err := runPermissionReadPhase(
			ctx,
			permissionReadOperationEffectivePermissions,
			"target_profile",
			targetScope,
			func(value string) int {
				if value == "" {
					return 0
				}
				return 1
			},
			func() (string, error) { return p.permissions.GetUserProfileID(ctx, target) },
		)
		if err != nil {
			return nil, permissionAdminReadError(err)
		}
		targetProfileID = profileID
		// Viewer authorization and target evaluation are different subjects.
		// Preserve the viewer's request cache and isolate all target sections.
		ctx = withFreshAccessInputCache(ctx)
	}

	sysPerms, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"system_permissions",
		targetScope,
		func(value map[string]bool) int { return len(value) },
		func() (map[string]bool, error) {
			return p.permissions.GetEffectiveSystemPermissions(ctx, target, targetProfileID)
		},
	)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	recordTypePermissions := map[string]bool(nil)
	if !constants.HasSuperUserCapability(sysPerms) {
		recordTypePermissions, err = runPermissionReadPhase(
			ctx,
			permissionReadOperationEffectivePermissions,
			"record_type_permissions",
			targetScope,
			func(value map[string]bool) int { return len(value) },
			func() (map[string]bool, error) {
				values, err := p.permissions.GetEffectiveRecordTypeVisibilities(
					ctx, target, targetProfileID,
				)
				if err != nil {
					return nil, err
				}
				result := make(map[string]bool, len(values))
				for recordTypeID, visibility := range values {
					result[recordTypeID] = visibility.IsVisible
				}
				return result, nil
			},
		)
		if err != nil {
			return nil, permissionAdminReadError(err)
		}
	}
	customPerms, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"custom_permissions",
		targetScope,
		func(value map[string]bool) int { return len(value) },
		func() (map[string]bool, error) {
			return p.permissions.GetEffectiveCustomPermissions(ctx, target, targetProfileID)
		},
	)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	objPerms, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"object_permissions",
		targetScope,
		func(value []models.ObjectPermissions) int { return len(value) },
		func() ([]models.ObjectPermissions, error) {
			return p.permissions.ListEffectiveObjectPermissionsForUser(ctx, target, targetProfileID)
		},
	)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	fieldPerms, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"field_permissions",
		targetScope,
		func(value []contract.FieldAccessProjection) int { return len(value) },
		func() ([]contract.FieldAccessProjection, error) {
			return p.permissions.projectEffectiveFieldAccessForUser(ctx, target, targetProfileID, nil)
		},
	)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	appPermissions, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"application_permissions",
		targetScope,
		func(value map[string]models.ProfileAppVisibility) int { return len(value) },
		func() (map[string]models.ProfileAppVisibility, error) {
			return p.permissions.GetEffectiveAppVisibilities(ctx, target, targetProfileID)
		},
	)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	navigationPermissions, err := runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"navigation_permissions",
		targetScope,
		func(value map[string]models.ProfileTabSetting) int { return len(value) },
		func() (map[string]models.ProfileTabSetting, error) {
			return p.permissions.GetEffectiveTabSettings(ctx, target, targetProfileID)
		},
	)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	result, resultErr = runPermissionReadPhase(
		ctx,
		permissionReadOperationEffectivePermissions,
		"projection",
		targetScope,
		func(value *contract.EffectivePermissionsResult) int {
			if value == nil {
				return 0
			}
			return len(value.ObjectPermissions) + len(value.FieldPermissions) +
				len(value.ApplicationPermissions) + len(value.NavigationPermissions) +
				len(value.RecordTypePermissions)
		},
		func() (*contract.EffectivePermissionsResult, error) {
			return &contract.EffectivePermissionsResult{
				SystemPermissions: sysPerms,
				CustomPermissions: customPerms,
				ObjectPermissions: objectAccessProjections(ctx, p.permissions, &models.UserSession{ID: target, ProfileID: targetProfileID}, objPerms),
				FieldPermissions:  fieldPerms,
				ApplicationPermissions: applicationAccessProjections(
					appPermissions,
				),
				NavigationPermissions: navigationAccessProjections(
					navigationPermissions,
				),
				RecordTypePermissions: recordTypePermissions,
			}, nil
		},
	)
	return result, resultErr
}

// EffectivePermissionsSelected computes only the explicitly requested neutral
// sections and Catalog resource types. It shares every decision owner with the
// complete projection; selection changes work performed and response scope,
// never permission semantics.
func (p *ContractPermissionAdmin) EffectivePermissionsSelected(
	ctx context.Context,
	viewer *models.UserSession,
	targetUserID string,
	selection permissionsemantic.Selection,
) (result *contract.EffectivePermissionsResult, resultErr error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	if viewer == nil || len(selection.Sections) == 0 {
		return nil, permissionAdminForbiddenError("You do not have permission to view another user's effective permissions.")
	}

	target := targetUserID
	if target == "" {
		target = viewer.ID
	}
	targetScope := "self"
	if target != viewer.ID {
		targetScope = "other"
	}
	totalPhase := startPermissionReadPhase(
		ctx, permissionReadOperationEffectivePermissions, "selected_total", targetScope,
	)
	defer func() {
		rows := 0
		if result != nil {
			rows = len(result.SystemPermissions) + len(result.CustomPermissions) +
				len(result.ObjectPermissions) + len(result.FieldPermissions) +
				len(result.ApplicationPermissions) + len(result.NavigationPermissions) +
				len(result.RecordTypePermissions)
		}
		if recovered := recover(); recovered != nil {
			totalPhase.completeWithOutcome(rows, "panic")
			panic(recovered)
		}
		totalPhase.complete(rows, resultErr)
	}()

	targetProfileID := viewer.ProfileID
	if target != viewer.ID {
		_, err := runPermissionReadPhase(
			ctx,
			permissionReadOperationEffectivePermissions,
			"selected_target_authorization",
			targetScope,
			func(bool) int { return 0 },
			func() (bool, error) {
				if !p.permissions.CheckSystemPermission(
					ctx, viewer, string(constants.PermViewSetup),
				) {
					return false, permissionAdminForbiddenError(
						"You do not have permission to view another user's effective permissions.",
					)
				}
				return true, nil
			},
		)
		if err != nil {
			return nil, err
		}
		profileID, err := runPermissionReadPhase(
			ctx,
			permissionReadOperationEffectivePermissions,
			"selected_target_profile",
			targetScope,
			func(value string) int {
				if value == "" {
					return 0
				}
				return 1
			},
			func() (string, error) { return p.permissions.GetUserProfileID(ctx, target) },
		)
		if err != nil {
			return nil, permissionAdminReadError(err)
		}
		targetProfileID = profileID
		// As in the complete projection, target facts must never populate or
		// consume the viewer-bound cache installed by Runtime ingress.
		ctx = withFreshAccessInputCache(ctx)
	}

	ctx = WithAccessInputCache(ctx)
	result = &contract.EffectivePermissionsResult{}
	if selection.Requests(permissionsemantic.SectionSystemPermissions) {
		result.SystemPermissions, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_system_permissions", targetScope,
			func(value map[string]bool) int { return len(value) },
			func() (map[string]bool, error) {
				return p.permissions.GetEffectiveSystemPermissions(ctx, target, targetProfileID)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminServerError(resultErr.Error())
		}
	}
	if selection.Requests(permissionsemantic.SectionCustomPermissions) {
		result.CustomPermissions, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_custom_permissions", targetScope,
			func(value map[string]bool) int { return len(value) },
			func() (map[string]bool, error) {
				return p.permissions.GetEffectiveCustomPermissions(ctx, target, targetProfileID)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminServerError(resultErr.Error())
		}
	}
	if selection.Requests(permissionsemantic.SectionObjectPermissions) {
		var rows []models.ObjectPermissions
		rows, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_object_permissions", targetScope,
			func(value []models.ObjectPermissions) int { return len(value) },
			func() ([]models.ObjectPermissions, error) {
				return p.permissions.ListEffectiveObjectPermissionsForUserResources(
					ctx, target, targetProfileID, selection.ResourceTypes,
				)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminServerError(resultErr.Error())
		}
		result.ObjectPermissions = objectAccessProjections(
			ctx, p.permissions,
			&models.UserSession{ID: target, ProfileID: targetProfileID},
			rows,
		)
	}
	if selection.Requests(permissionsemantic.SectionFieldPermissions) {
		var rows []contract.FieldAccessProjection
		rows, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_field_permissions", targetScope,
			func(value []contract.FieldAccessProjection) int { return len(value) },
			func() ([]contract.FieldAccessProjection, error) {
				return p.permissions.projectEffectiveFieldAccessForUser(
					ctx, target, targetProfileID, selection.ResourceTypes,
				)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminReadError(resultErr)
		}
		result.FieldPermissions = rows
	}
	if selection.Requests(permissionsemantic.SectionApplicationPermissions) {
		var rows map[string]models.ProfileAppVisibility
		rows, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_application_permissions", targetScope,
			func(value map[string]models.ProfileAppVisibility) int { return len(value) },
			func() (map[string]models.ProfileAppVisibility, error) {
				return p.permissions.GetEffectiveAppVisibilities(ctx, target, targetProfileID)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminReadError(resultErr)
		}
		result.ApplicationPermissions = applicationAccessProjections(rows)
	}
	if selection.Requests(permissionsemantic.SectionNavigationPermissions) {
		var rows map[string]models.ProfileTabSetting
		rows, resultErr = runPermissionReadPhase(
			ctx, permissionReadOperationEffectivePermissions, "selected_navigation_permissions", targetScope,
			func(value map[string]models.ProfileTabSetting) int { return len(value) },
			func() (map[string]models.ProfileTabSetting, error) {
				return p.permissions.GetEffectiveTabSettings(ctx, target, targetProfileID)
			},
		)
		if resultErr != nil {
			return nil, permissionAdminReadError(resultErr)
		}
		result.NavigationPermissions = navigationAccessProjections(rows)
	}
	if selection.Requests(permissionsemantic.SectionRecordTypePermissions) {
		user := &models.UserSession{ID: target, ProfileID: targetProfileID}
		if !p.permissions.HasSuperUserCapability(ctx, user) {
			var rows map[string]models.PermissionSetRecordTypeVisibility
			rows, resultErr = runPermissionReadPhase(
				ctx, permissionReadOperationEffectivePermissions, "selected_record_type_permissions", targetScope,
				func(value map[string]models.PermissionSetRecordTypeVisibility) int { return len(value) },
				func() (map[string]models.PermissionSetRecordTypeVisibility, error) {
					return p.permissions.GetEffectiveRecordTypeVisibilities(
						ctx, target, targetProfileID,
					)
				},
			)
			if resultErr != nil {
				return nil, permissionAdminReadError(resultErr)
			}
			result.RecordTypePermissions = make(map[string]bool, len(rows))
			for recordTypeID, visibility := range rows {
				result.RecordTypePermissions[recordTypeID] = visibility.IsVisible
			}
		}
	}
	return result, nil
}

func applicationAccessProjections(
	permissions map[string]models.ProfileAppVisibility,
) []contract.ApplicationAccessProjection {
	result := make([]contract.ApplicationAccessProjection, 0, len(permissions))
	for applicationID, permission := range permissions {
		result = append(result, contract.ApplicationAccessProjection{
			ApplicationID: applicationID,
			CanView:       permission.IsVisible,
			IsDefault:     permission.IsDefault,
		})
	}
	return result
}

func navigationAccessProjections(
	permissions map[string]models.ProfileTabSetting,
) []contract.NavigationAccessProjection {
	result := make([]contract.NavigationAccessProjection, 0, len(permissions))
	for navigationKey, permission := range permissions {
		visibility := strings.ToLower(strings.TrimSpace(permission.Visibility))
		result = append(result, contract.NavigationAccessProjection{
			NavigationKey: navigationKey,
			CanView:       visibility == "defaulton" || visibility == "visible",
		})
	}
	return result
}

func (p *ContractPermissionAdmin) ListRecordTypeCatalog(ctx context.Context) ([]contract.PermissionRecordTypeCatalogEntry, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	recordTypes, err := p.permissions.ListRecordTypeCatalog(ctx)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	out := make([]contract.PermissionRecordTypeCatalogEntry, 0, len(recordTypes))
	for _, rt := range recordTypes {
		out = append(out, contract.PermissionRecordTypeCatalogEntry{
			RecordTypeID:  rt.RecordTypeID,
			ObjectAPIName: rt.ObjectAPIName,
			Name:          rt.Name,
			Label:         rt.Label,
			IsActive:      rt.IsActive,
			IsMaster:      rt.IsMaster,
		})
	}
	return out, nil
}

func (p *ContractPermissionAdmin) GetPermissionSetRecordTypeGrants(ctx context.Context, permSetID string) ([]contract.RecordTypeVisibilityGrant, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	grants, err := p.permissions.GetPermissionSetRecordTypeGrants(ctx, permSetID)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	out := make([]contract.RecordTypeVisibilityGrant, 0, len(grants))
	for _, g := range grants {
		out = append(out, contract.RecordTypeVisibilityGrant{
			RecordTypeID: g.RecordTypeID,
			IsVisible:    g.IsVisible,
		})
	}
	return out, nil
}

func (p *ContractPermissionAdmin) SavePermissionSetRecordTypeGrants(ctx context.Context, permSetID string, grants map[string]contract.PermissionRecordTypeGrantChange) error {
	if p == nil || p.admin == nil {
		return permissionAdminServerError("permission admin service is not configured")
	}
	changes := make(map[string]RecordTypeGrantChange, len(grants))
	for id, grant := range grants {
		changes[id] = RecordTypeGrantChange{IsVisible: grant.IsVisible}
	}
	return permissionAdminMutationError(p.admin.SaveRecordTypeGrants(ctx, permSetID, changes))
}

func (p *ContractPermissionAdmin) ListCustomPermissionCatalog(ctx context.Context) ([]contract.CustomCapabilityCatalogEntry, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	perms, err := p.permissions.ListCustomPermissions(ctx)
	if err != nil {
		return nil, permissionAdminServerError(err.Error())
	}
	out := make([]contract.CustomCapabilityCatalogEntry, 0, len(perms))
	for _, cp := range perms {
		out = append(out, contract.CustomCapabilityCatalogEntry{
			ID:      cp.ID,
			APIName: cp.APIName,
			Label:   cp.Label,
		})
	}
	return out, nil
}

func (p *ContractPermissionAdmin) GetPermissionSetCustomPermissionGrants(ctx context.Context, permSetID string) ([]contract.CustomCapabilityGrant, error) {
	if p == nil || p.permissions == nil {
		return nil, permissionAdminServerError("permission service is not configured")
	}
	grants, err := p.permissions.GetPermissionSetCustomPermGrants(ctx, permSetID)
	if err != nil {
		return nil, permissionAdminReadError(err)
	}
	out := make([]contract.CustomCapabilityGrant, 0, len(grants))
	for _, g := range grants {
		out = append(out, contract.CustomCapabilityGrant{CapabilityID: g.CustomPermissionID})
	}
	return out, nil
}

func (p *ContractPermissionAdmin) SavePermissionSetCustomPermissionGrants(ctx context.Context, permSetID string, grants map[string]bool) error {
	if p == nil || p.admin == nil {
		return permissionAdminServerError("permission admin service is not configured")
	}
	return permissionAdminMutationError(p.admin.SaveCustomPermissionGrants(ctx, permSetID, grants))
}

// objectAccessProjections maps engine object-permission rows to the neutral
// contract projection field-by-field. The engine keeps []models.ObjectPermissions
// internally; only the contract boundary returns neutral projections.
func objectAccessProjections(ctx context.Context, ps *PermissionService, user *models.UserSession, rows []models.ObjectPermissions) []contract.ObjectAccessProjection {
	out := make([]contract.ObjectAccessProjection, 0, len(rows))
	for _, r := range rows {
		out = append(out, contract.ObjectAccessProjection{
			ResourceType:  r.SobjectType,
			CanRead:       r.PermissionsRead,
			CanCreate:     r.PermissionsCreate,
			CanEdit:       r.PermissionsEdit,
			CanDelete:     r.PermissionsDelete,
			CanDeactivate: ps.CheckObjectDeactivationPermissionWithUser(ctx, r.SobjectType, user),
			CanViewAll:    r.PermissionsViewAllRecords,
			CanModifyAll:  r.PermissionsModifyAllRecords,
		})
	}
	return out
}

func derefString(s *string) string {
	if s == nil {
		return ""
	}
	return *s
}

func permissionAdminReadError(err error) error {
	if err == nil {
		return nil
	}
	if appErrors.IsInternal(err) {
		return permissionAdminSanitizedInternalError("An internal server error occurred. Contact your system administrator.")
	}
	if appErrors.IsNotFound(err) {
		return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorNotFound, Message: err.Error()}
	}
	if appErrors.IsPermission(err) {
		return permissionAdminForbiddenError(err.Error())
	}
	return permissionAdminSanitizedInternalError("An internal server error occurred. Contact your system administrator.")
}

func permissionAdminMutationError(err error) error {
	if err == nil {
		return nil
	}
	if appErrors.IsInternal(err) {
		return permissionAdminServerError(err.Error())
	}
	if IsPermissionSetNotFound(err) {
		return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorNotFound, Message: err.Error()}
	}
	var forbidden *appErrors.ForbiddenError
	if errors.As(err, &forbidden) {
		return permissionAdminForbiddenError(err.Error())
	}
	if IsApplyError(err) {
		return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorInvalidField, Message: err.Error()}
	}
	return permissionAdminServerError(err.Error())
}

func permissionAdminServerError(message string) error {
	return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorServer, Message: message}
}

func permissionAdminSanitizedInternalError(message string) error {
	return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorSanitizedInternal, Message: message}
}

func permissionAdminForbiddenError(message string) error {
	return &contract.PermissionAdminError{Kind: contract.PermissionAdminErrorForbidden, Message: message}
}

var _ contract.PermissionAdmin = (*ContractPermissionAdmin)(nil)
