package permissions

import (
	"context"
	"strings"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

const userDeleteLifecycleWriteCapability = constants.RecordWriteValidationUserDeleteLifecycle

func schemaBlocksGenericDelete(schema *models.ObjectMetadata) bool {
	if schema == nil || schema.AccessPolicy == nil || schema.AccessPolicy.WriteValidation == nil {
		return false
	}
	for _, validator := range schema.AccessPolicy.WriteValidation.Validators {
		if !strings.EqualFold(strings.TrimSpace(validator.Phase), "before_delete") {
			continue
		}
		if strings.EqualFold(strings.TrimSpace(validator.Capability), constants.RecordWriteValidationUserDeleteLifecycle) {
			return true
		}
	}
	return false
}

// CheckUserDeactivationPermissionWithUser preserves the existing Delete User
// entitlement for the supported offboarding lifecycle without advertising
// generic DELETE User as a runnable operation.
func (ps *PermissionService) CheckUserDeactivationPermissionWithUser(ctx context.Context, user *models.UserSession) bool {
	return ps.checkStoredObjectPermissionWithSetupGate(ctx, constants.TableUser, constants.PermDelete, user)
}

// CheckObjectDeactivationPermissionWithUser exposes the lifecycle-specific
// offboarding capability separately from generic object deleteability.
func (ps *PermissionService) CheckObjectDeactivationPermissionWithUser(ctx context.Context, objectAPIName string, user *models.UserSession) bool {
	if ps == nil || ps.metadata == nil || user == nil || !strings.EqualFold(strings.TrimSpace(objectAPIName), constants.TableUser) {
		return false
	}
	if !schemaBlocksGenericDelete(ps.metadata.GetSchema(ctx, objectAPIName)) {
		return false
	}
	return ps.CheckUserDeactivationPermissionWithUser(ctx, user)
}

func (ps *PermissionService) checkStoredObjectPermissionWithSetupGate(ctx context.Context, objectAPIName string, operation string, user *models.UserSession) bool {
	if ps == nil || ps.metadata == nil || user == nil {
		return false
	}
	requiredSystemPerms := ps.requiredSystemPermissionsForSetupObject(ctx, objectAPIName, operation)
	if len(requiredSystemPerms) > 0 && !ps.hasAnySystemPermission(ctx, user, requiredSystemPerms) {
		return false
	}
	if ps.HasSuperUserCapability(ctx, user) {
		return true
	}
	perm, err := ps.loadStoredEffectiveObjectPermission(ctx, user, objectAPIName)
	if err != nil || perm == nil {
		return false
	}
	switch operation {
	case constants.PermRead:
		return perm.PermissionsRead
	case constants.PermCreate:
		return perm.PermissionsCreate
	case constants.PermEdit:
		return perm.PermissionsEdit
	case constants.PermDelete:
		return perm.PermissionsDelete
	case constants.PermViewAllRecords:
		return perm.PermissionsViewAllRecords
	case constants.PermModifyAllRecords:
		return perm.PermissionsModifyAllRecords
	default:
		return false
	}
}

func (ps *PermissionService) loadStoredEffectiveObjectPermission(ctx context.Context, user *models.UserSession, objectAPIName string) (*models.ObjectPermissions, error) {
	if ps == nil || ps.repo == nil || user == nil {
		return nil, nil
	}
	return ps.repo.LoadEffectiveObjectPermission(ctx, user, objectAPIName)
}
