<?php
/**
 * Server-side render for blocksify/image.
 *
 * Image is a fully dynamic block — `save.js` returns `null`, so saved
 * markup is just the comment delimiter and this file builds the entire
 * frontend HTML from `$attributes`. Per-instance CSS comes from
 * `Blocksify_CSS_Pipeline` (single-handle pool at `wp_enqueue_scripts`).
 * Block-local rules (aspect-ratio / object-fit / object-position) emit
 * via `Blocksify_CSS_Generator::emit_image_local_rules` which the
 * pipeline picks up through the adapter map.
 *
 * Output shape — single `<figure>` (or `<div>`) wrapping the `<img>`,
 * with optional `<a>` link wrapper around the `<img>` and optional
 * `<figcaption>` sibling:
 *
 *   <figure[ class="is-align-X"][ id="..."]>
 *     [<a href="..." target="..." rel="...">]
 *       <img class="bsy-image-{uid}[ wp-image-{id}]"
 *            src="..." alt="..." width="..." height="..."
 *            loading="lazy" />
 *     [</a>]
 *     [<figcaption>...</figcaption>]
 *   </figure>
 *
 * No outer wrapper (no BlockRoot) — `<figure>` is already block-level
 * and absorbs the host theme's content-area treatment naturally.
 *
 * Lightbox: DEFERRED to Phase 2. Toggle persists attribute; render emits
 * no markup/runtime. Re-using core/image's lightbox needs a full markup
 * shim (wp-lightbox-container + 6 img-level directives + trigger button +
 * svg + specific data-wp-context shape) — too tight a coupling to private
 * core markup for MVP. See docs/SPEC-image-block.md §7 for Phase 2 paths.
 *
 * @package Blocksify
 *
 * @var array    $attributes Block attributes.
 * @var string   $content    Saved block markup (always empty for dynamic).
 * @var WP_Block $block      Parsed block instance.
 */

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

if ( isset( $_GET['blocksify_debug'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	$debug_css = Blocksify_CSS_Generator::generate_block_css( 'blocksify/image', $attributes );
	echo "\n<!-- Blocksify Image CSS:\n" . esc_html( $debug_css ) . "\n-->\n";
}

$allowed_tags = array( 'figure', 'div' );
$tag          = isset( $attributes['tagName'] ) && in_array( $attributes['tagName'], $allowed_tags, true )
	? $attributes['tagName']
	: 'figure';

$uid         = isset( $attributes['uid'] ) ? (string) $attributes['uid'] : '';
$id          = isset( $attributes['id'] ) ? (int) $attributes['id'] : 0;
$url         = isset( $attributes['url'] ) ? (string) $attributes['url'] : '';
$alt         = isset( $attributes['alt'] ) ? (string) $attributes['alt'] : '';
$caption     = isset( $attributes['caption'] ) ? (string) $attributes['caption'] : '';
$width       = isset( $attributes['width'] ) ? (int) $attributes['width'] : 0;
$height      = isset( $attributes['height'] ) ? (int) $attributes['height'] : 0;
$user_class  = isset( $attributes['className'] ) ? trim( (string) $attributes['className'] ) : '';
$anchor      = isset( $attributes['anchor'] ) ? (string) $attributes['anchor'] : '';

$allowed_loading = array( 'lazy', 'eager' );
$loading_raw     = isset( $attributes['loading'] ) ? (string) $attributes['loading'] : 'lazy';
$loading         = in_array( $loading_raw, $allowed_loading, true ) ? $loading_raw : 'lazy';

$allowed_align = array( 'left', 'center', 'right' );
$align_raw     = isset( $attributes['imageAlignment'] ) ? (string) $attributes['imageAlignment'] : '';
$align         = in_array( $align_raw, $allowed_align, true ) ? $align_raw : '';

$allowed_link_to = array( 'none', 'media', 'custom' );
$link_to_raw     = isset( $attributes['linkTo'] ) ? (string) $attributes['linkTo'] : 'none';
$link_to         = in_array( $link_to_raw, $allowed_link_to, true ) ? $link_to_raw : 'none';
$url_link        = isset( $attributes['url_link'] ) ? (string) $attributes['url_link'] : '';
$link_target     = isset( $attributes['linkTarget'] ) ? (string) $attributes['linkTarget'] : '';
$rel             = isset( $attributes['rel'] ) ? (string) $attributes['rel'] : '';
$show_link       = 'none' !== $link_to && '' !== $url_link;

$figure_classes = array();
if ( '' !== $align ) {
	$figure_classes[] = 'is-align-' . $align;
}
$figure_class_attr = implode( ' ', $figure_classes );
$figure_attrs      = '' !== $figure_class_attr ? ' class="' . esc_attr( $figure_class_attr ) . '"' : '';
if ( '' !== $anchor ) {
	$figure_attrs .= ' id="' . esc_attr( $anchor ) . '"';
}

if ( '' === $url ) {
	echo '<' . esc_attr( $tag ) . $figure_attrs . '></' . esc_attr( $tag ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	return;
}

$img_classes = array();
if ( '' !== $uid ) {
	$img_classes[] = 'bsy-image-' . preg_replace( '/[^a-z0-9_-]/i', '', $uid );
}
if ( $id > 0 ) {
	$img_classes[] = 'wp-image-' . $id;
}
if ( '' !== $user_class ) {
	$img_classes[] = $user_class;
}
$img_class_attr = esc_attr( implode( ' ', $img_classes ) );

$img_attrs  = ' class="' . $img_class_attr . '"';
$img_attrs .= ' src="' . esc_url( $url ) . '"';
$img_attrs .= ' alt="' . esc_attr( $alt ) . '"';
if ( $width > 0 ) {
	$img_attrs .= ' width="' . $width . '"';
}
if ( $height > 0 ) {
	$img_attrs .= ' height="' . $height . '"';
}
$img_attrs .= ' loading="' . esc_attr( $loading ) . '"';

$img_html = '<img' . $img_attrs . ' />';

if ( $show_link ) {
	$link_attrs  = ' href="' . esc_url( $url_link ) . '"';
	if ( '' !== $link_target ) {
		$link_attrs .= ' target="' . esc_attr( $link_target ) . '"';
	}
	if ( '' !== $rel ) {
		$link_attrs .= ' rel="' . esc_attr( $rel ) . '"';
	}
	$img_html = '<a' . $link_attrs . '>' . $img_html . '</a>';
}

$caption_html = '';
if ( '' !== trim( $caption ) ) {
	// Caption was authored via `<RichText>` in edit.js; sanitization
	// runs at commit time. Echoed without `wp_kses` because the JS
	// allowlist is the single source of truth.
	$caption_html = '<figcaption>' . $caption . '</figcaption>';
}

echo '<' . esc_attr( $tag ) . $figure_attrs . '>' . $img_html . $caption_html . '</' . esc_attr( $tag ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
