<?php
/**
 * Helper functions.
 *
 * @package Zluck_Ajax_Posts_Filter_Elementor
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Get post types for query controls.
 *
 * @return array
 */
function aapf_get_post_types() {
	$post_types = get_post_types( array( 'public' => true ), 'objects' );
	$options    = array();

	foreach ( $post_types as $post_type ) {
		$options[ $post_type->name ] = $post_type->label;
	}

	return $options;
}

/**
 * Get taxonomies for filter controls.
 *
 * @return array
 */
function aapf_get_taxonomies() {
	$taxonomies = get_taxonomies( array( 'public' => true ), 'objects' );
	$options    = array();

	foreach ( $taxonomies as $taxonomy ) {
		$options[ $taxonomy->name ] = $taxonomy->label;
	}

	return $options;
}

/**
 * Get terms for a taxonomy.
 *
 * @param string $taxonomy Taxonomy name.
 * @param bool   $hierarchical Whether to include hierarchy.
 * @return array
 */
function aapf_get_terms( $taxonomy, $hierarchical = false ) {
	$args = array(
		'taxonomy'   => $taxonomy,
		'hide_empty' => false,
	);

	if ( $hierarchical ) {
		$args['hierarchical'] = true;
	}

	$terms = get_terms( $args );

	if ( is_wp_error( $terms ) || empty( $terms ) ) {
		return array();
	}

	$options = array();
	foreach ( $terms as $term ) {
		$options[ $term->term_id ] = $term->name;
	}

	return $options;
}

/**
 * Build WP_Query args from widget settings.
 *
 * @param array $settings Widget settings.
 * @return array
 */
function aapf_build_query_args( $settings ) {
	$post_type = isset( $settings['post_type'] ) ? sanitize_key( $settings['post_type'] ) : 'post';
	
	// Validate post type exists
	if ( ! post_type_exists( $post_type ) ) {
		$post_type = 'post'; // Fallback to default
	}
	
	$args = array(
		'post_type'      => $post_type,
		'posts_per_page' => isset( $settings['posts_per_page'] ) ? absint( $settings['posts_per_page'] ) : 6,
		'post_status'    => 'publish',
		'ignore_sticky_posts' => isset( $settings['ignore_sticky_posts'] ) && 'yes' === $settings['ignore_sticky_posts'] ? 1 : 0,
	);

	// Post IDs
	if ( ! empty( $settings['include_ids'] ) ) {
		$include_ids = array_map( 'absint', explode( ',', $settings['include_ids'] ) );
		$args['post__in'] = $include_ids;
	}

	if ( ! empty( $settings['exclude_ids'] ) ) {
		$exclude_ids = array_map( 'absint', explode( ',', $settings['exclude_ids'] ) );
		// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Required for excluding specific posts
		$args['post__not_in'] = $exclude_ids;
	}

	// Order by
	$orderby = isset( $settings['orderby'] ) ? $settings['orderby'] : 'date';
	$order   = isset( $settings['order'] ) ? strtoupper( $settings['order'] ) : 'DESC';
	
	// Validate order value - only allow ASC or DESC
	if ( ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) {
		$order = 'DESC';
	}

	switch ( $orderby ) {
		case 'title':
			$args['orderby'] = 'title';
			$args['order']   = $order;
			break;
		case 'menu_order':
			$args['orderby'] = 'menu_order';
			$args['order']   = $order;
			break;
		case 'random':
			$args['orderby'] = 'rand';
			break;
		default:
			$args['orderby'] = 'date';
			$args['order']   = $order;
	}

	// Offset
	if ( ! empty( $settings['offset'] ) ) {
		$args['offset'] = absint( $settings['offset'] );
	}

	// Taxonomy filter (if enabled and terms selected)
	if ( ! empty( $settings['enable_taxonomy_filter'] ) && 'yes' === $settings['enable_taxonomy_filter'] ) {
		if ( ! empty( $settings['filter_taxonomy'] ) ) {
			$taxonomy = sanitize_key( $settings['filter_taxonomy'] );
			
			// Validate taxonomy exists
			if ( ! taxonomy_exists( $taxonomy ) ) {
				return $args; // Return args without tax_query if invalid
			}
			
			$tax_query = array();

			// Include terms
			if ( ! empty( $settings['filter_include_terms'] ) ) {
				$include_terms = is_array( $settings['filter_include_terms'] ) 
					? array_map( 'absint', $settings['filter_include_terms'] )
					: array( absint( $settings['filter_include_terms'] ) );

				// Validate terms exist
				$valid_include_terms = get_terms(
					array(
						'taxonomy'   => $taxonomy,
						'include'    => $include_terms,
						'hide_empty' => false,
						'fields'     => 'ids',
					)
				);

				if ( ! is_wp_error( $valid_include_terms ) && ! empty( $valid_include_terms ) ) {
					$tax_query[] = array(
						'taxonomy' => $taxonomy,
						'field'    => 'term_id',
						'terms'    => $valid_include_terms,
						'operator' => 'IN',
					);
				}
			}

			// Exclude terms
			if ( ! empty( $settings['filter_exclude_terms'] ) ) {
				$exclude_terms = is_array( $settings['filter_exclude_terms'] )
					? array_map( 'absint', $settings['filter_exclude_terms'] )
					: array( absint( $settings['filter_exclude_terms'] ) );

				// Validate terms exist
				$valid_exclude_terms = get_terms(
					array(
						'taxonomy'   => $taxonomy,
						'include'    => $exclude_terms,
						'hide_empty' => false,
						'fields'     => 'ids',
					)
				);

				if ( ! is_wp_error( $valid_exclude_terms ) && ! empty( $valid_exclude_terms ) ) {
					$tax_query[] = array(
						'taxonomy' => $taxonomy,
						'field'    => 'term_id',
						'terms'    => $valid_exclude_terms,
						'operator' => 'NOT IN',
					);
				}
			}

			if ( ! empty( $tax_query ) ) {
				// Always use AND relation for multiple taxonomy queries
				if ( count( $tax_query ) > 1 ) {
					$tax_query['relation'] = 'AND';
				}
				// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for taxonomy filtering functionality
				$args['tax_query'] = $tax_query;
			}
		}
	}

	/**
	 * Filter query arguments before execution.
	 *
	 * @param array $args Query arguments.
	 * @param array $settings Widget settings.
	 */
	$args = apply_filters( 'aapf_before_query', $args, $settings );

	return $args;
}

/**
 * Render post card template.
 *
 * @param WP_Post $post Post object.
 * @param array   $settings Widget settings.
 */
function aapf_render_post_card( $post, $settings ) {
	$template_path = AAPF_PLUGIN_DIR . 'templates/post-card.php';

	if ( file_exists( $template_path ) ) {
		include $template_path;
	}
}

/**
 * Sanitize settings array.
 *
 * @param array $settings Settings array.
 * @return array
 */
function aapf_sanitize_settings( $settings ) {
	if ( ! is_array( $settings ) ) {
		return array();
	}

	$sanitized = array();

	foreach ( $settings as $key => $value ) {
		// Skip Elementor internal keys
		if ( is_string( $key ) && strpos( $key, '__' ) === 0 ) {
			continue;
		}

		$sanitized_key = sanitize_key( $key );

		if ( is_array( $value ) ) {
			$sanitized[ $sanitized_key ] = aapf_sanitize_settings( $value );
		} elseif ( is_numeric( $value ) ) {
			$sanitized[ $sanitized_key ] = is_float( $value ) ? floatval( $value ) : intval( $value );
		} elseif ( is_bool( $value ) ) {
			$sanitized[ $sanitized_key ] = (bool) $value;
		} else {
			$sanitized[ $sanitized_key ] = sanitize_text_field( $value );
		}
	}

	return $sanitized;
}

/**
 * Render card layout with overlays.
 *
 * @param WP_Post $post Post object.
 * @param array   $settings Widget settings.
 */
function aapf_render_card_layout( $post, $settings ) {
	?>
	<article id="post-<?php the_ID(); ?>" <?php post_class( 'aapf-post-card aapf-card-layout' ); ?>>
		<?php if ( ! empty( $settings['show_image'] ) && 'yes' === $settings['show_image'] && has_post_thumbnail() ) : ?>
			<div class="aapf-post-thumbnail aapf-card-thumbnail">
				<a href="<?php echo esc_url( get_permalink() ); ?>" aria-label="<?php echo esc_attr( get_the_title() ); ?>">
					<?php
					$image_size = isset( $settings['image_size'] ) ? $settings['image_size'] : 'medium';
					the_post_thumbnail(
						$image_size,
						array(
							'alt' => get_the_title(),
							'loading' => 'lazy',
						)
					);
					?>
				</a>
				
				

				<?php if ( ! empty( $settings['show_meta'] ) && 'yes' === $settings['show_meta'] ) : ?>
					<?php
					$meta_items = isset( $settings['meta_items'] ) ? $settings['meta_items'] : array();
					?>
				<?php endif; ?>

				<?php
				// Date overlay (top right) - only for card layout
				$show_date_overlay = isset( $settings['card_show_date_overlay'] ) ? $settings['card_show_date_overlay'] : 'yes';
				if ( $show_date_overlay === 'yes' ) {
					?>
					<div class="aapf-card-date-overlay">
						<span class="aapf-card-date-day-month"><?php echo esc_html( get_the_date( 'd M' ) ); ?></span>
						<span class="aapf-card-date-year"><?php echo esc_html( get_the_date( 'Y' ) ); ?></span>
					</div>
					<?php
				}
				?>
			</div>
		<?php endif; ?>

		<div class="aapf-post-content aapf-card-content">
			<?php
				// Category overlay (bottom left) - only for card layout
				$show_category_overlay = isset( $settings['card_show_category_overlay'] ) ? $settings['card_show_category_overlay'] : 'yes';
				if ( $show_category_overlay === 'yes' ) {
					$categories = get_the_category();
					if ( ! empty( $categories ) ) {
						$first_category = $categories[0];
						?>
						<div class="aapf-card-category-overlay">
							<a href="<?php echo esc_url( get_category_link( $first_category->term_id ) ); ?>">
								<?php echo esc_html( strtoupper( $first_category->name ) ); ?>
							</a>
						</div>
						<?php
					}
				}
				?>
			<?php if ( ! empty( $settings['show_title'] ) && 'yes' === $settings['show_title'] ) : ?>
				<?php
				$title_tag = isset( $settings['title_tag'] ) ? $settings['title_tag'] : 'h3';
				?>
				<<?php echo esc_attr( $title_tag ); ?> class="aapf-post-title aapf-card-title">
					<a href="<?php echo esc_url( get_permalink() ); ?>"><?php echo esc_html( get_the_title() ); ?></a>
				</<?php echo esc_attr( $title_tag ); ?>>
			<?php endif; ?>

			<?php if ( ! empty( $settings['show_excerpt'] ) && 'yes' === $settings['show_excerpt'] ) : ?>
				<div class="aapf-post-excerpt aapf-card-excerpt">
					<?php
					$excerpt_length = isset( $settings['excerpt_length'] ) ? absint( $settings['excerpt_length'] ) : 20;
					$excerpt = get_the_excerpt();

					if ( $excerpt_length > 0 ) {
						$excerpt = wp_trim_words( $excerpt, $excerpt_length, '...' );
					}

					echo wp_kses_post( $excerpt );
					?>
				</div>
			<?php endif; ?>

			<?php if ( ! empty( $settings['show_read_more'] ) && 'yes' === $settings['show_read_more'] ) : ?>
				<div class="aapf-post-read-more aapf-card-read-more">
					<a href="<?php echo esc_url( get_permalink() ); ?>" class="aapf-read-more-link aapf-card-read-more-link">
						<?php
						$read_more_text = isset( $settings['read_more_text'] ) ? $settings['read_more_text'] : esc_html__( 'Read More', 'zluck-ajax-posts-filter-for-elementor' );
						echo esc_html( $read_more_text );
						?>
						<span class="aapf-read-more-arrow">&raquo;</span>
					</a>
				</div>
			<?php endif; ?>

			<?php if ( ! empty( $settings['show_meta'] ) && 'yes' === $settings['show_meta'] ) : ?>
				<div class="aapf-post-meta aapf-card-meta">
					<?php
					$meta_items = isset( $settings['meta_items'] ) ? $settings['meta_items'] : array();
					aapf_render_meta_items( $meta_items, $settings );
					?>
				</div>
			<?php endif; ?>
		</div>
	</article>
	<?php
}

/**
 * Render meta items with simple array structure.
 *
 * @param array $meta_items Meta items array (simple array of strings).
 * @param array $settings Widget settings.
 * @return void
 */
function aapf_render_meta_items( $meta_items, $settings = array() ) {
	if ( empty( $meta_items ) || ! is_array( $meta_items ) ) {
		return;
	}

	// Get separator from settings
	$separator = isset( $settings['meta_separator'] ) ? sanitize_text_field( $settings['meta_separator'] ) : '•';
	$separator_html = '';
	if ( ! empty( $separator ) ) {
		$separator_html = '<span class="aapf-meta-separator">' . esc_html( $separator ) . '</span>';
	}

	$rendered_items = array();

	foreach ( $meta_items as $meta_type ) {
		if ( empty( $meta_type ) || ! is_string( $meta_type ) ) {
			continue;
		}

		ob_start();
		switch ( $meta_type ) {
			case 'author':
				$author_name = get_the_author();
				$author_url = get_author_posts_url( get_the_author_meta( 'ID' ) );
				?>
				<span class="aapf-meta-author">
					<a href="<?php echo esc_url( $author_url ); ?>"><?php echo esc_html( $author_name ); ?></a>
				</span>
				<?php
				break;

			case 'date':
				?>
				<span class="aapf-meta-date">
					<time datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>"><?php echo esc_html( get_the_date() ); ?></time>
				</span>
				<?php
				break;

			case 'category':
				$categories = get_the_category();
				if ( ! empty( $categories ) ) {
					?>
					<span class="aapf-meta-category">
						<?php
						$category_links = array();
						foreach ( $categories as $category ) {
							$category_links[] = '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '">' . esc_html( $category->name ) . '</a>';
						}
						echo implode( ', ', $category_links ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
						?>
					</span>
					<?php
				}
				break;

			case 'comments':
				$comments_count = get_comments_number();
				$comments_link = get_comments_link();
				?>
				<span class="aapf-meta-comments">
					<a href="<?php echo esc_url( $comments_link ); ?>">
						<?php
						/* translators: %d: comments count */
						printf( esc_html( _n( '%d Comment', '%d Comments', $comments_count, 'zluck-ajax-posts-filter-for-elementor' ) ), absint( $comments_count ) );
						?>
					</a>
				</span>
				<?php
				break;
		}
		$item_html = trim( ob_get_clean() );
		if ( $item_html ) {
			$rendered_items[] = $item_html;
		}
	}

	if ( ! empty( $rendered_items ) ) {
		echo implode( $separator_html, $rendered_items ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	}
}

/**
 * Render meta icon.
 *
 * @param array $icon Icon settings.
 * @return string Icon HTML.
 */
function aapf_render_meta_icon( $icon ) {
	if ( empty( $icon ) || ! is_array( $icon ) ) {
		return '';
	}

	$icon_value = isset( $icon['value'] ) ? $icon['value'] : '';
	if ( empty( $icon_value ) ) {
		return '';
	}

	$icon_library = isset( $icon['library'] ) ? $icon['library'] : '';
	$icon_html = '';

	if ( 'svg' === $icon_library && is_array( $icon_value ) ) {
		$width = isset( $icon_value['width'] ) ? absint( $icon_value['width'] ) : 16;
		$height = isset( $icon_value['height'] ) ? absint( $icon_value['height'] ) : 16;
		$path = isset( $icon_value['path'] ) ? $icon_value['path'] : '';
		$viewbox = isset( $icon_value['viewBox'] ) ? $icon_value['viewBox'] : "0 0 {$width} {$height}";
		
		// Sanitize SVG path
		$path = preg_replace( '/[^MmLlHhVvCcSsQqTtAaZz0-9\s,.-]/', '', $path );
		
		// Validate viewBox format
		$viewbox = sanitize_text_field( $viewbox );
		if ( ! preg_match( '/^\d+\s+\d+\s+\d+\s+\d+$/', $viewbox ) ) {
			$viewbox = "0 0 {$width} {$height}";
		}
		
		$icon_html = '<svg class="aapf-meta-icon-svg" aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" viewBox="' . esc_attr( $viewbox ) . '"><path d="' . esc_attr( $path ) . '"></path></svg>';
	} else {
		$icon_class = is_string( $icon_value ) ? $icon_value : ( isset( $icon_value['url'] ) ? $icon_value['url'] : '' );
		if ( ! empty( $icon_class ) ) {
			$icon_html = '<i class="' . esc_attr( $icon_class ) . '"></i>';
		}
	}

	return $icon_html;
}

