<?php
/**
 * Runtime layout renderer — generates HTML/CSS/JS from canvas_data.
 *
 * Developer customizations are applied via oppb_layout_* filters (never stored in DB).
 * Pro preset assets are merged in LayoutExporter via the oppb_preset_assets filter.
 *
 * @package OpusPriceBuilder\Export
 */

declare(strict_types=1);

namespace OpusPriceBuilder\Export;

/**
 * Centralizes sanitize → export → filter pipeline for frontend rendering.
 */
class LayoutRenderer {

	/**
	 * Render a layout at runtime from stored canvas data.
	 *
	 * @param array<string, mixed> $layout   Layout row from database.
	 * @param array<string, mixed> $context  Render context (scenario, location, product_id).
	 * @return array{html: string, css: string, js: string}
	 */
	public static function render( array $layout, array $context = array() ): array {
		$layout_id   = (int) ( $layout['id'] ?? 0 );
		$canvas_data = self::parseCanvasData( $layout['canvas_data'] ?? '' );

		if ( empty( $canvas_data ) ) {
			return array(
				'html' => '',
				'css'  => '',
				'js'   => '',
			);
		}

		$sanitized = CanvasSanitizer::sanitize( $canvas_data );
		$exported  = LayoutExporter::export( $sanitized );
		$html      = CanvasPlaceholders::apply(
			$exported['exported_html'],
			is_array( $sanitized['elements'] ?? null ) ? $sanitized['elements'] : array()
		);

		$filter_context = array_merge(
			$context,
			array(
				'layout_id'   => $layout_id,
				'elements'    => $sanitized['elements'] ?? array(),
				'canvas_data' => $sanitized,
				'preset_id'   => $sanitized['presetId'] ?? '',
			)
		);

		$html = (string) apply_filters( 'oppb_layout_html', $html, $layout_id, $filter_context );
		$css  = (string) apply_filters( 'oppb_layout_css', $exported['exported_css'], $layout_id, $filter_context );
		$js   = (string) apply_filters( 'oppb_layout_js', $exported['exported_js'], $layout_id, $filter_context );

		return array(
			'html' => $html,
			'css'  => $css,
			'js'   => $js,
		);
	}

	/**
	 * Parse canvas_data JSON string or array.
	 *
	 * @param mixed $canvas_data Raw canvas data.
	 * @return array<string, mixed>
	 */
	private static function parseCanvasData( $canvas_data ): array {
		if ( is_array( $canvas_data ) ) {
			return $canvas_data;
		}

		if ( ! is_string( $canvas_data ) || '' === $canvas_data ) {
			return array();
		}

		$decoded = json_decode( $canvas_data, true );

		return is_array( $decoded ) ? $decoded : array();
	}

}
