<?php
/** Shared, version-bound Kadence Blocks advanced-form helpers. */

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

const WPAGENT_KADENCE_FORM_VERSION       = '3.7.8';
const WPAGENT_KADENCE_FORM_LOCK_TTL      = 120;
const WPAGENT_KADENCE_FORM_LOCK_PREFIX   = 'wp_agent_kadence_form_lock_';
const WPAGENT_KADENCE_FORM_MAX_FIELDS    = 100;
const WPAGENT_KADENCE_FORM_MAX_BLOCKS    = 500;
const WPAGENT_KADENCE_FORM_MAX_DEPTH     = 16;

/** @return true|WP_Error */
function wpagent_kadence_form_runtime() {
	if ( ! defined( 'KADENCE_BLOCKS_VERSION' )
		|| WPAGENT_KADENCE_FORM_VERSION !== KADENCE_BLOCKS_VERSION
		|| ! class_exists( 'Kadence_Blocks_Form_CPT_Controller' )
		|| ! post_type_exists( 'kadence_form' ) ) {
		return new WP_Error(
			'wpagent_kadence_form_provider_unsupported',
			__( 'Kadence Forms ist nicht aktiv oder entspricht nicht der praktisch verifizierten Kadence-Blocks-Version 3.7.8.', 'wp-agent-companion' ),
			array( 'status' => 409, 'required_version' => WPAGENT_KADENCE_FORM_VERSION )
		);
	}
	if ( class_exists( 'Kadence_Blocks_Pro' ) ) {
		return new WP_Error(
			'wpagent_kadence_form_pro_unsupported',
			__( 'Dieser enge Vertrag gilt ausschließlich für Kadence Blocks Free. Pro-Aktionen werden ohne separates Provider-Fixture nicht verändert.', 'wp-agent-companion' ),
			array( 'status' => 409 )
		);
	}
	$post_type = get_post_type_object( 'kadence_form' );
	$block     = WP_Block_Type_Registry::get_instance()->get_registered( 'kadence/advanced-form' );
	if ( ! $post_type instanceof WP_Post_Type
		|| true !== $post_type->show_in_rest
		|| 'Kadence_Blocks_Form_CPT_Rest_Controller' !== $post_type->rest_controller_class
		|| ! $block instanceof WP_Block_Type
		|| ! is_callable( $block->render_callback ) ) {
		return new WP_Error( 'wpagent_kadence_form_provider_contract', __( 'Der native Kadence-Formular-CPT oder Renderpfad entspricht nicht dem verifizierten Providervertrag.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$registered = get_registered_meta_keys( 'post', 'kadence_form' );
	$required   = array(
		'_kad_form_actions' => 'array', '_kad_form_email' => 'object',
		'_kad_form_browserValidation' => 'boolean', '_kad_form_redirect' => 'string',
		'_kad_form_submitHide' => 'boolean', '_kad_form_description' => 'string',
	);
	foreach ( $required as $key => $type ) {
		if ( ! is_array( $registered[ $key ] ?? null )
			|| $type !== ( $registered[ $key ]['type'] ?? null )
			|| true !== ( $registered[ $key ]['single'] ?? false ) ) {
			return new WP_Error( 'wpagent_kadence_form_provider_contract', __( 'Ein registriertes Kadence-Formularfeld entspricht nicht dem verifizierten Providervertrag.', 'wp-agent-companion' ), array( 'status' => 409, 'meta_key' => $key ) );
		}
	}
	return true;
}

/** @param mixed $input */
function wpagent_perm_kadence_forms_list( $input = null ): bool {
	return ! is_wp_error( wpagent_kadence_form_runtime() ) && current_user_can( 'edit_kadence_forms' );
}

/** @param mixed $input */
function wpagent_perm_kadence_form( $input = null ): bool {
	$form_id = is_array( $input ) ? (int) ( $input['form_id'] ?? 0 ) : 0;
	return $form_id > 0
		&& ! is_wp_error( wpagent_kadence_form_runtime() )
		&& current_user_can( 'edit_kadence_forms' )
		&& current_user_can( 'edit_post', $form_id );
}

/** @return WP_Post|WP_Error */
function wpagent_kadence_form_get_authorized( int $form_id ) {
	$runtime = wpagent_kadence_form_runtime();
	if ( is_wp_error( $runtime ) ) {
		return $runtime;
	}
	$post = get_post( $form_id );
	if ( ! $post instanceof WP_Post || 'kadence_form' !== $post->post_type || 'trash' === $post->post_status ) {
		return new WP_Error( 'wpagent_kadence_form_not_found', __( 'Kadence-Formular nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! current_user_can( 'edit_kadence_forms' ) || ! current_user_can( 'edit_post', $form_id ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung für dieses Kadence-Formular.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	return $post;
}

/** @return array<int,array{meta_id:int,meta_key:string,meta_value:string}>|WP_Error */
function wpagent_kadence_form_raw_meta( int $form_id ) {
	global $wpdb;
	$rows = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT meta_id, meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key LIKE %s ORDER BY meta_id ASC",
			$form_id,
			$wpdb->esc_like( '_kad_form_' ) . '%'
		),
		ARRAY_A
	);
	if ( ! is_array( $rows ) ) {
		return new WP_Error( 'wpagent_kadence_form_storage', __( 'Der rohe Kadence-Formularzustand konnte nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$result = array();
	foreach ( $rows as $row ) {
		if ( ! is_numeric( $row['meta_id'] ?? null ) || ! is_string( $row['meta_key'] ?? null ) || ! is_string( $row['meta_value'] ?? null ) ) {
			return new WP_Error( 'wpagent_kadence_form_storage', __( 'Der rohe Kadence-Formularzustand ist nicht eindeutig lesbar.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$result[] = array( 'meta_id' => (int) $row['meta_id'], 'meta_key' => $row['meta_key'], 'meta_value' => $row['meta_value'] );
	}
	return $result;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_kadence_form_snapshot( int $form_id ) {
	global $wpdb;
	$post = $wpdb->get_row(
		$wpdb->prepare(
			"SELECT ID, post_type, post_status, post_title, post_content, post_author FROM {$wpdb->posts} WHERE ID = %d LIMIT 1",
			$form_id
		),
		ARRAY_A
	);
	if ( ! is_array( $post ) || 'kadence_form' !== ( $post['post_type'] ?? null ) ) {
		return new WP_Error( 'wpagent_kadence_form_not_found', __( 'Kadence-Formular nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! is_numeric( $post['ID'] ?? null )
		|| ! is_string( $post['post_status'] ?? null )
		|| ! is_string( $post['post_title'] ?? null )
		|| ! is_string( $post['post_content'] ?? null )
		|| ! is_numeric( $post['post_author'] ?? null ) ) {
		return new WP_Error( 'wpagent_kadence_form_storage', __( 'Der rohe Kadence-Formularzustand ist nicht eindeutig lesbar.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$rows = wpagent_kadence_form_raw_meta( $form_id );
	if ( is_wp_error( $rows ) ) {
		return $rows;
	}
	$snapshot = array(
		'blog_id'          => get_current_blog_id(),
		'provider_version' => WPAGENT_KADENCE_FORM_VERSION,
		'form_id'          => $form_id,
		'post_title'       => $post['post_title'],
		'post_status'      => $post['post_status'],
		'post_content'     => $post['post_content'],
		'post_author'      => (int) $post['post_author'],
		'meta'             => $rows,
	);
	$encoded = wp_json_encode( $snapshot, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
	if ( ! is_string( $encoded ) ) {
		return new WP_Error( 'wpagent_kadence_form_storage', __( 'Der rohe Kadence-Formularzustand kann nicht sicher gehasht werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$snapshot['hash'] = hash( 'sha256', $encoded );
	return $snapshot;
}

/** @param array<int,array{meta_id:int,meta_key:string,meta_value:string}> $rows @return array<int,array{meta_id:int,meta_key:string,meta_value:string}> */
function wpagent_kadence_form_rows_without_key( array $rows, string $key ): array {
	return array_values( array_filter( $rows, static fn ( array $row ): bool => $key !== $row['meta_key'] ) );
}

/** @param array<string,mixed> $before @param array<string,mixed> $after */
function wpagent_kadence_form_snapshot_changed_only_key( array $before, array $after, string $key ): bool {
	foreach ( array( 'blog_id', 'provider_version', 'form_id', 'post_title', 'post_status', 'post_content', 'post_author' ) as $field ) {
		if ( ( $before[ $field ] ?? null ) !== ( $after[ $field ] ?? null ) ) {
			return false;
		}
	}
	return wpagent_kadence_form_rows_without_key( $before['meta'], $key ) === wpagent_kadence_form_rows_without_key( $after['meta'], $key );
}

/** @param array<int,array{meta_id:int,meta_key:string,meta_value:string}> $rows @return mixed|WP_Error */
function wpagent_kadence_form_meta_value_from_rows( array $rows, string $key ) {
	$matches = array_values( array_filter( $rows, static fn ( array $row ): bool => $key === $row['meta_key'] ) );
	if ( count( $matches ) > 1 ) {
		return new WP_Error( 'wpagent_kadence_form_duplicate_meta', __( 'Eine verwaltete Kadence-Formulareinstellung besitzt mehrere rohe Werte.', 'wp-agent-companion' ), array( 'status' => 409, 'meta_key' => $key ) );
	}
	if ( array() === $matches ) {
		return '';
	}
	$raw = $matches[0]['meta_value'];
	return is_serialized( $raw ) ? unserialize( trim( $raw ), array( 'allowed_classes' => false ) ) : $raw;
}

/** @return mixed|WP_Error */
function wpagent_kadence_form_meta_value( int $form_id, string $key ) {
	$rows = wpagent_kadence_form_raw_meta( $form_id );
	return is_wp_error( $rows ) ? $rows : wpagent_kadence_form_meta_value_from_rows( $rows, $key );
}

/** @param array<int,array<string,mixed>> $blocks @param array<int,string> $types @return true|WP_Error */
function wpagent_kadence_form_collect_fields( array $blocks, array &$types, int &$block_count, int $depth = 0 ) {
	if ( $depth > WPAGENT_KADENCE_FORM_MAX_DEPTH ) {
		return new WP_Error( 'wpagent_kadence_form_structure', __( 'Die Kadence-Formularstruktur ist zu tief verschachtelt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	foreach ( $blocks as $block ) {
		if ( ! is_array( $block ) ) {
			return new WP_Error( 'wpagent_kadence_form_structure', __( 'Die Kadence-Formularstruktur ist nicht eindeutig lesbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		++$block_count;
		if ( $block_count > WPAGENT_KADENCE_FORM_MAX_BLOCKS ) {
			return new WP_Error( 'wpagent_kadence_form_structure', __( 'Das Kadence-Formular enthält zu viele Blöcke.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$name = is_string( $block['blockName'] ?? null ) ? $block['blockName'] : '';
		if ( str_starts_with( $name, 'kadence/advanced-form-' ) ) {
			$types[] = substr( $name, strlen( 'kadence/advanced-form-' ) );
			if ( count( $types ) > WPAGENT_KADENCE_FORM_MAX_FIELDS ) {
				return new WP_Error( 'wpagent_kadence_form_structure', __( 'Das Kadence-Formular enthält zu viele Felder.', 'wp-agent-companion' ), array( 'status' => 409 ) );
			}
		}
		$inner = $block['innerBlocks'] ?? array();
		if ( ! is_array( $inner ) ) {
			return new WP_Error( 'wpagent_kadence_form_structure', __( 'Die Kadence-Formularstruktur ist nicht eindeutig lesbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$result = wpagent_kadence_form_collect_fields( $inner, $types, $block_count, $depth + 1 );
		if ( is_wp_error( $result ) ) {
			return $result;
		}
	}
	return true;
}

/** @return array<int,string>|WP_Error */
function wpagent_kadence_form_field_types( WP_Post $post ) {
	$blocks = parse_blocks( $post->post_content );
	if ( 1 !== count( $blocks ) || 'kadence/advanced-form' !== ( $blocks[0]['blockName'] ?? '' ) ) {
		return new WP_Error( 'wpagent_kadence_form_structure', __( 'Das Formular besitzt nicht genau einen nativen Kadence-Advanced-Form-Wurzelblock.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$types       = array();
	$block_count = 0;
	$result      = wpagent_kadence_form_collect_fields( $blocks, $types, $block_count );
	return is_wp_error( $result ) ? $result : $types;
}

function wpagent_kadence_form_lock_name( int $form_id ): string {
	return WPAGENT_KADENCE_FORM_LOCK_PREFIX . $form_id;
}

/** @return string|WP_Error */
function wpagent_kadence_form_acquire_lock( int $form_id ) {
	$token = wpagent_companion_acquire_option_lock( wpagent_kadence_form_lock_name( $form_id ), WPAGENT_KADENCE_FORM_LOCK_TTL );
	return is_string( $token ) && '' !== $token
		? $token
		: new WP_Error( 'wpagent_kadence_form_locked', __( 'Das Kadence-Formular wird gerade in einem anderen Vorgang geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_kadence_form_refresh_lock( int $form_id, string $token ): bool {
	return wpagent_companion_refresh_option_lock( wpagent_kadence_form_lock_name( $form_id ), $token, WPAGENT_KADENCE_FORM_LOCK_TTL );
}

function wpagent_kadence_form_release_lock( int $form_id, string $token ): void {
	wpagent_companion_release_option_lock( wpagent_kadence_form_lock_name( $form_id ), $token );
}
