<?php
/**
 * Custom Fields — post edit screen layout helpers.
 *
 * Handles the custom "after title" meta box zone and block editor compatibility.
 *
 * @package CustomFields
 * @since 1.10.0
 */

namespace CustomFields;

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

/**
 * Post edit screen integration for meta box positioning.
 */
final class PostEditForm {

	/**
	 * Register hooks for after-title rendering and block editor shims.
	 */
	public function register(): void {
		add_action( 'edit_form_after_title', [ $this, 'renderAfterTitleMetaBoxes' ] );
		add_filter( 'filter_block_editor_meta_boxes', [ $this, 'filterBlockEditorMetaBoxes' ] );
		add_filter( 'get_user_option', [ $this, 'mergeAfterTitleMetaBoxOrder' ], 10, 3 );
	}

	/**
	 * Output meta boxes registered in the custom after-title context.
	 *
	 * @param \WP_Post $post Current post.
	 */
	public function renderAfterTitleMetaBoxes( \WP_Post $post ): void {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( ! $screen || $screen->base !== 'post' ) {
			return;
		}

		echo '<div id="wpps-cf-after-title-sortables" class="meta-box-sortables">';
		do_meta_boxes( $screen, Config::AFTER_TITLE_CONTEXT, $post );
		echo '</div>';
	}

	/**
	 * Move after-title meta boxes into the normal column for the block editor.
	 *
	 * @param array<string, mixed> $meta_boxes Registered meta boxes.
	 * @return array<string, mixed>
	 */
	public function filterBlockEditorMetaBoxes( array $meta_boxes ): array {
		if ( ! isset( $meta_boxes[ Config::AFTER_TITLE_CONTEXT ] ) || ! is_array( $meta_boxes[ Config::AFTER_TITLE_CONTEXT ] ) ) {
			return $meta_boxes;
		}

		foreach ( $meta_boxes[ Config::AFTER_TITLE_CONTEXT ] as $id => $box ) {
			if ( ! is_array( $box ) ) {
				continue;
			}

			$box['context']  = 'normal';
			$box['priority'] = 'high';
			$meta_boxes['normal'][ $id ] = $box;
		}

		unset( $meta_boxes[ Config::AFTER_TITLE_CONTEXT ] );

		return $meta_boxes;
	}

	/**
	 * Prepend saved after-title meta box order into the normal column order.
	 *
	 * @param mixed  $value       Option value.
	 * @param int    $user_id     User ID.
	 * @param string $option_name Option name.
	 * @return mixed
	 */
	public function mergeAfterTitleMetaBoxOrder( mixed $value, int $user_id, string $option_name ): mixed {
		unset( $user_id );

		if ( ! is_string( $option_name ) || ! str_starts_with( $option_name, 'meta-box-order_' ) ) {
			return $value;
		}

		if ( ! is_array( $value ) ) {
			$value = [];
		}

		$after_title = get_user_option( str_replace( 'meta-box-order_', 'meta-box-order_' . Config::AFTER_TITLE_CONTEXT . '_', $option_name ) );
		if ( ! is_array( $after_title ) || $after_title === [] ) {
			$after_title_key = Config::AFTER_TITLE_CONTEXT;
			if ( isset( $value[ $after_title_key ] ) && is_array( $value[ $after_title_key ] ) ) {
				$after_title = $value[ $after_title_key ];
			}
		}

		$normal = isset( $value['normal'] ) && is_array( $value['normal'] ) ? $value['normal'] : [];
		if ( is_array( $after_title ) && $after_title !== [] ) {
			$value['normal'] = array_values( array_unique( array_merge( $after_title, $normal ) ) );
		}

		return $value;
	}
}
