<?php
/** Update verified Ocean Extra per-post header, footer, sidebar and width overrides. */

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

function wpagent_ability_update_oceanwp_post_layout_overrides(): array {
	return array(
		'label'               => __( 'Ocean-Extra-Beitragslayout aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Ändert sichere Ocean-Extra-Header-, Footer-, Sidebar- und Breitenvorgaben mit Konfliktschutz, Laufzeitprüfung, Read-back und fail-closed Recovery bei nicht verifizierter Persistierung.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'post_id'       => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'settings'      => wpagent_oceanwp_extra_layout_settings_schema(),
			),
			'required'             => array( 'post_id', 'expected_hash', 'settings' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'post_id'    => array( 'type' => 'integer' ),
				'post_type'  => array( 'type' => 'string' ),
				'overrides'  => wpagent_oceanwp_extra_layout_state_schema(),
				'state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'verified'   => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'post_id', 'post_type', 'overrides', 'state_hash', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_update_oceanwp_post_layout_overrides',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_oceanwp_post_layout_overrides( $input ) {
	$ready = wpagent_oceanwp_extra_layout_require_runtime();
	if ( is_wp_error( $ready ) ) {
		return $ready;
	}
	$input  = is_array( $input ) ? $input : array();
	$target = wpagent_oceanwp_extra_layout_post_target( absint( $input['post_id'] ?? 0 ) );
	if ( is_wp_error( $target ) ) {
		return $target;
	}
	$schema = wpagent_oceanwp_extra_layout_settings_schema();
	$valid  = rest_validate_value_from_schema( $input['settings'] ?? null, $schema, 'settings' );
	if ( is_wp_error( $valid ) || ! is_array( $input['settings'] ?? null ) || ! wpagent_oceanwp_extra_layout_settings_are_safe( $input['settings'] ) ) {
		return new WP_Error( 'wpagent_ocean_extra_layout_invalid_settings', __( 'Die Ocean-Extra-Layouteinstellungen sind ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$settings = rest_sanitize_value_from_schema( $input['settings'], $schema, 'settings' );
	if ( is_wp_error( $settings ) || ! is_array( $settings ) || ! $settings || ! wpagent_oceanwp_extra_layout_settings_are_safe( $settings ) ) {
		return new WP_Error( 'wpagent_ocean_extra_layout_invalid_settings', __( 'Die Ocean-Extra-Layouteinstellungen sind ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$post_id = $target['post']->ID;
	$blog_id = $target['blog_id'];
	$lock    = wpagent_oceanwp_post_acquire_lock( $post_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$target = wpagent_oceanwp_extra_layout_post_target( $post_id, $blog_id );
		if ( is_wp_error( $target ) ) {
			return $target;
		}
		$ready = wpagent_oceanwp_extra_layout_require_runtime();
		if ( is_wp_error( $ready ) ) {
			return $ready;
		}
		if ( ! wpagent_oceanwp_extra_layout_settings_are_safe( $settings ) ) {
			return new WP_Error( 'wpagent_ocean_extra_layout_settings_changed', __( 'Eine gewählte Ocean-Extra-Layoutvorgabe ist nicht mehr sicher verfügbar. Lies den Zustand neu und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$previous = wpagent_oceanwp_extra_layout_snapshot( $target['post'], $target['blog_id'] );
		if ( is_wp_error( $previous ) ) {
			return $previous;
		}
		$previous_hash = wpagent_oceanwp_extra_layout_state_hash( $previous );
		$expected_hash = strtolower( (string) ( $input['expected_hash'] ?? '' ) );
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) || ! hash_equals( $previous_hash, $expected_hash ) ) {
			return new WP_Error( 'wpagent_ocean_extra_layout_conflict', __( 'Die Ocean-Extra-Layouteinstellungen haben sich seit dem Lesen geändert. Lies sie neu und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $previous_hash ) );
		}
		if ( isset( $settings['content_width'] ) && 'set' === $settings['content_width']['mode'] && 'both-sidebars' !== $previous['meta']['ocean_post_layout']['value'] ) {
			return new WP_Error( 'wpagent_ocean_extra_layout_content_width_unavailable', __( 'Eine individuelle Inhaltsbreite ist nur bei der nativen Ocean-Extra-Beitragsvorlage mit zwei Sidebars verfügbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$expected            = wpagent_oceanwp_extra_layout_expected_snapshot( $previous, $settings );
		$expected_write_hash = wpagent_oceanwp_extra_layout_state_hash( $expected );
		if ( ! wpagent_oceanwp_post_refresh_lock( $post_id, $lock ) ) {
			return new WP_Error( 'wpagent_ocean_extra_layout_lock_lost', __( 'Die Ocean-Extra-Layoutänderung hat ihre exklusive Sperre verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$write_target = wpagent_oceanwp_extra_layout_post_target( $post_id, $blog_id );
		if ( is_wp_error( $write_target ) ) {
			return $write_target;
		}
		try {
			$persisted = wpagent_oceanwp_extra_layout_persist_settings( $write_target['post']->ID, $blog_id, $settings, $lock, $previous );
		} catch ( Throwable $error ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		if ( is_wp_error( $persisted ) ) {
			$data = $persisted->get_error_data();
			if ( ! is_array( $data ) || empty( $data['write_started'] ) ) {
				return $persisted;
			}
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		$fresh = wpagent_oceanwp_extra_layout_snapshot( $target['post'], $blog_id );
		if ( is_wp_error( $fresh ) || ! hash_equals( $expected_write_hash, wpagent_oceanwp_extra_layout_state_hash( $fresh ) ) ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		if ( ! wpagent_oceanwp_post_refresh_lock( $post_id, $lock ) ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		$width   = (int) $fresh['meta']['ocean_both_sidebars_content_width']['value'];
		$runtime = wpagent_oceanwp_extra_layout_runtime_state( $post_id, $width );
		if ( is_wp_error( $runtime ) || ! wpagent_oceanwp_extra_layout_runtime_matches( $settings, $runtime ) ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		if ( ! wpagent_oceanwp_post_refresh_lock( $post_id, $lock ) ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		$verified_target = wpagent_oceanwp_extra_layout_post_target( $post_id, $blog_id );
		if ( is_wp_error( $verified_target ) ) {
			return wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id );
		}
		return array(
			'post_id'    => (int) $verified_target['post']->ID,
			'post_type'  => $verified_target['post']->post_type,
			'overrides'  => wpagent_oceanwp_extra_layout_normalize( $fresh ),
			'state_hash' => wpagent_oceanwp_extra_layout_state_hash( $fresh ),
			'verified'   => true,
		);
	} finally {
		wpagent_oceanwp_post_release_lock( $post_id, $lock );
	}
}

/** @return WP_Error */
function wpagent_oceanwp_extra_layout_persist_lock_lost( bool $write_started ): WP_Error {
	return new WP_Error(
		$write_started ? 'wpagent_ocean_extra_layout_lock_lost_after_write' : 'wpagent_ocean_extra_layout_lock_lost',
		__( 'Die Ocean-Extra-Layoutänderung hat ihre exklusive Sperre verloren.', 'wp-agent-companion' ),
		array( 'status' => $write_started ? 500 : 409, 'write_started' => $write_started )
	);
}

/** @return WP_Error */
function wpagent_oceanwp_extra_layout_persist_failed( bool $write_started ): WP_Error {
	return new WP_Error(
		'wpagent_ocean_extra_layout_write_failed',
		__( 'Ocean Extra konnte die Layoutvorgaben nicht sicher speichern.', 'wp-agent-companion' ),
		array( 'status' => $write_started ? 500 : 502, 'write_started' => $write_started )
	);
}

/** @return WP_Error */
function wpagent_oceanwp_extra_layout_persist_target_lost(): WP_Error {
	return new WP_Error(
		'wpagent_ocean_extra_layout_target_lost_after_write',
		__( 'Der Ocean-Extra-Layoutbeitrag ist nach einer begonnenen Änderung nicht mehr sicher bearbeitbar.', 'wp-agent-companion' ),
		array( 'status' => 500, 'write_started' => true )
	);
}

/** @return true|WP_Error */
function wpagent_oceanwp_extra_layout_write_checkpoint( int $post_id, int $blog_id, string $lock ) {
	$ready = wpagent_oceanwp_extra_layout_require_runtime();
	if ( is_wp_error( $ready ) ) return $ready;
	$target = wpagent_oceanwp_extra_layout_post_target( $post_id, $blog_id );
	if ( is_wp_error( $target ) ) return $target;
	if ( ! wpagent_oceanwp_post_refresh_lock( $post_id, $lock ) || ! wpagent_companion_option_lock_is_owned( WPAGENT_OCEANWP_POST_LOCK_PREFIX . $post_id, $lock ) ) {
		return wpagent_oceanwp_extra_layout_persist_lock_lost( false );
	}
	return true;
}

/** @param array<string,mixed> $settings @param array<string,mixed> $previous @return true|WP_Error */
function wpagent_oceanwp_extra_layout_persist_settings( int $post_id, int $blog_id, array $settings, string $lock, array $previous ) {
	$catalog = wpagent_oceanwp_extra_layout_choice_catalog();
	$operations = array();
	foreach ( array( 'header' => array( 'visibility' => 'header_visibility', 'style' => 'header_style' ), 'footer' => array( 'widgets' => 'footer_widgets', 'bottom' => 'footer_bottom' ) ) as $group => $fields ) {
		foreach ( $fields as $input_field => $catalog_field ) {
			if ( isset( $settings[ $group ] ) && is_array( $settings[ $group ] ) && array_key_exists( $input_field, $settings[ $group ] ) ) {
				$operations[] = array( 'key' => $catalog[ $catalog_field ]['meta'], 'value' => 'inherit' === $settings[ $group ][ $input_field ] ? 'inherit' : $catalog[ $catalog_field ]['values'][ $settings[ $group ][ $input_field ] ] );
			}
		}
	}
	if ( isset( $settings['custom_sidebar'] ) ) $operations[] = array( 'key' => 'ocean_sidebar', 'value' => 'inherit' === $settings['custom_sidebar']['mode'] ? 'inherit' : $settings['custom_sidebar']['sidebar_id'] );
	if ( isset( $settings['content_width'] ) ) $operations[] = array( 'key' => 'ocean_both_sidebars_content_width', 'value' => 'inherit' === $settings['content_width']['mode'] ? 'inherit' : (string) $settings['content_width']['value'] );
	$raw = array();
	foreach ( $previous['meta'] as $key => $entry ) {
		$row = wpagent_oceanwp_post_raw_meta_row( $post_id, $key );
		if ( is_wp_error( $row ) ) return $row;
		if ( $row['exists'] !== $entry['exists'] || ( $row['exists'] && $row['raw'] !== $entry['value'] ) ) {
			return new WP_Error( 'wpagent_ocean_extra_layout_conflict', __( 'Die rohe Ocean-Extra-Layoutmetadatenzeile änderte sich während der Vorbereitung.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$raw[ $key ] = $row;
	}
	$write_started = false;
	foreach ( $operations as $operation ) {
		$checkpoint = wpagent_oceanwp_extra_layout_write_checkpoint( $post_id, $blog_id, $lock );
		if ( is_wp_error( $checkpoint ) ) return $write_started ? wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id ) : $checkpoint;
		$current = wpagent_oceanwp_post_raw_meta_row( $post_id, $operation['key'] );
		if ( is_wp_error( $current ) || $current !== $raw[ $operation['key'] ] ) {
			return $write_started ? wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id ) : new WP_Error( 'wpagent_ocean_extra_layout_conflict', __( 'Die Ocean-Extra-Layoutmetadaten wurden gleichzeitig verändert und nicht überschrieben.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$result = wpagent_oceanwp_post_cas_meta( $post_id, $operation['key'], $raw[ $operation['key'] ], $operation['value'] );
		if ( is_wp_error( $result ) ) {
			$data = $result->get_error_data();
			return $write_started || ( is_array( $data ) && ! empty( $data['write_started'] ) ) ? wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id ) : $result;
		}
		$write_started = $write_started || $result !== $raw[ $operation['key'] ];
		$raw[ $operation['key'] ] = $result;
		$checkpoint = wpagent_oceanwp_extra_layout_write_checkpoint( $post_id, $blog_id, $lock );
		if ( is_wp_error( $checkpoint ) ) return $write_started ? wpagent_oceanwp_extra_layout_recovery_required( $post_id, $blog_id ) : $checkpoint;
	}
	return true;
}
