<?php
namespace Prodigy\Includes\Helpers;

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

/**
 * Prodigy Template Helper
 *
 * @version    3.0.2
 * @package    Prodigy
 * @subpackage Prodigy/includes
 */
class Prodigy_Template {

	/**
	 * @param string $slug
	 * @param string $name
	 */
	public static function prodigy_get_template_part( string $slug, string $name = '' ) {
		$template = '';

		// Look in yourtheme/slug-name.php and yourtheme/prodigy/slug-name.php.
		if ( $name ) {
			$template = locate_template( array( "{$slug}-{$name}.php", 'prodigy/' . "{$slug}-{$name}.php" ) );
		}

		// Get default slug-name.php.
		if ( ! $template && $name && file_exists( PRODIGY_PLUGIN_PATH . "/templates/partials/{$slug}-{$name}.php" ) ) {
			$template = PRODIGY_PLUGIN_PATH . "/templates/partials/{$slug}-{$name}.php";
		}

		// If template file doesn't exist, look in yourtheme/slug.php and yourtheme/prodigy/slug.php.
		if ( ! $template ) {
			$template = locate_template( array( "{$slug}.php", 'prodigy/' . "{$slug}.php" ) );
		}

		if ( $template ) {
			load_template( $template, false );
		}
	}

	/**
	 * @param   string $template_name
	 * @param           $args
	 * @param   string $directory_name
	 * @param   string $template_path
	 * @param   string $default_path
	 *
	 * @return void
	 */
	public static function prodigy_get_template( string $template_name, $args = array(), string $directory_name = 'templates', string $template_path = '', string $default_path = '' ) {
		// Resolve path before extract() so user-controlled $args['template_name'] cannot override it (LFI prevention).
		$located = self::prodigy_locate_template( $template_name, $directory_name, $template_path, $default_path );

		if ( ! empty( $args ) && is_array( $args ) ) {
			extract( $args );
		}

		$located = apply_filters( 'prodigy_get_' . $directory_name, $located, $template_name, $args, $template_path, $default_path );
		$located = self::prodigy_validate_template_path( $located, $directory_name, $default_path ?: ( PRODIGY_PLUGIN_PATH . $directory_name . '/partials/' ) );

		if ( $located && ! is_dir( $located ) && file_exists( $located ) ) {
			include $located;
		}
	}

	/**
	 * @param   string $template_name
	 * @param   array  $args
	 * @param   string $directory_name
	 * @param   string $template_path
	 * @param   string $default_path
	 *
	 * @return false|string
	 */
	public static function prodigy_get_template_html( string $template_name, array $args = array(), string $directory_name = 'templates', string $template_path = '', string $default_path = '' ) {
		if ( ! empty( $template_name ) ) {
			ob_start();
			self::prodigy_get_template( $template_name, $args, $directory_name, $template_path, $default_path );
		}

		return ob_get_clean();
	}

	/**
	 * @param   string $template_name
	 * @param   string $directory_name
	 * @param   string $template_path
	 * @param   string $default_path
	 *
	 * @return string
	 */
	public static function prodigy_locate_template( string $template_name, string $directory_name = 'templates', string $template_path = '', string $default_path = '' ): string {
		// Prevent path traversal (LFI): reject null bytes.
		if ( strpos( $template_name, "\0" ) !== false ) {
			return '';
		}
		// Reject path traversal: disallow '.' or '..' as path segments.
		$segments = explode( '/', $template_name );
		foreach ( $segments as $segment ) {
			if ( $segment === '.' || $segment === '..' ) {
				return '';
			}
		}

		if ( ! $template_path ) {
			$template_path = 'prodigy/';
		}

		if ( ! $default_path ) {
			$default_path = PRODIGY_PLUGIN_PATH . $directory_name . '/partials/';
		}

		$sanitized_segments = array();
		foreach ( $segments as $segment ) {
			$segment = sanitize_file_name( $segment );
			if ( $segment === '.' || $segment === '..' ) {
				return '';
			}
			if ( $segment !== '' ) {
				$sanitized_segments[] = $segment;
			}
		}
		if ( empty( $sanitized_segments ) ) {
			return '';
		}
		$sanitized_name = implode( '/', $sanitized_segments );

		// sanitized path first; if file is not found , fall back to original path which is already safe (no . or ..).
		$template = self::prodigy_locate_template_resolve( $sanitized_name, $template_path, $default_path );
		if ( empty( $template ) || ! file_exists( $template ) ) {
			$template = self::prodigy_locate_template_resolve( $template_name, $template_path, $default_path );
		}

		return $template;
	}

	/**
	 * Resolves template path for a given template name (theme then default).
	 *
	 * @param string $template_name Relative template name (e.g. shortcode/cart.php).
	 * @param string $template_path  Theme path (e.g. prodigy/).
	 * @param string $default_path    Plugin partials base path.
	 * @return string Resolved path or empty string.
	 */
	private static function prodigy_locate_template_resolve( string $template_name, string $template_path, string $default_path ): string {
		$template = locate_template(
			array(
				trailingslashit( $template_path ) . $template_name,
				$template_name,
			)
		);
		if ( ! $template ) {
			$template = $default_path . $template_name;
		}
		return $template;
	}

	/**
	 * Validates that the resolved template path is within allowed directories (prevents path traversal / LFI).
	 *
	 * @param string $located       Resolved template path.
	 * @param string $directory_name Directory name (e.g. 'templates').
	 * @param string $default_path   Default path for templates (plugin partials base).
	 *
	 * @return string The $located path if valid, or empty string if path traversal detected.
	 */
	public static function prodigy_validate_template_path( string $located, string $directory_name = 'templates', string $default_path = '' ): string {
		if ( empty( $located ) || ! file_exists( $located ) ) {
			return $located;
		}

		$real_located = realpath( $located );
		if ( $real_located === false ) {
			return '';
		}

		$allowed_bases = array();

		if ( $default_path ) {
			$real_default = realpath( $default_path );
			if ( $real_default !== false ) {
				$allowed_bases[] = $real_default;
			}
		}

		$plugin_partials = PRODIGY_PLUGIN_PATH . $directory_name . '/partials/';
		$real_plugin     = realpath( $plugin_partials );
		if ( $real_plugin !== false ) {
			$allowed_bases[] = $real_plugin;
		}

		$theme_path = get_theme_root();
		if ( $theme_path && file_exists( $theme_path ) ) {
			$real_theme = realpath( $theme_path );
			if ( $real_theme !== false ) {
				$allowed_bases[] = $real_theme;
			}
		}

		foreach ( $allowed_bases as $base ) {
			if ( strpos( $real_located, $base ) === 0 || $real_located === $base ) {
				return $located;
			}
		}

		return '';
	}

	/**
	 * @return bool
	 */
	public static function prodigy_is_admin(): bool {
		$user = wp_get_current_user();
		if ( ! empty( $user->roles ) && $user->roles[0] === 'administrator' ) {
			$result = true;
		} else {
			$result = false;
		}

		return $result;
	}
}
