<?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/video-css.php';
require_once dirname( __DIR__, 3 ) . '/includes/render-helpers/video-embed.php';
require_once dirname( __DIR__, 3 ) . '/includes/svg-support.php';

// ─── Attributes ───────────────────────────────────────────────────────────────

$anchor       = isset( $attributes['anchor'] ) ? sanitize_title( $attributes['anchor'] ) : '';
$open_in_new  = ! empty( $attributes['openInNewTab'] );
$unique_class = isset( $attributes['uniqueClass'] ) ? sanitize_html_class( $attributes['uniqueClass'] ) : '';
if ( empty( $unique_class ) ) {
	$unique_class = sanitize_html_class( 'axb-' . wp_unique_id() );
}

$video_id    = isset( $attributes['videoId'] ) ? (int) $attributes['videoId'] : 0;
$video_url   = isset( $attributes['videoUrl'] ) ? esc_url_raw( $attributes['videoUrl'] ) : '';
$video_type  = isset( $attributes['videoType'] ) ? sanitize_text_field( $attributes['videoType'] ) : '';
$poster_id   = isset( $attributes['posterId'] ) ? (int) $attributes['posterId'] : 0;
$poster_url  = isset( $attributes['posterUrl'] ) ? esc_url_raw( $attributes['posterUrl'] ) : '';

// Source mode: self-hosted <video> vs. streaming-platform embed (<iframe> / oEmbed).
$source_mode   = ( ( $attributes['sourceMode'] ?? 'self' ) === 'embed' ) ? 'embed' : 'self';
$is_embed      = ( 'embed' === $source_mode );
$embed_url     = isset( $attributes['embedUrl'] ) ? esc_url_raw( $attributes['embedUrl'] ) : '';
$embed_title   = isset( $attributes['embedTitle'] ) ? sanitize_text_field( $attributes['embedTitle'] ) : '';
$embed_ratio   = isset( $attributes['embedAspectRatio'] ) ? (string) $attributes['embedAspectRatio'] : '16 / 9';
$embed_ratio   = preg_match( '#^\s*\d+(?:\.\d+)?\s*/\s*\d+(?:\.\d+)?\s*$#', $embed_ratio ) ? $embed_ratio : '16 / 9';

// Playback options → native <video> attributes.
$controls    = ! empty( $attributes['controls'] );
$autoplay    = ! empty( $attributes['autoplay'] );
$muted       = ! empty( $attributes['muted'] ) || $autoplay; // Autoplay requires muted.
$loop        = ! empty( $attributes['loop'] );
$playsinline = ! empty( $attributes['playsInline'] );
$preload     = $attributes['preload'] ?? 'metadata';
$preload     = in_array( $preload, [ 'auto', 'metadata', 'none' ], true ) ? $preload : 'metadata';
$disable_pip = ! empty( $attributes['disablePictureInPicture'] );

$controls_list = [];
if ( ! empty( $attributes['controlsNoDownload'] ) )       { $controls_list[] = 'nodownload'; }
if ( ! empty( $attributes['controlsNoFullscreen'] ) )     { $controls_list[] = 'nofullscreen'; }
if ( ! empty( $attributes['controlsNoRemotePlayback'] ) ) { $controls_list[] = 'noremoteplayback'; }

$custom_play_overlay             = ! empty( $attributes['customPlayOverlay'] ) && ! $autoplay;
$hide_native_controls_until_play = ! empty( $attributes['hideNativeControlsUntilPlay'] );
$show_controls_on_play           = $custom_play_overlay && $hide_native_controls_until_play && $controls;
$play_button_label               = isset( $attributes['playButtonLabel'] ) ? sanitize_text_field( $attributes['playButtonLabel'] ) : '';
if ( '' === $play_button_label ) {
	$play_button_label = __( 'Play video', 'axcelersblocks' );
}

$tracks = isset( $attributes['tracks'] ) && is_array( $attributes['tracks'] ) ? $attributes['tracks'] : [];

// Dynamic source.
$dynamic_tag   = $attributes['dynamicTag']  ?? '';
$selected_tag  = $attributes['selectedTag'] ?? '';
$source_type   = $attributes['sourceType']  ?? 'current';
$post_id_attr  = isset( $attributes['postId'] ) ? (int) $attributes['postId'] : 0;
$post_type     = isset( $attributes['postType'] ) ? sanitize_key( $attributes['postType'] ) : 'post';
$source_entity = $attributes['sourceEntity'] ?? 'post';
$taxonomy      = isset( $attributes['taxonomy'] ) ? sanitize_key( $attributes['taxonomy'] ) : 'category';
$term_id_attr  = isset( $attributes['termId'] ) ? (int) $attributes['termId'] : 0;
$meta_key      = isset( $attributes['metaKey'] ) ? sanitize_key( $attributes['metaKey'] ) : '';
$acf_field     = isset( $attributes['acfField'] ) ? sanitize_text_field( $attributes['acfField'] ) : '';
$acf_scope     = $attributes['acfScope']   ?? 'entity';

// Link.
$link_option = $attributes['linkOption'] ?? 'none';
$custom_link = isset( $attributes['customLink'] ) ? esc_url( $attributes['customLink'] ) : '';
$link_title  = isset( $attributes['linkTitle'] ) ? sanitize_text_field( $attributes['linkTitle'] ) : '';
$aria_label  = isset( $attributes['ariaLabel'] ) ? sanitize_text_field( $attributes['ariaLabel'] ) : '';

$rel_tokens = [];
if ( $open_in_new ) {
	$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 ) . '"' : '';

// ─── Dynamic state ────────────────────────────────────────────────────────────

$has_dynamic = ! empty( $dynamic_tag ) || in_array( $selected_tag, [ 'acf_field', 'post_meta', 'term_meta' ], true );

// ─── Normalise a dynamic value into { url, type } ─────────────────────────────

$normalize_to_video = static function ( $value ) {
	$out = [ 'url' => '', 'type' => '' ];
	$from_attachment = static function ( $att_id ) {
		$url = wp_get_attachment_url( $att_id );
		return [ 'url' => $url ? esc_url_raw( $url ) : '', 'type' => $url ? (string) get_post_mime_type( $att_id ) : '' ];
	};
	if ( is_numeric( $value ) ) {
		$att_id = (int) $value;
		return $att_id > 0 ? $from_attachment( $att_id ) : $out;
	}
	if ( is_array( $value ) && ! empty( $value ) ) {
		$maybe_id = $value['ID'] ?? $value['id'] ?? null;
		if ( is_numeric( $maybe_id ) ) {
			return $from_attachment( (int) $maybe_id );
		}
		if ( ! empty( $value['url'] ) ) {
			$out['url']  = esc_url_raw( $value['url'] );
			$out['type'] = isset( $value['mime_type'] ) ? sanitize_text_field( $value['mime_type'] ) : '';
			return $out;
		}
	}
	if ( is_string( $value ) && filter_var( $value, FILTER_VALIDATE_URL ) ) {
		$out['url'] = esc_url_raw( $value );
	}
	return $out;
};

// ─── Source resolution (dynamic → library ID → external URL) ──────────────────

$src       = '';
$src_type  = '';
$link_href = '';
$poster    = '';

if ( ! $is_embed ) :

$target_post_id = ( $source_type === 'specific' && $post_id_attr ) ? $post_id_attr : get_the_ID();

// ACF field.
if ( ! $src && $has_dynamic && ( $selected_tag === 'acf_field' || ( is_string( $dynamic_tag ) && strpos( $dynamic_tag, 'acf_field' ) !== false ) ) ) {
	$val = null;
	if ( function_exists( 'get_field' ) ) {
		if ( $acf_scope === 'options' ) {
			$val = $acf_field ? get_field( $acf_field, 'option' ) : null;
		} elseif ( $source_entity === 'term' && $term_id_attr ) {
			$val = $acf_field ? get_field( $acf_field, "{$taxonomy}_{$term_id_attr}" ) : null;
		} else {
			$val = ( $acf_field && $target_post_id ) ? get_field( $acf_field, $target_post_id ) : null;
		}
	} elseif ( $acf_scope === 'options' ) {
		$val = get_option( $acf_field );
	} elseif ( $source_entity === 'term' && $term_id_attr ) {
		$val = get_term_meta( $term_id_attr, $acf_field, true );
	} elseif ( $target_post_id ) {
		$val = get_post_meta( $target_post_id, $acf_field, true );
	}
	$resolved = $normalize_to_video( $val );
	if ( ! empty( $resolved['url'] ) ) {
		$src      = $resolved['url'];
		$src_type = $resolved['type'];
		if ( $link_option === 'term' && $term_id_attr ) {
			$tl = get_term_link( $term_id_attr, $taxonomy );
			if ( ! is_wp_error( $tl ) ) { $link_href = $tl; }
		} elseif ( $link_option === 'post' ) {
			$link_href = $target_post_id ? get_permalink( $target_post_id ) : '';
		}
	}
}

// Post meta.
if ( ! $src && $has_dynamic && ( $selected_tag === 'post_meta' || ( is_string( $dynamic_tag ) && strpos( $dynamic_tag, 'post_meta' ) !== false ) ) && $target_post_id && $meta_key ) {
	$resolved = $normalize_to_video( get_post_meta( $target_post_id, $meta_key, true ) );
	if ( ! empty( $resolved['url'] ) ) {
		$src      = $resolved['url'];
		$src_type = $resolved['type'];
		if ( $link_option === 'post' ) { $link_href = get_permalink( $target_post_id ); }
	}
}

// Term meta.
if ( ! $src && $has_dynamic && ( $selected_tag === 'term_meta' || ( is_string( $dynamic_tag ) && strpos( $dynamic_tag, 'term_meta' ) !== false ) ) && $term_id_attr && $meta_key ) {
	$resolved = $normalize_to_video( get_term_meta( $term_id_attr, $meta_key, true ) );
	if ( ! empty( $resolved['url'] ) ) {
		$src      = $resolved['url'];
		$src_type = $resolved['type'];
		if ( $link_option === 'term' ) {
			$tl = get_term_link( $term_id_attr, $taxonomy );
			if ( ! is_wp_error( $tl ) ) { $link_href = $tl; }
		}
	}
}

// Library video (by ID).
if ( ! $src && $video_id ) {
	$url = wp_get_attachment_url( $video_id );
	if ( $url ) {
		$src      = esc_url_raw( $url );
		$src_type = $video_type ?: (string) get_post_mime_type( $video_id );
		if ( $custom_link ) { $link_href = $custom_link; }
	}
}

// External URL.
if ( ! $src && $video_url ) {
	$src      = $video_url;
	$src_type = $video_type;
	if ( $custom_link ) { $link_href = $custom_link; }
}

// Guess the MIME type from the file extension when not already known.
if ( $src && ! $src_type ) {
	$ftype = wp_check_filetype( $src );
	if ( ! empty( $ftype['type'] ) ) {
		$src_type = $ftype['type'];
	}
}

// ─── Poster resolution ────────────────────────────────────────────────────────

if ( $poster_id ) {
	$poster = wp_get_attachment_image_url( $poster_id, 'large' ) ?: wp_get_attachment_url( $poster_id );
} elseif ( $poster_url ) {
	$poster = $poster_url;
}

// Match the editor preview: custom links take precedence over dynamic post/term
// links for any resolved self-hosted video source.
if ( $src && $custom_link ) {
	$link_href = $custom_link;
}

endif; // ! $is_embed

// ─── Custom play overlay styles ───────────────────────────────────────────────

$sanitize_play_style_value = static function ( $value ) {
	if ( ! is_scalar( $value ) ) {
		return '';
	}

	$value = trim( wp_strip_all_tags( (string) $value ) );

	if ( '' === $value ) {
		return '';
	}

	if ( preg_match( '/[;<>{}]|javascript\s*:|expression\s*\(|@import|behavior\s*:|url\s*\(/i', $value ) ) {
		return '';
	}

	return $value;
};

$play_overlay_style_map = [
	'playOverlayBackground'  => '--axb-video-play-overlay-bg',
	'playButtonBackground'   => '--axb-video-play-button-bg',
	'playButtonColor'        => '--axb-video-play-button-color',
	'playIconColor'          => '--axb-video-play-icon-color',
	'playButtonSize'         => '--axb-video-play-button-size',
	'playIconSize'           => '--axb-video-play-icon-size',
	'playButtonBorderRadius' => '--axb-video-play-button-radius',
	'playOverlayZIndex'      => '--axb-video-play-overlay-z-index',
	'playButtonZIndex'       => '--axb-video-play-button-z-index',
];

$play_overlay_style_decls = [];
if ( $custom_play_overlay ) {
	foreach ( $play_overlay_style_map as $attr_name => $css_var ) {
		$style_value = $sanitize_play_style_value( $attributes[ $attr_name ] ?? '' );

		if ( '' !== $style_value ) {
			$play_overlay_style_decls[] = $css_var . ': ' . $style_value;
		}
	}
}

// ─── Wrapper attributes (<figure>) ────────────────────────────────────────────

$wrapper_classes = [
	'axcelersblocks-video',
	$unique_class,
	$custom_play_overlay ? 'axcelersblocks-video--has-play-overlay' : '',
	$show_controls_on_play ? 'axcelersblocks-video--controls-on-play' : '',
];

$extra_attrs = [ 'class' => trim( implode( ' ', array_filter( $wrapper_classes ) ) ) ];
if ( $anchor ) {
	$extra_attrs['id'] = $anchor;
}
if ( $custom_play_overlay ) {
	$extra_attrs['data-axb-video-player'] = '1';
}
if ( $show_controls_on_play ) {
	$extra_attrs['data-axb-show-controls-on-play'] = '1';
}
if ( ! empty( $play_overlay_style_decls ) ) {
	$extra_attrs['style'] = implode( '; ', $play_overlay_style_decls ) . ';';
}
$wrapper_attrs = get_block_wrapper_attributes( $extra_attrs );

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

$is_linked  = ! $is_embed && ( $custom_link !== '' || ( $has_dynamic && $link_option !== 'none' ) );
$devices    = axcelersblocks_get_responsive_devices();
$styles_css = axcelersblocks_generate_block_styles( $unique_class, $devices, $attributes, [ 'is_linked' => $is_linked ] );
$video_css  = axcelersblocks_video_generate_video_css( $unique_class, $devices, $attributes );

// Embed iframes are sized by aspect-ratio (not the video sizing controls).
$embed_css = [];
if ( $is_embed ) {
	$embed_css[] = sprintf(
		'.%1$s .axcelersblocks-video__embed { width: 100%%; aspect-ratio: %2$s; border: 0; }',
		sanitize_html_class( $unique_class ),
		$embed_ratio
	);
}

axcelersblocks_collect_block_styles( $unique_class, $block, array_merge( $styles_css, $video_css, $embed_css ) );

// ─── Markup ───────────────────────────────────────────────────────────────────

if ( $is_embed ) {
	// Streaming-platform embed (YouTube / Vimeo / Dailymotion → iframe; anything
	// else → WordPress oEmbed).
	$inner = axcelersblocks_video_build_embed(
		$embed_url,
		[
			'autoplay'    => $autoplay,
			'muted'       => $muted,
			'loop'        => $loop,
			'controls'    => $controls,
			'playsinline' => $playsinline,
		],
		$embed_title
	);

	if ( '' === $inner ) {
		if ( empty( $attributes['showEmptyPlaceholder'] ) ) {
			return;
		}
		$inner = '<div class="axcelersblocks-video__placeholder"><div class="axcelersblocks-video__empty">'
			. '<span>' . esc_html__( 'No video', 'axcelersblocks' ) . '</span></div></div>';
	}
} elseif ( ! $src ) {
	// No video resolved. By default render nothing; with "Show placeholder when
	// empty" on, render the same empty-state UI the editor shows.
	if ( empty( $attributes['showEmptyPlaceholder'] ) ) {
		return;
	}
	$inner = '<div class="axcelersblocks-video__placeholder"><div class="axcelersblocks-video__empty">'
		. '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">'
		. '<rect x="2" y="4" width="14" height="16" rx="2"></rect><path d="M16 9l6-3v12l-6-3"></path>'
		. '</svg><span>' . esc_html__( 'No video', 'axcelersblocks' ) . '</span></div></div>';
} else {
	// Build the <video> attribute string.
	$video_attrs  = ' class="axcelersblocks-video__video"';
	$video_attrs .= ' preload="' . esc_attr( $preload ) . '"';
	if ( $controls && ! $show_controls_on_play ) { $video_attrs .= ' controls'; }
	if ( $autoplay )    { $video_attrs .= ' autoplay'; }
	if ( $muted )       { $video_attrs .= ' muted'; }
	if ( $loop )        { $video_attrs .= ' loop'; }
	if ( $playsinline ) { $video_attrs .= ' playsinline'; }
	if ( $disable_pip ) { $video_attrs .= ' disablepictureinpicture'; }
	if ( ! empty( $controls_list ) ) {
		$video_attrs .= ' controlslist="' . esc_attr( implode( ' ', $controls_list ) ) . '"';
	}
	if ( $poster ) {
		$video_attrs .= ' poster="' . esc_url( $poster ) . '"';
	}

	$source_tag = sprintf(
		'<source src="%1$s"%2$s />',
		esc_url( $src ),
		$src_type ? ' type="' . esc_attr( $src_type ) . '"' : ''
	);

	// <track> children (captions / subtitles / chapters …).
	$track_tags = '';
	$allowed_kinds = [ 'subtitles', 'captions', 'descriptions', 'chapters', 'metadata' ];
	$default_used  = false;
	foreach ( $tracks as $track ) {
		if ( ! is_array( $track ) ) { continue; }
		$t_src = isset( $track['src'] ) ? esc_url_raw( $track['src'] ) : '';
		if ( '' === $t_src ) { continue; }
		$t_kind    = isset( $track['kind'] ) && in_array( $track['kind'], $allowed_kinds, true ) ? $track['kind'] : 'subtitles';
		$t_srclang = isset( $track['srclang'] ) ? sanitize_text_field( $track['srclang'] ) : '';
		$t_label   = isset( $track['label'] ) ? sanitize_text_field( $track['label'] ) : '';
		$is_default = ! $default_used && ! empty( $track['default'] );

		$track_tags .= sprintf(
			'<track kind="%1$s" src="%2$s"%3$s%4$s%5$s />',
			esc_attr( $t_kind ),
			esc_url( $t_src ),
			$t_srclang ? ' srclang="' . esc_attr( $t_srclang ) . '"' : '',
			$t_label ? ' label="' . esc_attr( $t_label ) . '"' : '',
			$is_default ? ' default' : ''
		);
		if ( $is_default ) { $default_used = true; }
	}

	$fallback = '<a href="' . esc_url( $src ) . '">' . esc_html__( 'Download video', 'axcelersblocks' ) . '</a>';

	$inner = sprintf( '<video%1$s>%2$s%3$s%4$s</video>', $video_attrs, $source_tag, $track_tags, $fallback );
}

// ─── Custom play overlay ─────────────────────────────────────────────────────

$has_play_overlay_media = $custom_play_overlay && ( $is_embed ? ( '' !== $embed_url ) : ( '' !== $src ) );

if ( $has_play_overlay_media ) {
	$play_icon_source = '';

	if ( ! empty( $attributes['playIconSvg'] ) && is_string( $attributes['playIconSvg'] ) ) {
		$play_icon_source = $attributes['playIconSvg'];
	} elseif ( ! empty( $attributes['playCustomIcon'] ) && is_string( $attributes['playCustomIcon'] ) ) {
		$play_icon_source = $attributes['playCustomIcon'];
	}

	$play_icon_html = '';
	if ( $play_icon_source && false !== strpos( $play_icon_source, '<svg' ) ) {
		$play_icon_svg  = wp_kses( $play_icon_source, axcelersblocks_get_allowed_svg_html() );
		$play_icon_html = $play_icon_svg ? '<span class="axcelersblocks-video__play-icon" aria-hidden="true">' . $play_icon_svg . '</span>' : '';
	}

	if ( '' === $play_icon_html ) {
		$play_icon_html = '<span class="axcelersblocks-video__play-icon" aria-hidden="true">'
			. '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"></path></svg>'
			. '</span>';
	}

	$inner .= sprintf(
		'<span class="axcelersblocks-video__play-overlay" data-axb-video-play aria-hidden="true"></span><span class="axcelersblocks-video__play-button" role="button" tabindex="0" aria-label="%1$s" data-axb-video-play>%2$s</span>',
		esc_attr( $play_button_label ),
		$play_icon_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- SVG is sanitized above or hardcoded fallback.
	);
}

// ─── Output ───────────────────────────────────────────────────────────────────

$figure_html = sprintf( '<figure %1$s>%2$s</figure>', $wrapper_attrs, $inner );

if ( ! empty( $link_href ) ) {
	$link_class = sanitize_html_class( $unique_class ) . '-link';
	$target_rel = $open_in_new ? ' target="_blank"' : '';
	printf(
		'<a href="%1$s" class="%2$s"%3$s%4$s%5$s%6$s>%7$s</a>',
		esc_url( $link_href ),
		esc_attr( $link_class ),
		$target_rel, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Hardcoded safe attribute fragment.
		$rel_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped 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.
		$figure_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Built from escaped values above.
	);
} else {
	echo $figure_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Built from escaped values above.
}
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
