<?php
/**
 * Per-post meta box.
 *
 * Lets editors override plugin settings on a post-by-post basis:
 *   - Post count
 *   - Layout
 *   - Relate By (taxonomy matching strategy)
 *   - Pinned posts (always shown first)
 *   - Disabled (hide related posts for this post only)
 *
 * Meta key: _igit_rpwt  (serialised array, private)
 *
 * @package IGIT_RPWT
 */

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

class IGIT_RPWT_Metabox {

	/**
	 * Meta key used to store per-post overrides.
	 */
	const META_KEY = '_igit_rpwt';

	/**
	 * Nonce action / name.
	 */
	const NONCE_ACTION = 'igit_rpwt_meta_save';
	const NONCE_NAME   = 'igit_rpwt_meta_nonce';

	public function __construct() {
		add_action( 'add_meta_boxes',  array( $this, 'add_meta_box' ) );
		add_action( 'save_post',       array( $this, 'save_meta' ), 20 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	// ── Registration ─────────────────────────────────────────────────────────

	/**
	 * Register the meta box on all public post types.
	 */
	public function add_meta_box() {
		$post_types = get_post_types( array( 'public' => true ) );
		foreach ( $post_types as $pt ) {
			add_meta_box(
				'igit-rpwt-meta',
				__( 'Related Posts Settings', 'igit-related-posts-with-thumb-images-after-posts' ),
				array( $this, 'render_meta_box' ),
				$pt,
				'side',
				'default'
			);
		}
	}

	// ── Render ───────────────────────────────────────────────────────────────

	/**
	 * Output the meta box HTML.
	 *
	 * @param WP_Post $post
	 */
	public function render_meta_box( $post ) {
		$meta     = $this->get_meta( $post->ID );
		$settings = IGIT_RPWT_Settings::get_all();
		$opt      = IGIT_RPWT_Settings::OPTION_KEY;

		wp_nonce_field( self::NONCE_ACTION, self::NONCE_NAME );
		?>
		<div class="igit-rpwt-metabox">

			<!-- Disable toggle -->
			<p class="igit-rpwt-meta-row igit-rpwt-meta-row--toggle">
				<label>
					<input type="checkbox"
						name="igit_rpwt_meta[disabled]"
						value="1"
						<?php checked( true, ! empty( $meta['disabled'] ) ); ?>
					/>
					<?php esc_html_e( 'Hide related posts for this post', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</label>
			</p>

			<hr class="igit-rpwt-meta-divider" />

			<p class="igit-rpwt-meta-desc">
				<?php esc_html_e( 'Leave fields blank/default to use global settings.', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
			</p>

			<!-- Post count -->
			<p class="igit-rpwt-meta-row">
				<label for="igit_rpwt_meta_post_count">
					<?php esc_html_e( 'Number of posts', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</label>
				<input
					type="number"
					id="igit_rpwt_meta_post_count"
					name="igit_rpwt_meta[post_count]"
					value="<?php echo esc_attr( $meta['post_count'] ); ?>"
					min="1" max="20"
					placeholder="<?php echo esc_attr( $settings['post_count'] ); ?>"
					class="small-text"
				/>
			</p>

			<!-- Layout -->
			<p class="igit-rpwt-meta-row">
				<label for="igit_rpwt_meta_layout">
					<?php esc_html_e( 'Layout', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</label>
				<select id="igit_rpwt_meta_layout" name="igit_rpwt_meta[layout]">
					<option value=""><?php esc_html_e( '— Global default —', 'igit-related-posts-with-thumb-images-after-posts' ); ?></option>
					<?php
					foreach ( array( 'grid' => __( 'Grid', 'igit-related-posts-with-thumb-images-after-posts' ), 'list' => __( 'List', 'igit-related-posts-with-thumb-images-after-posts' ), 'compact' => __( 'Compact', 'igit-related-posts-with-thumb-images-after-posts' ) ) as $val => $lbl ) {
						printf(
							'<option value="%s" %s>%s</option>',
							esc_attr( $val ),
							selected( $meta['layout'], $val, false ),
							esc_html( $lbl )
						);
					}
					?>
				</select>
			</p>

			<!-- Relate By -->
			<p class="igit-rpwt-meta-row">
				<label for="igit_rpwt_meta_relate_by">
					<?php esc_html_e( 'Match by', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</label>
				<select id="igit_rpwt_meta_relate_by" name="igit_rpwt_meta[relate_by]">
					<option value=""><?php esc_html_e( '— Global default —', 'igit-related-posts-with-thumb-images-after-posts' ); ?></option>
					<?php
					foreach ( array(
						'both'     => __( 'Category &amp; Tag', 'igit-related-posts-with-thumb-images-after-posts' ),
						'category' => __( 'Category only', 'igit-related-posts-with-thumb-images-after-posts' ),
						'tag'      => __( 'Tag only', 'igit-related-posts-with-thumb-images-after-posts' ),
					) as $val => $lbl ) {
						printf(
							'<option value="%s" %s>%s</option>',
							esc_attr( $val ),
							selected( $meta['relate_by'], $val, false ),
							wp_kses_post( $lbl )
						);
					}
					?>
				</select>
			</p>

			<!-- Pinned posts -->
			<p class="igit-rpwt-meta-row">
				<label for="igit_rpwt_meta_pinned">
					<?php esc_html_e( 'Pinned post IDs', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</label>
				<input
					type="text"
					id="igit_rpwt_meta_pinned"
					name="igit_rpwt_meta[pinned_posts]"
					value="<?php echo esc_attr( implode( ', ', $meta['pinned_posts'] ) ); ?>"
					placeholder="e.g. 12, 45, 99"
					class="widefat"
				/>
				<span class="description">
					<?php esc_html_e( 'These posts are always shown first (comma-separated IDs).', 'igit-related-posts-with-thumb-images-after-posts' ); ?>
				</span>
			</p>

		</div>
		<?php
	}

	// ── Save ─────────────────────────────────────────────────────────────────

	/**
	 * Validate nonce, capability, then persist meta.
	 *
	 * @param int $post_id
	 */
	public function save_meta( $post_id ) {
		// Nonce check.
		if (
			! isset( $_POST[ self::NONCE_NAME ] )
			|| ! wp_verify_nonce( sanitize_key( $_POST[ self::NONCE_NAME ] ), self::NONCE_ACTION )
		) {
			return;
		}

		// Skip autosaves, revisions, AJAX saves.
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}
		if ( wp_is_post_revision( $post_id ) ) {
			return;
		}

		// Capability check.
		$post_type = get_post_type( $post_id );
		$post_type_obj = $post_type ? get_post_type_object( $post_type ) : null;
		if ( ! $post_type_obj || ! current_user_can( $post_type_obj->cap->edit_post, $post_id ) ) {
			return;
		}

		// Sanitise and save.
		$raw = isset( $_POST['igit_rpwt_meta'] ) && is_array( $_POST['igit_rpwt_meta'] )
			? $_POST['igit_rpwt_meta'] // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
			: array();

		update_post_meta( $post_id, self::META_KEY, $this->sanitise_meta( $raw ) );
	}

	// ── Helpers ──────────────────────────────────────────────────────────────

	/**
	 * Return the meta array for a post, merged with empty defaults.
	 *
	 * @param int $post_id
	 * @return array
	 */
	public static function get_meta( $post_id ) {
		$saved = get_post_meta( $post_id, self::META_KEY, true );
		$saved = is_array( $saved ) ? $saved : array();
		return wp_parse_args( $saved, array(
			'disabled'    => false,
			'post_count'  => '',
			'layout'      => '',
			'relate_by'   => '',
			'pinned_posts' => array(),
		) );
	}

	/**
	 * Sanitise raw POST input for the meta box.
	 *
	 * @param array $raw
	 * @return array
	 */
	private function sanitise_meta( array $raw ) {
		$pinned_raw   = isset( $raw['pinned_posts'] ) ? $raw['pinned_posts'] : '';
		$pinned_ids   = is_array( $pinned_raw )
			? array_values( array_filter( array_map( 'absint', $pinned_raw ) ) )
			: array_values( array_filter( array_map( 'absint', array_map( 'trim', explode( ',', $pinned_raw ) ) ) ) );

		return array(
			'disabled'     => ! empty( $raw['disabled'] ),
			'post_count'   => isset( $raw['post_count'] ) && '' !== $raw['post_count']
				? min( 20, max( 1, absint( $raw['post_count'] ) ) )
				: '',
			'layout'       => in_array( $raw['layout'] ?? '', array( 'grid', 'list', 'compact' ), true )
				? $raw['layout']
				: '',
			'relate_by'    => in_array( $raw['relate_by'] ?? '', array( 'both', 'category', 'tag' ), true )
				? $raw['relate_by']
				: '',
			'pinned_posts' => $pinned_ids,
		);
	}

	// ── Assets ───────────────────────────────────────────────────────────────

	/**
	 * Enqueue meta box styles on post edit screens.
	 *
	 * @param string $hook
	 */
	public function enqueue_assets( $hook ) {
		if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
			return;
		}
		wp_enqueue_style(
			'igit-rpwt-metabox',
			IGIT_RPWT_PLUGIN_URL . 'assets/css/metabox.css',
			array(),
			IGIT_RPWT_VERSION
		);
	}
}
