<?php
/**
 * Base class for all plugin blocks.
 *
 * Each subclass owns one block. Registration reads the block's manifest
 * (a `block.json` file under `blocks/{slug}/`) and binds the subclass's
 * `render()` method as the server-side renderer.
 *
 * Why server-side only: avoids a JS build pipeline for v1, keeps blocks
 * cacheable, and reuses the existing PHP template parts. The editor
 * preview comes from `register_block_type`'s built-in handling — WP
 * inserts a "preview" iframe that calls the same render_callback, so
 * authors see the real output as they tweak attributes.
 *
 * @package ThemeREX\AutoDealer
 * @version 1.0.0
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Blocks;

defined( 'ABSPATH' ) || exit;
/**
 * Each plugin block extends this and provides a slug + render method.
 */
abstract class AbstractBlock {

	/**
	 * Block slug (without the namespace). Must match the directory name
	 * under `blocks/` and the `name` in `block.json` after the slash.
	 *
	 * @var string
	 */
	protected string $slug = '';

	/**
	 * Register the block via its manifest.
	 *
	 * Hooked at `init` priority 10 (default for `register_block_type`).
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'init', array( $this, 'registerBlockType' ) );
	}

	/**
	 * `register_block_type` callback — invoked on `init`.
	 *
	 * @return void
	 */
	public function registerBlockType(): void {
		$path = $this->blockJsonPath();
		if ( '' === $path || ! is_readable( $path ) ) {
			return;
		}

		register_block_type(
			dirname( $path ),
			array(
				'render_callback' => array( $this, 'render' ),
			)
		);
	}

	/**
	 * Absolute path to this block's `block.json` manifest.
	 *
	 * @return string
	 */
	protected function blockJsonPath(): string {
		if ( '' === $this->slug ) {
			return '';
		}
		return TRX_AD_PATH . 'blocks/' . $this->slug . '/block.json';
	}

	/**
	 * Render the block's server-side output.
	 *
	 * @param array<string, mixed> $attributes Block attributes from the editor.
	 * @param string               $content    InnerBlocks content (always empty for our leaf blocks).
	 * @param \WP_Block            $block      Block instance.
	 * @return string Rendered HTML.
	 */
	abstract public function render( array $attributes, string $content = '', $block = null ): string;

	/**
	 * Convenience: capture the output of a callable into a string.
	 *
	 * @param callable $fn
	 * @return string
	 */
	protected static function capture( callable $fn ): string {
		ob_start();
		$fn();
		return (string) ob_get_clean();
	}
}
