<?php
/**
 * Programmatic Visual Builder save for bulk legacy module re-save.
 *
 * Replays Divi's sync-to-server save path for a single post without rewriting
 * stored content in the bulk layer. Legacy shortcode-module conversion runs
 * inside {@see PersistShortcodeModuleConversionOnSave::filter_post_data()} when
 * the VB REST save flag is set — the same as a manual builder Save.
 *
 * @package DiviSupreme
 */

declare(strict_types=1);

namespace DiviSupreme\Includes\Divi5Conversion;

use ET\Builder\VisualBuilder\REST\SyncToServer\SyncToServerController;
use ET\Builder\VisualBuilder\Saving\SavingUtility;

/**
 * Bulk re-save via Divi's builder save pipeline.
 */
final class DiviVisualBuilderResaveService
{

	/**
	 * Re-save one post through Divi's Visual Builder save hooks.
	 *
	 * Does not call {@see LegacyShortcodeConversionService::convert_content()} directly.
	 * Conversion during {@see wp_update_post()} is handled by save filters when flagged.
	 *
	 * @param int  $post_id Post ID.
	 * @param bool $dry_run When true, report only; do not write.
	 * @return array<string, mixed>
	 */
	public static function resave_post( int $post_id, bool $dry_run = false ): array
	{
		try {
			$post = get_post( $post_id );

			if ( ! $post instanceof \WP_Post ) {
				return array(
					'success' => false,
					'message' => __( 'Post not found.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			if ( ! current_user_can( 'edit_post', $post_id ) ) {
				return array(
					'success' => false,
					'message' => __( 'You do not have permission to edit this item.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			$raw_content = (string) $post->post_content;
			$reason      = LegacyShortcodeConversionService::get_resave_reason( $raw_content );

			if ( null === $reason ) {
				return array(
					'success' => true,
					'skipped' => true,
					'message' => __( 'No Supreme modules detected in stored content.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			$legacy_before = LegacyShortcodeConversionService::count_legacy_blocks( wp_unslash( $raw_content ) );

			if ( $dry_run ) {
				return array(
					'success'       => true,
					'dry_run'       => true,
					'resave_reason' => $reason,
					'legacy_before' => $legacy_before,
				);
			}

			if ( ! class_exists( SavingUtility::class ) || ! class_exists( SyncToServerController::class ) ) {
				return array(
					'success' => false,
					'message' => __( 'Divi 5 Visual Builder save utilities are not available.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			$unslashed = wp_unslash( $raw_content );

			// Builder re-save only: pass stored content through unchanged (no parse_blocks round-trip).
			// Legacy conversion still uses Divi's sanitize path — same as a manual Visual Builder Save.
			// Pure D4 + Supreme: convert via outlines + Divi structure mapping, then persist.
			if ( 'builder_resave' === $reason ) {
				$post_content = $unslashed;
			} elseif ( LegacyShortcodeConversionService::content_is_pure_d4_shortcode_layout( $unslashed ) ) {
				$conversion = LegacyShortcodeConversionService::convert_content( $unslashed, $post_id );

				if ( null !== $conversion->fatal_error && '' !== $conversion->fatal_error && ! $conversion->changed ) {
					return array(
						'success' => false,
						'message' => $conversion->fatal_error,
					);
				}

				if ( ! $conversion->changed ) {
					return array(
						'success' => true,
						'skipped' => true,
						'message' => __( 'Pure Divi 4 layout did not change during Supreme conversion.', 'dsm-supreme-modules-pro-for-divi' ),
					);
				}

				return LegacyShortcodeConversionService::persist_converted_post(
					$post_id,
					$conversion->content,
					false
				);
			} else {
				$sanitized_map = SyncToServerController::sanitize_content(
					array(
						'post_content' => $unslashed,
					)
				);
				$post_content  = isset( $sanitized_map['post_content'] ) && is_string( $sanitized_map['post_content'] )
					? $sanitized_map['post_content']
					: $unslashed;
			}

			$post_status                  = (string) $post->post_status;
			$options                      = array();
			$post_content_page_settings   = array();
			$main_loop_type               = 'singular';
			$main_loop_settings_data      = array();

			$post_author = get_current_user_id();
			$autosave    = wp_get_post_autosave( $post_id, $post_author );

			if ( ! empty( $autosave ) ) {
				wp_delete_post_revision( (int) $autosave->ID );
			}

			wp_save_post_revision( $post );

			/**
			 * Mirrors {@see SyncToServerController::update()} — sets the VB REST save flag
			 * and allows modules to abort the save when returning an array.
			 */
			$abort_save_response = apply_filters(
				'divi_visual_builder_rest_before_save_post',
				null,
				$post_id,
				$post_content,
				$post_status,
				$options,
				$post_content_page_settings
			);

			if ( is_array( $abort_save_response ) ) {
				return array(
					'success' => false,
					'message' => __( 'Save was aborted by a filter.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			$update = wp_update_post(
				array(
					'ID'           => $post_id,
					'post_status'  => $post_status,
					'post_content' => wp_slash( $post_content ),
				),
				true
			);

			if ( is_wp_error( $update ) ) {
				return array(
					'success' => false,
					'message' => $update->get_error_message(),
				);
			}

			if ( ! $update ) {
				return array(
					'success' => false,
					'message' => __( 'Failed to save post.', 'dsm-supreme-modules-pro-for-divi' ),
				);
			}

			/**
			 * Post-save hooks — same order as {@see SyncToServerController::update()}.
			 *
			 * @deprecated 5.0.0 Use divi_visual_builder_rest_save_post.
			 */
			do_action( 'et_save_post', $post_id );

			do_action(
				'divi_visual_builder_rest_save_post',
				$post_id,
				array(
					'mainLoopType'         => $main_loop_type,
					'mainLoopSettingsData' => $main_loop_settings_data,
				)
			);

			SavingUtility::prime_page_cache_on_save( $post_id );

			update_post_meta( $post_id, '_et_pb_use_divi_5', 'on' );
			update_post_meta( $post_id, '_et_pb_use_builder', 'on' );
			update_post_meta( $post_id, '_et_pb_show_page_creation', 'off' );

			/**
			 * @deprecated 5.0.0 Use divi_visual_builder_rest_update_post.
			 */
			do_action( 'et_update_post', $post_id );
			do_action( 'divi_visual_builder_rest_update_post', $post_id );

			if ( function_exists( 'et_theme_builder_clear_wp_post_cache' ) ) {
				et_theme_builder_clear_wp_post_cache( $post_id );
			}

			clean_post_cache( $post_id );

			$saved_content = (string) get_post_field( 'post_content', $post_id );
			$legacy_after  = LegacyShortcodeConversionService::count_legacy_blocks( wp_unslash( $saved_content ) );

			if ( 'legacy_conversion' === $reason ) {
				if ( LegacyShortcodeConversionService::content_needs_legacy_conversion( $saved_content ) && $legacy_after >= $legacy_before ) {
					return array(
						'success'       => false,
						'legacy_before' => $legacy_before,
						'legacy_after'  => $legacy_after,
						'resave_reason' => $reason,
						'message'       => __(
							'Re-save completed but legacy shortcode-module blocks remain.',
							'dsm-supreme-modules-pro-for-divi'
						),
					);
				}

				if ( $legacy_after > 0 ) {
					return array(
						'success'       => true,
						'partial'       => true,
						'legacy_before' => $legacy_before,
						'legacy_after'  => $legacy_after,
						'resave_reason' => $reason,
						'message'       => sprintf(
							/* translators: %d: number of legacy blocks still stored */
							_n(
								'%d legacy module block remains after re-save.',
								'%d legacy module blocks remain after re-save.',
								$legacy_after,
								'dsm-supreme-modules-pro-for-divi'
							),
							$legacy_after
						),
					);
				}
			}

			return array(
				'success'       => true,
				'legacy_before' => $legacy_before,
				'legacy_after'  => $legacy_after,
				'resave_reason' => $reason,
			);
		} catch ( \Throwable $exception ) {
			return array(
				'success' => false,
				'message' => $exception->getMessage(),
			);
		}
	}
}
