<?php
/** Shared, fail-closed helpers for Elementor v4 global classes. */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

define( 'WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_ITEMS', 1000 );
define( 'WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_VARIANTS', 64 );
define( 'WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_PROPS', 100 );
define( 'WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_POSTS', 100 );
define( 'WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_CANDIDATES', 1000 );

/** @return WP_Error */
function wpagent_elementor_global_classes_unavailable_error(): WP_Error {
	return new WP_Error(
		'wpagent_elementor_global_classes_unavailable',
		__( 'Elementor v4 Global Classes sind in dieser Installation nicht verfügbar.', 'wp-agent-companion' ),
		array( 'status' => 409 )
	);
}

function wpagent_elementor_global_classes_feature_gate_active(): bool {
	if ( ! wpagent_elementor_available() || ! isset( \Elementor\Plugin::$instance->experiments ) || ! is_object( \Elementor\Plugin::$instance->experiments ) || ! method_exists( \Elementor\Plugin::$instance->experiments, 'is_feature_active' ) ) {
		return false;
	}
	try {
		return \Elementor\Plugin::$instance->experiments->is_feature_active( 'e_classes' )
			&& \Elementor\Plugin::$instance->experiments->is_feature_active( 'e_atomic_elements' );
	} catch ( Throwable ) {
		return false;
	}
}

function wpagent_elementor_global_classes_available(): bool {
	return wpagent_elementor_global_classes_feature_gate_active()
		&& class_exists( '\\Elementor\\Modules\\GlobalClasses\\Global_Classes_Repository' )
		&& class_exists( '\\Elementor\\Modules\\GlobalClasses\\Global_Classes_Parser' )
		&& class_exists( '\\Elementor\\Modules\\GlobalClasses\\Global_Classes_Relations' )
		&& method_exists( '\\Elementor\\Modules\\GlobalClasses\\Global_Classes_Relations', 'collect_class_ids_from_post' )
		&& class_exists( '\\Elementor\\Modules\\GlobalClasses\\Global_Class_Post_Type' )
		&& class_exists( '\\Elementor\\Modules\\GlobalClasses\\Utils\\Atomic_Elements_Utils' )
		&& class_exists( '\\Elementor\\Modules\\AtomicWidgets\\PropTypes\\Classes_Prop_Type' )
		&& class_exists( '\\Elementor\\Modules\\AtomicWidgets\\Styles\\Style_Schema' )
		&& class_exists( '\\Elementor\\Modules\\AtomicWidgets\\Styles\\Style_States' )
		&& isset( \Elementor\Plugin::$instance->kits_manager )
		&& is_object( \Elementor\Plugin::$instance->kits_manager )
		&& method_exists( \Elementor\Plugin::$instance->kits_manager, 'get_active_kit' );
}

/** @return object|WP_Error */
function wpagent_elementor_global_classes_kit() {
	if ( ! wpagent_elementor_global_classes_available() ) {
		return wpagent_elementor_global_classes_unavailable_error();
	}
	try {
		\Elementor\Modules\GlobalClasses\Global_Class_Post_Type::ensure_registered();
		if ( ! post_type_exists( \Elementor\Modules\GlobalClasses\Global_Class_Post_Type::CPT ) ) {
			return wpagent_elementor_global_classes_unavailable_error();
		}
		$kit = \Elementor\Plugin::$instance->kits_manager->get_active_kit();
	} catch ( Throwable ) {
		return wpagent_elementor_global_classes_unavailable_error();
	}
	if ( ! is_object( $kit ) || ! method_exists( $kit, 'get_main_id' ) ) {
		return wpagent_elementor_global_classes_unavailable_error();
	}
	return $kit;
}

/** @return object|WP_Error */
function wpagent_elementor_global_classes_repository() {
	$kit = wpagent_elementor_global_classes_kit();
	if ( is_wp_error( $kit ) ) {
		return $kit;
	}
	try {
		return \Elementor\Modules\GlobalClasses\Global_Classes_Repository::make( $kit )->set_preview( false );
	} catch ( Throwable ) {
		return new WP_Error(
			'wpagent_elementor_global_classes_read_failed',
			__( 'Elementor konnte das Repository der Global Classes nicht öffnen.', 'wp-agent-companion' ),
			array( 'status' => 500 )
		);
	}
}

/** @return string[] */
function wpagent_elementor_global_class_breakpoints(): array {
	$breakpoints = array( 'desktop' );
	try {
		$manager = \Elementor\Plugin::$instance->breakpoints ?? null;
		$active = is_object( $manager ) && method_exists( $manager, 'get_active_breakpoints' )
			? $manager->get_active_breakpoints()
			: array();
		foreach ( array_keys( is_array( $active ) ? $active : array() ) as $breakpoint ) {
			if ( is_string( $breakpoint ) && preg_match( '/^[a-z][a-z0-9_-]{0,63}$/', $breakpoint ) ) {
				$breakpoints[] = $breakpoint;
			}
		}
	} catch ( Throwable ) {
		return array( 'desktop' );
	}
	return array_values( array_unique( $breakpoints ) );
}

/**
 * @return array{kit_id:int,items:array<string,array<string,mixed>>,order:string[]}|WP_Error
 */
function wpagent_elementor_global_classes_snapshot() {
	$kit = wpagent_elementor_global_classes_kit();
	$repository = is_wp_error( $kit ) ? $kit : wpagent_elementor_global_classes_repository();
	if ( is_wp_error( $repository ) ) {
		return $repository;
	}
	try {
		$raw = $repository->all( true )->get();
	} catch ( Throwable ) {
		return new WP_Error(
			'wpagent_elementor_global_classes_read_failed',
			__( 'Elementor konnte die Global Classes nicht lesen.', 'wp-agent-companion' ),
			array( 'status' => 500 )
		);
	}
	$items = is_array( $raw['items'] ?? null ) ? $raw['items'] : null;
	$order = is_array( $raw['order'] ?? null ) && array_is_list( $raw['order'] ) ? $raw['order'] : null;
	if ( null === $items || null === $order || count( $items ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_ITEMS ) {
		return new WP_Error(
			'wpagent_elementor_global_classes_bad_state',
			__( 'Elementor lieferte einen ungültigen oder zu großen Global-Classes-Zustand.', 'wp-agent-companion' ),
			array( 'status' => 500 )
		);
	}
	foreach ( $order as $id ) {
		if ( ! is_string( $id ) || ! isset( $items[ $id ] ) || ! is_array( $items[ $id ] ) ) {
			return new WP_Error( 'wpagent_elementor_global_classes_bad_state', __( 'Elementors Global-Classes-Reihenfolge ist inkonsistent.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
	}
	if ( count( array_unique( $order ) ) !== count( $order ) || count( $order ) !== count( $items ) ) {
		return new WP_Error( 'wpagent_elementor_global_classes_bad_state', __( 'Elementors Global-Classes-Reihenfolge ist inkonsistent.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$encoded = wp_json_encode( array( 'items' => $items, 'order' => $order ) );
	if ( false === $encoded || strlen( $encoded ) > WPAGENT_ELEMENTOR_MAX_BYTES ) {
		return new WP_Error( 'wpagent_elementor_global_classes_payload_size', __( 'Der Global-Classes-Zustand ist für diesen sicheren Pfad zu groß.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	return array(
		'kit_id' => absint( $kit->get_main_id() ),
		'items'   => $items,
		'order'   => $order,
	);
}

/** @param array{items:array<string,array<string,mixed>>,order:string[]} $snapshot */
function wpagent_elementor_global_classes_hash( array $snapshot ): string {
	return hash(
		'sha256',
		(string) wp_json_encode(
			wpagent_elementor_canonicalize( array( 'items' => $snapshot['items'], 'order' => $snapshot['order'] ) ),
			JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
		)
	);
}

/** @param array{kit_id:int,items:array<string,array<string,mixed>>,order:string[]} $snapshot */
function wpagent_elementor_global_classes_state( array $snapshot ) {
	$classes = array();
	foreach ( $snapshot['order'] as $id ) {
		$class = wpagent_elementor_global_class_public_item( $snapshot['items'][ $id ] );
		if ( is_wp_error( $class ) ) {
			return $class;
		}
		$classes[] = $class;
	}
	return array(
		'kit_id'           => $snapshot['kit_id'],
		'elementor_version' => defined( 'ELEMENTOR_VERSION' ) ? (string) ELEMENTOR_VERSION : '',
		'breakpoints'      => wpagent_elementor_global_class_breakpoints(),
		'classes'          => $classes,
		'total'            => count( $classes ),
		'hash'             => wpagent_elementor_global_classes_hash( $snapshot ),
	);
}

/** @return true|WP_Error */
function wpagent_elementor_global_class_validate_public_props( $props ) {
	if ( ! is_array( $props ) || ( $props && array_is_list( $props ) ) || count( $props ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_PROPS ) {
		return new WP_Error( 'wpagent_elementor_global_class_bad_props', __( 'props muss ein begrenztes Objekt sein.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	return wpagent_elementor_validate_json_value( $props );
}

/** @param array<string,mixed> $item */
function wpagent_elementor_global_class_has_custom_css( array $item ): bool {
	foreach ( is_array( $item['variants'] ?? null ) ? $item['variants'] : array() as $variant ) {
		if ( is_array( $variant ) && array_key_exists( 'custom_css', $variant ) && null !== $variant['custom_css'] && '' !== $variant['custom_css'] ) {
			return true;
		}
	}
	return false;
}

/** @param array<string,mixed> $item @return array<string,mixed>|WP_Error */
function wpagent_elementor_global_class_public_item( array $item ) {
	$id = is_string( $item['id'] ?? null ) ? $item['id'] : '';
	$label = wpagent_elementor_global_class_label( $item['label'] ?? null );
	$variants = $item['variants'] ?? null;
	if ( ! preg_match( '/^[a-z][a-z0-9_-]{0,63}$/', $id ) || 'class' !== ( $item['type'] ?? null ) || is_wp_error( $label ) || ! is_array( $variants ) || ! array_is_list( $variants ) || count( $variants ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_VARIANTS ) {
		return new WP_Error( 'wpagent_elementor_global_classes_bad_state', __( 'Elementor lieferte eine nicht sicher veröffentlichbare Global Class.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$public_variants = array();
	$has_unsupported_custom_css = false;
	foreach ( $variants as $variant ) {
		if ( ! is_array( $variant ) || array_is_list( $variant ) || array_diff( array_keys( $variant ), array( 'meta', 'props', 'custom_css' ) ) || ! is_array( $variant['meta'] ?? null ) || array_is_list( $variant['meta'] ) || array_diff( array_keys( $variant['meta'] ), array( 'breakpoint', 'state' ) ) ) {
			return new WP_Error( 'wpagent_elementor_global_classes_bad_state', __( 'Elementor lieferte eine nicht sicher veröffentlichbare Global-Class-Variante.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$meta = $variant['meta'];
		if ( ! is_string( $meta['breakpoint'] ?? null ) || strlen( $meta['breakpoint'] ) > 64 || ( ! is_string( $meta['state'] ) && null !== $meta['state'] ) || ( is_string( $meta['state'] ) && strlen( $meta['state'] ) > 64 ) ) {
			return new WP_Error( 'wpagent_elementor_global_classes_bad_state', __( 'Elementor lieferte eine ungültige Global-Class-Metadatenstruktur.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$props = wpagent_elementor_json_document_output( $variant['props'] ?? null, 'wpagent_elementor_global_class_validate_public_props' );
		if ( is_wp_error( $props ) ) {
			return $props;
		}
		$has_unsupported_custom_css = $has_unsupported_custom_css || ( array_key_exists( 'custom_css', $variant ) && null !== $variant['custom_css'] && '' !== $variant['custom_css'] );
		$public_variants[] = array( 'meta' => $meta, 'props' => $props );
	}
	return array(
		'id'                         => $id,
		'type'                       => 'class',
		'label'                      => $label,
		'sync_to_v3'                 => (bool) ( $item['sync_to_v3'] ?? false ),
		'variants'                   => $public_variants,
		'has_unsupported_custom_css' => $has_unsupported_custom_css,
	);
}

/** @return true|WP_Error */
function wpagent_elementor_global_classes_require_capability( string $capability ) {
	if ( ! current_user_can( 'manage_options' ) || ! current_user_can( $capability ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	return true;
}

/** @return string|WP_Error */
function wpagent_elementor_global_class_hash_input( array $input ) {
	$hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $hash ) ) {
		return new WP_Error( 'wpagent_elementor_global_classes_bad_hash', __( 'expected_hash muss ein vollständiger SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $hash;
}

/** @return string|WP_Error */
function wpagent_elementor_global_class_label( $value ) {
	if ( ! is_string( $value ) || strlen( $value ) > 200 ) {
		return new WP_Error( 'wpagent_elementor_global_class_bad_label', __( 'Der Name der Global Class ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$label = sanitize_text_field( $value );
	if ( $label !== $value || strlen( $label ) < 2 || strlen( $label ) > 50 || ! preg_match( '/^(?!--)(?!-[0-9])(?![0-9])[A-Za-z0-9_-]+$/', $label ) || 'container' === strtolower( $label ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_bad_label', __( 'Der Name der Global Class muss 2-50 sichere CSS-Klassenzeichen enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $label;
}

/** @return array<int,array<string,mixed>>|WP_Error */
function wpagent_elementor_global_class_variants( $value, string $class_id, string $label ) {
	if ( ! is_array( $value ) || ! array_is_list( $value ) || ! $value || count( $value ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_VARIANTS ) {
		return new WP_Error( 'wpagent_elementor_global_class_bad_variants', __( 'variants muss eine Liste mit 1-64 Einträgen sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$breakpoints = wpagent_elementor_global_class_breakpoints();
	try {
		$style_schema = \Elementor\Modules\AtomicWidgets\Styles\Style_Schema::get();
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_parse_failed', __( 'Elementor konnte sein natives Style-Schema nicht laden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	if ( ! is_array( $style_schema ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_parse_failed', __( 'Elementor konnte sein natives Style-Schema nicht laden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$seen = array();
	$has_base = false;
	foreach ( $value as $variant ) {
		if ( ! is_array( $variant ) || array_is_list( $variant ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_variants', __( 'Jede Global-Class-Variante muss ein Objekt sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( array_key_exists( 'custom_css', $variant ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_custom_css', __( 'Rohes CSS ist für Global Classes über diesen sicheren Pfad nicht erlaubt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( array_diff( array_keys( $variant ), array( 'meta', 'props' ) ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_variants', __( 'Eine Global-Class-Variante enthält unbekannte Felder.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$meta = $variant['meta'] ?? null;
		$props = $variant['props'] ?? null;
		if ( wpagent_builder_json_document_is_envelope( $props ) ) {
			$props = wpagent_builder_json_document_to_value(
				$props,
				WPAGENT_ELEMENTOR_MAX_BYTES,
				static function ( $candidate ) {
					if ( ! is_array( $candidate ) || ( $candidate && array_is_list( $candidate ) ) || count( $candidate ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_PROPS ) {
						return new WP_Error( 'wpagent_elementor_global_class_bad_props', __( 'props muss ein begrenztes Objekt sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
					}
					return wpagent_elementor_validate_json_value( $candidate );
				},
				'wpagent_elementor_global_class'
			);
			if ( is_wp_error( $props ) ) {
				return $props;
			}
		}
		if ( ! is_array( $meta ) || array_is_list( $meta ) || array_diff( array_keys( $meta ), array( 'breakpoint', 'state' ) ) || ! array_key_exists( 'breakpoint', $meta ) || ! array_key_exists( 'state', $meta ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_variants', __( 'meta benötigt ausschließlich breakpoint und state.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$breakpoint = $meta['breakpoint'];
		if ( ! is_string( $breakpoint ) || ! in_array( $breakpoint, $breakpoints, true ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_breakpoint', __( 'Die Global Class verwendet einen nicht aktiven Elementor-Breakpoint.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state = $meta['state'];
		if ( ! class_exists( '\\Elementor\\Modules\\AtomicWidgets\\Styles\\Style_States' ) || ! \Elementor\Modules\AtomicWidgets\Styles\Style_States::is_valid_state( $state ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_state', __( 'Die Global Class verwendet einen unbekannten Zustand.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$key = $breakpoint . ':' . ( null === $state ? 'normal' : $state );
		if ( isset( $seen[ $key ] ) ) {
			return new WP_Error( 'wpagent_elementor_global_class_duplicate_variant', __( 'Breakpoint und Zustand dürfen nur einmal vorkommen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$seen[ $key ] = true;
		$has_base = $has_base || ( 'desktop' === $breakpoint && null === $state );
		if ( ! is_array( $props ) || array_is_list( $props ) || ! $props || count( $props ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_PROPS ) {
			return new WP_Error( 'wpagent_elementor_global_class_bad_props', __( 'props muss ein begrenztes, nicht leeres Objekt sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		foreach ( array_keys( $props ) as $prop_name ) {
			if ( ! is_string( $prop_name ) || ! array_key_exists( $prop_name, $style_schema ) ) {
				return new WP_Error( 'wpagent_elementor_global_class_bad_props', __( 'Die Global Class enthält eine unbekannte Elementor-Style-Eigenschaft.', 'wp-agent-companion' ), array( 'status' => 400, 'property' => is_scalar( $prop_name ) ? (string) $prop_name : '' ) );
			}
		}
		$valid = wpagent_elementor_validate_json_value( $props );
		if ( is_wp_error( $valid ) ) {
			return $valid;
		}
	}
	if ( ! $has_base ) {
		return new WP_Error( 'wpagent_elementor_global_class_missing_base', __( 'Jede Global Class benötigt eine normale Desktop-Basisvariante.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$item = array( 'id' => $class_id, 'type' => 'class', 'label' => $label, 'variants' => $value );
	try {
		$result = \Elementor\Modules\GlobalClasses\Global_Classes_Parser::make()->parse_items( array( $class_id => $item ) );
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_parse_failed', __( 'Elementor konnte die Global Class nicht validieren.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	if ( ! is_object( $result ) || ! method_exists( $result, 'is_valid' ) || ! $result->is_valid() ) {
		return new WP_Error( 'wpagent_elementor_global_class_bad_props', __( 'Mindestens eine Global-Class-Eigenschaft entspricht nicht Elementors nativem Schema.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$parsed = $result->unwrap()[ $class_id ] ?? null;
	if ( ! is_array( $parsed ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_parse_failed', __( 'Elementor konnte die Global Class nicht normalisieren.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	foreach ( $parsed['variants'] as &$variant ) {
		if ( null === ( $variant['custom_css'] ?? null ) ) {
			unset( $variant['custom_css'] );
		}
	}
	unset( $variant );
	if ( wpagent_elementor_canonicalize( $parsed ) !== wpagent_elementor_canonicalize( $item ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_sanitized', __( 'Elementor müsste die Global Class verändern. Die Anfrage wurde deshalb abgelehnt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $parsed['variants'];
}

/** @return int[]|WP_Error */
function wpagent_elementor_global_class_meta_candidates( string $class_id ) {
	global $wpdb;

	$needle = '%' . $wpdb->esc_like( '"' . $class_id . '"' ) . '%';
	$limit = WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_CANDIDATES + 1;
	$wpdb->last_error = '';
	$post_ids = $wpdb->get_col(
		$wpdb->prepare(
			"SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value LIKE %s ORDER BY post_id ASC LIMIT %d",
			'_elementor_data',
			$needle,
			$limit
		)
	);
	if ( '' !== $wpdb->last_error || ! is_array( $post_ids ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'WordPress konnte die Elementor-Dokumente für die Verwendungsprüfung nicht lesen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$post_ids = array_values( array_unique( array_filter( array_map( 'absint', $post_ids ) ) ) );
	if ( count( $post_ids ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_CANDIDATES ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_candidates_limit', __( 'Zu viele Elementor-Dokumente enthalten mögliche Verweise auf diese Global Class.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	return $post_ids;
}

/** @return bool|WP_Error */
function wpagent_elementor_global_class_meta_contains( int $post_id, string $class_id ) {
	$post = $post_id > 0 ? get_post( $post_id ) : null;
	if ( ! $post || 'revision' === $post->post_type ) {
		return false;
	}
	$raw = get_post_meta( $post_id, '_elementor_data', true );
	if ( ! is_string( $raw ) || '' === $raw ) {
		return false;
	}
	if ( strlen( $raw ) > WPAGENT_ELEMENTOR_MAX_BYTES ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_payload_size', __( 'Ein Elementor-Dokument ist für die sichere Verwendungsprüfung zu groß.', 'wp-agent-companion' ), array( 'status' => 413, 'post_id' => $post_id ) );
	}
	$data = json_decode( $raw, true, WPAGENT_ELEMENTOR_MAX_DEPTH, JSON_INVALID_UTF8_SUBSTITUTE );
	if ( JSON_ERROR_NONE !== json_last_error() || ! is_array( $data ) ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_bad_document', __( 'Ein mögliches Elementor-Dokument enthält ungültige JSON-Daten.', 'wp-agent-companion' ), array( 'status' => 500, 'post_id' => $post_id ) );
	}
	try {
		$relations = ( new \Elementor\Modules\GlobalClasses\Global_Classes_Relations() )->set_preview( false );
		$ids = $relations->collect_class_ids_from_post( $post_id, array( $class_id ) );
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'Elementor konnte ein mögliches Dokument nicht für die Verwendungsprüfung lesen.', 'wp-agent-companion' ), array( 'status' => 500, 'post_id' => $post_id ) );
	}
	return is_array( $ids ) && in_array( $class_id, $ids, true );
}

/** @return int[]|WP_Error */
function wpagent_elementor_global_class_usage( string $class_id ) {
	try {
		$post_ids = ( new \Elementor\Modules\GlobalClasses\Global_Classes_Relations() )->set_preview( false )->get_posts_by_style( $class_id );
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'Elementor konnte die Verwendung der Global Class nicht bestimmen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$post_ids = array_values( array_unique( array_filter( array_map( 'absint', is_array( $post_ids ) ? $post_ids : array() ) ) ) );
	$meta_candidates = wpagent_elementor_global_class_meta_candidates( $class_id );
	if ( is_wp_error( $meta_candidates ) ) {
		return $meta_candidates;
	}
	$post_ids = array_values( array_unique( array_merge( $post_ids, $meta_candidates ) ) );
	if ( count( $post_ids ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_CANDIDATES ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_candidates_limit', __( 'Zu viele Elementor-Dokumente müssen für die Verwendungsprüfung untersucht werden.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	$usage = array();
	foreach ( $post_ids as $post_id ) {
		$meta_contains = wpagent_elementor_global_class_meta_contains( $post_id, $class_id );
		if ( is_wp_error( $meta_contains ) ) {
			return $meta_contains;
		}
		if ( $meta_contains ) {
			$usage[] = $post_id;
		}
	}
	$post_ids = $usage;
	sort( $post_ids, SORT_NUMERIC );
	if ( count( $post_ids ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_POSTS ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_limit', __( 'Die Global Class wird in zu vielen Dokumenten verwendet, um sie über diesen sicheren Pfad zu löschen.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	return $post_ids;
}

/**
 * Rebuild Elementor's relation metadata from the document source before a provider deletion.
 *
 * Elementor's repository cleanup trusts the reverse index. A missing or stale reverse index
 * would otherwise leave verified raw document references behind. This only repairs metadata;
 * it never changes _elementor_data.
 *
 * @param int[] $expected_usage
 * @return true|WP_Error
 */
function wpagent_elementor_global_class_repair_relations( string $class_id, array $expected_usage ) {
	$expected_usage = array_values( array_unique( array_filter( array_map( 'absint', $expected_usage ) ) ) );
	sort( $expected_usage, SORT_NUMERIC );
	try {
		$relations = ( new \Elementor\Modules\GlobalClasses\Global_Classes_Relations() )->set_preview( false );
		$indexed = $relations->get_posts_by_style( $class_id );
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'Elementor konnte den Global-Class-Index nicht reparieren.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$indexed = array_values( array_unique( array_filter( array_map( 'absint', is_array( $indexed ) ? $indexed : array() ) ) ) );
	$meta_candidates = wpagent_elementor_global_class_meta_candidates( $class_id );
	if ( is_wp_error( $meta_candidates ) ) {
		return $meta_candidates;
	}
	$candidates = array_values( array_unique( array_merge( $indexed, $meta_candidates, $expected_usage ) ) );
	if ( count( $candidates ) > WPAGENT_ELEMENTOR_GLOBAL_CLASSES_MAX_USAGE_CANDIDATES ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_candidates_limit', __( 'Zu viele Elementor-Dokumente müssen für die Verwendungsprüfung repariert werden.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	foreach ( $candidates as $post_id ) {
		try {
			if ( ! get_post( $post_id ) || 'revision' === get_post_type( $post_id ) ) {
				$relations->set_styles_for_post( $post_id, array() );
				continue;
			}
			$relations->get_styles_by_post( $post_id );
		} catch ( Throwable ) {
			return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'Elementor konnte eine Global-Class-Beziehung nicht reparieren.', 'wp-agent-companion' ), array( 'status' => 500, 'post_id' => $post_id ) );
		}
	}
	try {
		$repaired_index = $relations->get_posts_by_style( $class_id );
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_failed', __( 'Elementor konnte den reparierten Global-Class-Index nicht lesen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$repaired_index = array_values( array_unique( array_filter( array_map( 'absint', is_array( $repaired_index ) ? $repaired_index : array() ) ) ) );
	sort( $repaired_index, SORT_NUMERIC );
	if ( $expected_usage !== $repaired_index ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_conflict', __( 'Elementors reparierter Global-Class-Index stimmt nicht mit den bestätigten Dokumenten überein.', 'wp-agent-companion' ), array( 'status' => 409, 'affected_post_ids' => $repaired_index ) );
	}
	$verified_usage = wpagent_elementor_global_class_usage( $class_id );
	if ( is_wp_error( $verified_usage ) ) {
		return $verified_usage;
	}
	if ( $expected_usage !== $verified_usage ) {
		return new WP_Error( 'wpagent_elementor_global_class_usage_conflict', __( 'Die Global-Class-Verwendung änderte sich während der Indexreparatur.', 'wp-agent-companion' ), array( 'status' => 409, 'affected_post_ids' => $verified_usage ) );
	}
	return true;
}
