<?php
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template variables are scoped when required inside the block render callback.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

require_once dirname( __DIR__, 3 ) . '/includes/block-css-generator.php';
require_once dirname( __DIR__, 3 ) . '/includes/render-helpers/bodycopy-content.php';

// ─── Tag & identity ───────────────────────────────────────────────────────────

$tag_name     = isset( $attributes['tagName'] ) ? strtolower( (string) $attributes['tagName'] ) : 'p';
$allowed_tags = [ 'p', 'div', 'span', 'section', 'article', 'aside', 'header', 'footer', 'main', 'blockquote', 'figcaption' ];
$tag_name     = tag_escape( in_array( $tag_name, $allowed_tags, true ) ? $tag_name : 'p' );
$anchor       = isset( $attributes['anchor'] ) ? sanitize_title( $attributes['anchor'] ) : '';
$unique_class = isset( $attributes['uniqueClass'] ) ? sanitize_html_class( $attributes['uniqueClass'] ) : '';
if ( empty( $unique_class ) ) {
	$unique_class = sanitize_html_class( 'axb-' . wp_unique_id() );
}

// ─── Wrapper attributes ───────────────────────────────────────────────────────
// `has-icon` flips the block into the icon-beside-text flex layout (see
// shared-frontend.scss). Without an icon the block stays a normal paragraph so its
// inline content (<strong>, <a>, line breaks) flows naturally.

$icon_present = ! empty( $attributes['iconSvg'] );
$extra_attrs  = [
	'class' => trim( 'axcelersblocks-bodycopy__text ' . $unique_class . ( $icon_present ? ' has-icon' : '' ) ),
];
if ( $anchor ) {
	$extra_attrs['id'] = $anchor;
}
$wrapper_attrs = get_block_wrapper_attributes( $extra_attrs );

// ─── Link options (needed before CSS so is_linked context is correct) ─────────

$link_option  = $attributes['linkOption']  ?? 'none';
$custom_link  = isset( $attributes['customLink'] ) ? esc_url( $attributes['customLink'] ) : '';
$open_new_tab = ! empty( $attributes['openInNewTab'] );
$target_attr  = $open_new_tab ? ' target="_blank"' : '';
$link_title   = isset( $attributes['linkTitle'] ) ? sanitize_text_field( $attributes['linkTitle'] ) : '';
$aria_label   = isset( $attributes['ariaLabel'] ) ? sanitize_text_field( $attributes['ariaLabel'] ) : '';
$rel_tokens   = [];

if ( $open_new_tab ) {
	$rel_tokens[] = 'noopener';
	$rel_tokens[] = 'noreferrer';
}
if ( ! empty( $attributes['relNoFollow'] ) ) {
	$rel_tokens[] = 'nofollow';
}
if ( ! empty( $attributes['relSponsored'] ) ) {
	$rel_tokens[] = 'sponsored';
}
if ( ! empty( $attributes['relUgc'] ) ) {
	$rel_tokens[] = 'ugc';
}

$rel_value       = implode( ' ', array_unique( array_filter( $rel_tokens ) ) );
$rel_attr        = $rel_value ? ' rel="' . esc_attr( $rel_value ) . '"' : '';
$link_title_attr = $link_title ? ' title="' . esc_attr( $link_title ) . '"' : '';
$aria_label_attr = $aria_label ? ' aria-label="' . esc_attr( $aria_label ) . '"' : '';
$required     = array_key_exists( 'required', $attributes ) ? (bool) $attributes['required'] : true;
$is_linked    = $custom_link !== '' || ( ! empty( $attributes['dynamicTag'] ) && $link_option !== 'none' );

// ─── CSS generation & collection ──────────────────────────────────────────────

$devices = axcelersblocks_get_responsive_devices();

// column-gap is purely the icon↔text gap (only meaningful in the .has-icon flex
// layout). Without an icon there's no flex, so don't emit it at all.
$main_attributes = $attributes;
if ( ! $icon_present ) {
	unset( $main_attributes['columnGap'] );
}
$styles_css = axcelersblocks_generate_block_styles( $unique_class, $devices, $main_attributes, [ 'is_linked' => $is_linked ] );

// Content tab: the text span (.axcelersblocks-bodycopy__content) carries its own
// full style set, stored under the `contentStyles` object and emitted to the span
// via the generator's element_suffix.
$content_styles = ( isset( $attributes['contentStyles'] ) && is_array( $attributes['contentStyles'] ) ) ? $attributes['contentStyles'] : [];
$content_css    = axcelersblocks_generate_block_styles(
	$unique_class,
	$devices,
	$content_styles,
	[ 'element_suffix' => ' .axcelersblocks-bodycopy__content', 'has_icon' => false, 'is_linked' => false ]
);

axcelersblocks_collect_block_styles( $unique_class, $block, array_merge( $styles_css, $content_css ) );

// ─── Icon ─────────────────────────────────────────────────────────────────────

$icon_loc  = $attributes['iconLocation'] ?? 'before';
$icon_html = '';
if ( ! empty( $attributes['iconSvg'] ) ) {
	$icon_svg  = wp_kses( $attributes['iconSvg'], axcelersblocks_get_allowed_svg_html() );
	$icon_html = $icon_svg ? sprintf( '<span class="icon">%s</span>', $icon_svg ) : '';
}

// ─── Content ──────────────────────────────────────────────────────────────────

$content_markup = '';
$link_href      = '';
$author_href    = '';
$term_href      = '';

if ( ! empty( $attributes['dynamicTag'] ) ) {
	$resolved       = axcelersblocks_bodycopy_resolve_dynamic( $attributes );
	$content_markup = $resolved['markup'];
	$link_href      = $resolved['link_href'];
	$author_href    = $resolved['author_href'];
	$term_href      = $resolved['term_href'];
} elseif ( ! empty( $attributes['content'] ) ) {
	$content_markup = wp_kses_post( $attributes['content'] );
} elseif ( empty( $icon_html ) ) {
	$content_markup = $required ? esc_html__( '(No content provided)', 'axcelersblocks' ) : '';
}

// ─── Assemble inner content ───────────────────────────────────────────────────
// The text is wrapped in its own .__content element so that — when the icon flex
// layout is active — it stays a single flex item and its inline content is never
// split into per-word / per-tag flex items.

$content_html = '' !== $content_markup
	? '<span class="axcelersblocks-bodycopy__content">' . $content_markup . '</span>'
	: '';

$inner = $icon_loc === 'before'
	? $icon_html . $content_html
	: $content_html . $icon_html;

// ─── Link resolution ──────────────────────────────────────────────────────────

$resolved_link = '';
if ( $custom_link ) {
	$resolved_link = $custom_link;
} elseif ( ! empty( $attributes['dynamicTag'] ) && $link_option !== 'none' ) {
	$selected_tag = $attributes['selectedTag'] ?? 'post_excerpt';
	if ( $selected_tag === 'post_author' && $link_option === 'author' && $author_href ) {
		$resolved_link = esc_url( $author_href );
	} elseif ( $link_option === 'post' && $link_href ) {
		$resolved_link = in_array( $selected_tag, array( 'comments_count', 'comments_url' ), true )
			? esc_url( $link_href . '#comments' )
			: esc_url( $link_href );
	} elseif ( $link_option === 'term' && $term_href ) {
		$resolved_link = esc_url( $term_href );
	}
}

// ─── Output — <a> wraps <tag> from OUTSIDE (same pattern as Heading) ──────────

$block_html = sprintf(
	'<%1$s %2$s>%3$s</%1$s>',
	esc_attr( $tag_name ),
	$wrapper_attrs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	wp_kses( $inner, axcelersblocks_get_allowed_svg_html() )
);

if ( $resolved_link ) {
	$link_class = sanitize_html_class( $unique_class ) . '-link';
	printf(
		'<a href="%1$s" class="%2$s"%3$s%4$s%5$s%6$s>%7$s</a>',
		esc_url( $resolved_link ),
		esc_attr( $link_class ),
		$target_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Hardcoded safe attribute fragment.
		$rel_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Hardcoded safe attribute fragment.
		$link_title_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped safe attribute fragment.
		$aria_label_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped safe attribute fragment.
		$block_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	);
} else {
	echo $block_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
