<?php
/** Private, create-only compensation for failed portable form migrations. */

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

/** @param mixed $value @return mixed */
function wpagent_form_migration_compensation_canonicalize( $value ) {
	if ( is_object( $value ) ) {
		$value = get_object_vars( $value );
	}
	if ( ! is_array( $value ) ) {
		return $value;
	}
	if ( ! array_is_list( $value ) ) {
		ksort( $value, SORT_STRING );
	}
	foreach ( $value as $key => $item ) {
		$value[ $key ] = wpagent_form_migration_compensation_canonicalize( $item );
	}
	return $value;
}

/** @param mixed $state @return string|WP_Error */
function wpagent_form_migration_compensation_hash( $state ) {
	$encoded = wp_json_encode( wpagent_form_migration_compensation_canonicalize( $state ), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
	if ( false === $encoded || strlen( $encoded ) > 5 * MB_IN_BYTES ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Zustand der neu angelegten Zielkopie konnte nicht sicher gesichert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return hash( 'sha256', $encoded );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_form_migration_compensation_wp_post_state( int $form_id, string $post_type ): array|WP_Error {
	$post = get_post( $form_id, ARRAY_A );
	if ( ! is_array( $post ) || $post_type !== (string) ( $post['post_type'] ?? '' ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_not_found', __( 'Die neu angelegte Zielkopie konnte nicht vollständig gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	global $wpdb;
	$wpdb->last_error = '';
	$meta = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = %d ORDER BY meta_id ASC", $form_id ), ARRAY_A );
	if ( '' !== (string) $wpdb->last_error || ! is_array( $meta ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Zustand der neu angelegten Zielkopie konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return array( 'post' => $post, 'meta' => $meta );
}

/** @return array<int,array<string,mixed>>|WP_Error */
function wpagent_form_migration_compensation_wpforms_entry_rows( string $table, string $column, array $ids ): array|WP_Error {
	$ids = array_values( array_unique( array_filter( array_map( 'absint', $ids ) ) ) );
	if ( ! $ids ) {
		return array();
	}
	global $wpdb;
	$wpdb->last_error = '';
	$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );
	$sql          = "SELECT * FROM {$table} WHERE {$column} IN ({$placeholders}) ORDER BY id ASC";
	$rows         = $wpdb->get_results( $wpdb->prepare( $sql, ...$ids ), ARRAY_A );
	if ( '' !== (string) $wpdb->last_error || ! is_array( $rows ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige WPForms-Eintragszustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return $rows;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_form_migration_compensation_wpforms_entries_state( int $form_id ): array|WP_Error {
	$entries = function_exists( 'wpforms' ) ? wpforms()->obj( 'entry' ) : null;
	$meta    = function_exists( 'wpforms' ) ? wpforms()->obj( 'entry_meta' ) : null;
	$fields  = function_exists( 'wpforms' ) ? wpforms()->obj( 'entry_fields' ) : null;
	if ( ! $entries && ! $meta && ! $fields ) {
		// WPForms Lite has no entry storage, so its native form delete cannot
		// remove a concurrent submission.
		return array( 'entry_storage' => false );
	}
	if ( ! $entries || ! $meta || ! $fields ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der WPForms-Eintragszustand ist nicht vollständig verfügbar.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	global $wpdb;
	$wpdb->last_error = '';
	$records = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wpforms_entries WHERE form_id = %d ORDER BY entry_id ASC", $form_id ), ARRAY_A );
	if ( '' !== (string) $wpdb->last_error || ! is_array( $records ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige WPForms-Eintragszustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$entry_ids = array_column( $records, 'entry_id' );
	$meta_rows = wpagent_form_migration_compensation_wpforms_entry_rows( $wpdb->prefix . 'wpforms_entry_meta', 'entry_id', $entry_ids );
	$field_rows = wpagent_form_migration_compensation_wpforms_entry_rows( $wpdb->prefix . 'wpforms_entry_fields', 'entry_id', $entry_ids );
	if ( is_wp_error( $meta_rows ) || is_wp_error( $field_rows ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige WPForms-Eintragszustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return array( 'entry_storage' => true, 'entries' => $records, 'meta' => $meta_rows, 'fields' => $field_rows );
}

/** @return array<int,array<string,mixed>>|WP_Error */
function wpagent_form_migration_compensation_ninja_rows( string $table, string $column, array $ids ): array|WP_Error {
	$ids = array_values( array_unique( array_filter( array_map( 'absint', $ids ) ) ) );
	if ( ! $ids ) {
		return array();
	}
	global $wpdb;
	$wpdb->last_error = '';
	$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );
	$sql          = "SELECT * FROM {$table} WHERE {$column} IN ({$placeholders}) ORDER BY id ASC";
	$rows         = $wpdb->get_results( $wpdb->prepare( $sql, ...$ids ), ARRAY_A );
	if ( '' !== (string) $wpdb->last_error || ! is_array( $rows ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Ninja-Forms-Zustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return $rows;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_form_migration_compensation_ninja_state( int $form_id ): array|WP_Error {
	global $wpdb;
	$forms_table = $wpdb->prefix . 'nf3_forms';
	$forms       = wpagent_form_migration_compensation_ninja_rows( $forms_table, 'id', array( $form_id ) );
	if ( is_wp_error( $forms ) || 1 !== count( $forms ) ) {
		return is_wp_error( $forms ) ? $forms : new WP_Error( 'wpagent_form_migration_snapshot_not_found', __( 'Die Ninja-Forms-Zielkopie konnte nicht vollständig gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$form_meta    = wpagent_form_migration_compensation_ninja_rows( $wpdb->prefix . 'nf3_form_meta', 'parent_id', array( $form_id ) );
	$fields       = wpagent_form_migration_compensation_ninja_rows( $wpdb->prefix . 'nf3_fields', 'parent_id', array( $form_id ) );
	$actions      = wpagent_form_migration_compensation_ninja_rows( $wpdb->prefix . 'nf3_actions', 'parent_id', array( $form_id ) );
	if ( is_wp_error( $form_meta ) || is_wp_error( $fields ) || is_wp_error( $actions ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Ninja-Forms-Zustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$field_meta  = wpagent_form_migration_compensation_ninja_rows( $wpdb->prefix . 'nf3_field_meta', 'parent_id', array_column( $fields, 'id' ) );
	$action_meta = wpagent_form_migration_compensation_ninja_rows( $wpdb->prefix . 'nf3_action_meta', 'parent_id', array_column( $actions, 'id' ) );
	if ( is_wp_error( $field_meta ) || is_wp_error( $action_meta ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Ninja-Forms-Zustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$wpdb->last_error = '';
	$submission_ids = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} m ON m.post_id = p.ID WHERE p.post_type = 'nf_sub' AND m.meta_key = '_form_id' AND m.meta_value = %s ORDER BY p.ID ASC", (string) $form_id ) );
	if ( '' !== (string) $wpdb->last_error || ! is_array( $submission_ids ) ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Ninja-Forms-Zustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return array(
		'form'        => $forms,
		'form_meta'   => $form_meta,
		'fields'      => $fields,
		'field_meta'  => $field_meta,
		'actions'     => $actions,
		'action_meta' => $action_meta,
		'submissions' => array_map( 'absint', $submission_ids ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_form_migration_compensation_target_state( string $provider, int $form_id ): array|WP_Error {
	try {
		if ( 'wpforms' === $provider ) {
			$post = wpagent_form_migration_compensation_wp_post_state( $form_id, 'wpforms' );
			$entries = wpagent_form_migration_compensation_wpforms_entries_state( $form_id );
			if ( is_wp_error( $post ) || is_wp_error( $entries ) ) {
				return is_wp_error( $post ) ? $post : $entries;
			}
			return array( 'post' => $post, 'entries' => $entries );
		}
		if ( 'contact-form-7' === $provider ) {
			$form = function_exists( 'wpcf7_contact_form' ) ? wpcf7_contact_form( $form_id ) : null;
			$post = wpagent_form_migration_compensation_wp_post_state( $form_id, 'wpcf7_contact_form' );
			if ( ! $form || is_wp_error( $post ) ) {
				return is_wp_error( $post ) ? $post : new WP_Error( 'wpagent_form_migration_snapshot_not_found', __( 'Die Contact-Form-7-Zielkopie konnte nicht vollständig gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			return array( 'post' => $post, 'properties' => $form->get_properties(), 'locale' => (string) $form->locale() );
		}
		if ( 'gravity-forms' === $provider ) {
			$form = is_callable( array( 'GFAPI', 'get_form' ) ) ? GFAPI::get_form( $form_id ) : false;
			if ( ! is_array( $form ) ) {
				return new WP_Error( 'wpagent_form_migration_snapshot_not_found', __( 'Die Gravity-Forms-Zielkopie konnte nicht vollständig gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			$entries = array();
			if ( is_callable( array( 'GFAPI', 'get_entries' ) ) ) {
				$total = 0;
				$entries = GFAPI::get_entries( $form_id, array(), null, array( 'offset' => 0, 'page_size' => 201 ), $total );
				if ( is_wp_error( $entries ) || ! is_array( $entries ) || $total > 200 || count( $entries ) > 200 ) {
					return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Gravity-Forms-Eintragszustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
				}
			}
			return array( 'form' => function_exists( 'wpagent_gravity_json_value' ) ? wpagent_gravity_json_value( $form ) : $form, 'entries' => $entries );
		}
		if ( 'fluent-forms' === $provider ) {
			$authorized = wpagent_fluent_forms_get_authorized_form( array( 'form_id' => $form_id ) );
			if ( is_wp_error( $authorized ) ) {
				return $authorized;
			}
			$state = wpagent_fluent_forms_model_array( $authorized['form'] );
			return $state ? $state : new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Fluent-Forms-Zustand konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		if ( 'formidable-forms' === $provider ) {
			$form = FrmForm::getOne( $form_id );
			if ( ! is_object( $form ) ) {
				return new WP_Error( 'wpagent_form_migration_snapshot_not_found', __( 'Die Formidable-Forms-Zielkopie konnte nicht vollständig gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			$fields = array_map( static fn( $field ): array => get_object_vars( $field ), wpagent_formidable_bounded_fields( $form_id ) );
			$entries = class_exists( 'FrmDb' ) ? FrmDb::get_col( 'frm_items', array( 'form_id' => $form_id ), 'id' ) : array();
			return array( 'form' => get_object_vars( $form ), 'fields' => $fields, 'entry_ids' => array_map( 'absint', (array) $entries ) );
		}
		if ( 'ninja-forms' === $provider ) {
			return wpagent_form_migration_compensation_ninja_state( $form_id );
		}
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Der vollständige Zustand der neu angelegten Zielkopie konnte nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return new WP_Error( 'wpagent_form_migration_provider_unavailable', __( 'Der Zielanbieter unterstützt keine sichere Migrationskompensation.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

/** @return array{provider:string,form_id:int,state_hash:string}|WP_Error */
function wpagent_form_migration_capture_created_target( string $provider, int $form_id ): array|WP_Error {
	if ( ! in_array( $provider, wpagent_form_migration_providers(), true ) || $form_id <= 0 ) {
		return new WP_Error( 'wpagent_form_migration_snapshot_failed', __( 'Die neu angelegte Zielkopie konnte nicht sicher gesichert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$state = wpagent_form_migration_compensation_target_state( $provider, $form_id );
	$hash  = is_wp_error( $state ) ? $state : wpagent_form_migration_compensation_hash( $state );
	if ( is_wp_error( $hash ) ) {
		return $hash;
	}
	return array( 'provider' => $provider, 'form_id' => $form_id, 'state_hash' => $hash );
}

function wpagent_form_migration_compensation_delete( string $provider, int $form_id ): bool {
	try {
		if ( 'wpforms' === $provider ) {
			$handler = function_exists( 'wpforms' ) ? wpforms()->obj( 'form' ) : null;
			return $handler && $handler->delete( array( $form_id ) ) && ! get_post( $form_id );
		}
		if ( 'contact-form-7' === $provider ) {
			$form = function_exists( 'wpcf7_contact_form' ) ? wpcf7_contact_form( $form_id ) : null;
			return $form && $form->delete() && ! get_post( $form_id );
		}
		if ( 'gravity-forms' === $provider ) {
			return is_callable( array( 'GFAPI', 'delete_form' ) ) && true === GFAPI::delete_form( $form_id ) && ! is_array( GFAPI::get_form( $form_id ) );
		}
		if ( 'fluent-forms' === $provider ) {
			$service = wpagent_fluent_forms_service();
			return ! is_wp_error( $service ) && wpagent_fluent_forms_delete_and_verify( $service, $form_id );
		}
		if ( 'formidable-forms' === $provider ) {
			return true === FrmForm::destroy( $form_id ) && ! is_object( FrmForm::getOne( $form_id ) );
		}
		if ( 'ninja-forms' === $provider ) {
			Ninja_Forms()->form( $form_id )->delete();
			global $wpdb;
			return null === $wpdb->get_var( $wpdb->prepare( "SELECT 1 FROM {$wpdb->prefix}nf3_forms WHERE id = %d LIMIT 1", $form_id ) );
		}
	} catch ( Throwable $error ) {
		return false;
	}
	return false;
}

/** @return WP_Error */
function wpagent_form_migration_recovery_required( string $provider, int $form_id, string $reason ): WP_Error {
	return new WP_Error(
		'wpagent_form_migration_recovery_required',
		__( 'Die Zielkopie konnte nach einem fehlgeschlagenen Migrationsabgleich nicht sicher automatisch bereinigt werden. Prüfe sie manuell.', 'wp-agent-companion' ),
		array( 'status' => 500, 'target_provider' => $provider, 'target_form_id' => $form_id, 'reason' => $reason )
	);
}

/** @param array<string,mixed> $candidate @return array{removed:true}|WP_Error */
function wpagent_form_migration_compensate_created_target( array $candidate ): array|WP_Error {
	$provider = is_string( $candidate['provider'] ?? null ) ? $candidate['provider'] : '';
	$form_id  = absint( $candidate['form_id'] ?? 0 );
	$expected = is_string( $candidate['state_hash'] ?? null ) ? $candidate['state_hash'] : '';
	if ( ! in_array( $provider, wpagent_form_migration_providers(), true ) || $form_id <= 0 || ! preg_match( '/^[a-f0-9]{64}$/D', $expected ) ) {
		return wpagent_form_migration_recovery_required( $provider, $form_id, 'invalid_candidate' );
	}
	$current = wpagent_form_migration_compensation_target_state( $provider, $form_id );
	$hash    = is_wp_error( $current ) ? $current : wpagent_form_migration_compensation_hash( $current );
	if ( is_wp_error( $hash ) ) {
		return wpagent_form_migration_recovery_required( $provider, $form_id, 'fresh_state_unavailable' );
	}
	if ( ! hash_equals( $expected, $hash ) ) {
		return wpagent_form_migration_recovery_required( $provider, $form_id, 'state_changed' );
	}
	if ( ! wpagent_form_migration_compensation_delete( $provider, $form_id ) ) {
		return wpagent_form_migration_recovery_required( $provider, $form_id, 'delete_or_readback_failed' );
	}
	return array( 'removed' => true );
}
