<?php
/**
 * Frontend rendering for the language switcher.
 *
 * @package EffortLessMultisiteLanguageSwitcher
 */

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

/**
 * Handles frontend asset enqueueing, floating icon rendering, and shortcode output.
 */
class ELMLS_Frontend {

	/**
	 * Flag resolver instance.
	 *
	 * @var ELMLS_Flag_Resolver
	 */
	private $flag_resolver;

	/**
	 * Site data instance.
	 *
	 * @var ELMLS_Site_Data
	 */
	private $site_data;

	/**
	 * Constructor.
	 *
	 * @param ELMLS_Flag_Resolver $flag_resolver Flag resolver instance.
	 * @param ELMLS_Site_Data     $site_data     Site data instance.
	 */
	public function __construct( ELMLS_Flag_Resolver $flag_resolver, ELMLS_Site_Data $site_data ) {
		$this->flag_resolver = $flag_resolver;
		$this->site_data     = $site_data;
	}

	/**
	 * Enqueues plugin CSS and JS assets.
	 */
	public function enqueue_assets() {
		wp_enqueue_style( 'elmls-style', ELMLS_PLUGIN_URL . 'css/style.css', array(), ELMLS_Plugin::VERSION, 'all' );
		wp_enqueue_script( 'elmls-script', ELMLS_PLUGIN_URL . 'js/script.js', array( 'jquery' ), ELMLS_Plugin::VERSION, true );

		// Add inline CSS for switcher position and flag menu placement.
		$position = get_site_option( 'elmls_switcher_position', 'bottom-right' );

		// Get custom position offsets if using custom position.
		$custom_position_x = get_site_option( 'elmls_custom_position_x', '20' );
		$custom_position_y = get_site_option( 'elmls_custom_position_y', '20' );

		/**
		 * Filters the switcher position.
		 *
		 * @since 1.0.30
		 *
		 * @param string $position Position: 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'custom'.
		 */
		$position = apply_filters( 'elmls_switcher_position', $position );
		$css      = '#elmls-container { position: fixed; z-index: 9999; } #elmls-flags { position: absolute; z-index: 10000; }';

		if ( 'custom' === $position ) {
			$css .= sprintf(
				'#elmls-container { top: %spx !important; left: %spx !important; } #elmls-flags { top: 100%% !important; left: 50%% !important; transform: translateX(-50%%) !important; margin-top: 8px !important; }',
				intval( $custom_position_y ),
				intval( $custom_position_x )
			);
		} else {
			switch ( $position ) {
				case 'top-left':
					// Top position: flags show BELOW (60px from top of icon).
					$css .= '#elmls-container { top: 40px !important; left: 20px !important; } #elmls-flags { top: 60px !important; left: 50%% !important; transform: translateX(-50%%) !important; }';
					break;
				case 'top-right':
					// Top position: flags show BELOW (60px from top of icon).
					$css .= '#elmls-container { top: 40px !important; right: 20px !important; } #elmls-flags { top: 60px !important; left: 50%% !important; transform: translateX(-50%%) !important; }';
					break;
				case 'bottom-left':
					// Bottom position: flags show ABOVE (60px from bottom of icon).
					$css .= '#elmls-container { bottom: 20px !important; left: 20px !important; } #elmls-flags { bottom: 60px !important; left: 50%% !important; transform: translateX(-50%%) !important; }';
					break;
				case 'bottom-right':
				default:
					// Bottom position: flags show ABOVE (60px from bottom of icon).
					$css .= '#elmls-container { bottom: 20px !important; right: 20px !important; } #elmls-flags { bottom: 60px !important; left: 50%% !important; transform: translateX(-50%%) !important; }';
					break;
			}
		}
		wp_add_inline_style( 'elmls-style', $css );
	}

	/**
	 * Returns the equivalent URL of a page/post on another site.
	 *
	 * Uses the EffortLess Multisite Auto Translate API if available (accurate
	 * mapping via _translation_of_post meta), otherwise falls back to
	 * slug-based matching.
	 *
	 * @param int    $blog_id           Target blog ID.
	 * @param string $current_path      Current path.
	 * @param string $site_url          Target site URL.
	 * @param array  $translation_links Pre-fetched translation links from ms_gpt_get_translation_links().
	 * @return string Target URL.
	 */
	private function get_equivalent_url( $blog_id, $current_path, $site_url, $translation_links = array() ) {
		// 1. Use the translation plugin API if a mapping exists for this blog.
		if ( ! empty( $translation_links[ $blog_id ]['url'] ) ) {
			return $translation_links[ $blog_id ]['url'];
		}

		// 2. Check object cache for previously resolved URL.
		$current_post = get_post();
		$post_id      = $current_post ? $current_post->ID : 0;
		$cache_key    = "elmls_equiv_url_{$post_id}_{$blog_id}";
		$cached_url   = wp_cache_get( $cache_key, 'elmls' );

		if ( false !== $cached_url ) {
			return $cached_url;
		}

		// Fallback: slug-based matching (for non-singular pages, or when
		// the translation plugin is not active / post has no translation).
		$path_parts = wp_parse_url( $current_path );
		$path       = isset( $path_parts['path'] ) ? $path_parts['path'] : '/';
		$query      = isset( $path_parts['query'] ) ? '?' . $path_parts['query'] : '';

		$current_blog_id      = get_current_blog_id();
		$current_site_details = get_blog_details( $current_blog_id );
		$current_site_path    = rtrim( $current_site_details->path, '/' );

		$relative_path = $path;
		if ( ! empty( $current_site_path ) && '/' !== $current_site_path && 0 === strpos( $path, $current_site_path . '/' ) ) {
			$relative_path = substr( $path, strlen( $current_site_path ) );
		}

		if ( ! $current_post || is_home() || is_front_page() ) {
			$target_url = $site_url . $relative_path . $query;
			wp_cache_set( $cache_key, $target_url, 'elmls', HOUR_IN_SECONDS );
			return $target_url;
		}

		switch_to_blog( $blog_id );

		$target_url = $site_url;
		$found      = false;

		$post_slug = $current_post->post_name;
		$post_type = $current_post->post_type;

		$args = array(
			'name'        => $post_slug,
			'post_type'   => $post_type,
			'post_status' => 'publish',
			'numberposts' => 1,
		);

		$equivalent_posts = get_posts( $args );

		if ( ! empty( $equivalent_posts ) ) {
			$target_url = get_permalink( $equivalent_posts[0]->ID );
			if ( $query ) {
				$target_url .= $query;
			}
			$found = true;
		}

		if ( ! $found && 'page' !== $post_type ) {
			$equivalent_page = get_page_by_path( $post_slug, OBJECT, 'page' );
			if ( $equivalent_page ) {
				$target_url = get_permalink( $equivalent_page->ID );
				if ( $query ) {
					$target_url .= $query;
				}
				$found = true;
			}
		}

		if ( ! $found ) {
			$target_url = $site_url . $relative_path . $query;
		}

		restore_current_blog();

		wp_cache_set( $cache_key, $target_url, 'elmls', HOUR_IN_SECONDS );

		return $target_url;
	}

	/**
	 * Gathers switcher data: visible sites, locales, current flag, and flag links HTML.
	 *
	 * Returns false if the switcher should not be rendered (not multisite, <2 sites).
	 *
	 * @return array|false Switcher data or false.
	 */
	private function get_switcher_data() {
		if ( ! is_multisite() ) {
			return false;
		}

		$current_blog_id = get_current_blog_id();
		$hidden_sites    = get_site_option( 'elmls_hidden_sites', array() );

		/**
		 * Filters the maximum number of sites to query.
		 *
		 * @since 1.0.36
		 *
		 * @param int $limit Maximum number of sites. Default 100.
		 */
		$sites_limit = apply_filters( 'elmls_sites_limit', 100 );

		$sites = get_sites(
			array(
				'public'   => 1,
				'archived' => 0,
				'deleted'  => 0,
				'number'   => $sites_limit,
			)
		);

		/**
		 * Filters the sites to display in the language switcher.
		 *
		 * @since 1.0.30
		 *
		 * @param array $sites Array of WP_Site objects.
		 */
		$sites = apply_filters( 'elmls_sites', $sites );

		if ( ! is_array( $sites ) || 1 >= count( $sites ) ) {
			return false;
		}

		// Collect all blog IDs including current site for batch fetch.
		$all_blog_ids  = array( $current_blog_id );
		$visible_sites = array();

		foreach ( $sites as $site ) {
			if ( (int) $site->blog_id === (int) $current_blog_id || in_array( (int) $site->blog_id, $hidden_sites, true ) ) {
				continue;
			}
			$all_blog_ids[]  = (int) $site->blog_id;
			$visible_sites[] = $site;
		}

		// Batch fetch all locales (uses object cache + get_blog_details).
		$all_locales = $this->site_data->get_site_locales( $all_blog_ids );

		// Per-site overrides (custom URL and/or custom flag), keyed by blog ID.
		$site_overrides   = get_site_option( 'elmls_site_overrides', array() );
		$current_override = isset( $site_overrides[ $current_blog_id ] ) ? $site_overrides[ $current_blog_id ] : array();

		$current_locale    = isset( $all_locales[ $current_blog_id ] ) ? $all_locales[ $current_blog_id ] : 'en_US';
		$current_flag_code = ! empty( $current_override['flag'] ) ? $current_override['flag'] : $this->flag_resolver->get_flag_code( $current_locale );
		$current_flag_url  = $this->flag_resolver->get_flag_url( $current_flag_code );

		$current_path = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/';

		// Fetch translation links once (empty array if translation plugin is not active).
		$translation_links = function_exists( 'ms_gpt_get_translation_links' ) ? ms_gpt_get_translation_links() : array();

		// Build flag links HTML.
		$flag_links = '';
		foreach ( $visible_sites as $site ) {
			$blog_id  = (int) $site->blog_id;
			$override = isset( $site_overrides[ $blog_id ] ) ? $site_overrides[ $blog_id ] : array();

			$locale    = isset( $all_locales[ $blog_id ] ) ? $all_locales[ $blog_id ] : 'en_US';
			$flag_code = ! empty( $override['flag'] ) ? $override['flag'] : $this->flag_resolver->get_flag_code( $locale );
			$flag_url  = $this->flag_resolver->get_flag_url( $flag_code );

			if ( ! empty( $override['url'] ) ) {
				// A custom URL always wins: link straight to it, skipping equivalent-page matching.
				$site_url   = $override['url'];
				$target_url = $override['url'];
			} else {
				$site_url   = get_home_url( $site->blog_id );
				$target_url = $this->get_equivalent_url( $site->blog_id, $current_path, $site_url, $translation_links );
			}

			$flag_links .= sprintf(
				'<a href="%s" class="elmls-flag" data-blog-id="%s" data-home-url="%s">%s</a>',
				esc_url( $target_url ),
				esc_attr( $site->blog_id ),
				esc_url( $site_url ),
				wp_kses_post( $this->flag_resolver->render_flag_img( $flag_url, $locale ) )
			);
		}

		return array(
			'current_flag_img' => wp_kses_post( $this->flag_resolver->render_flag_img( $current_flag_url, $current_locale ) ),
			'flag_links'       => $flag_links,
		);
	}

	/**
	 * Renders the floating language switcher icon.
	 */
	public function render_floating_icon() {
		if ( get_site_option( 'elmls_hide_switcher', false ) ) {
			return;
		}

		$data = $this->get_switcher_data();
		if ( ! $data ) {
			return;
		}

		echo '<div id="elmls-container"><div id="elmls-icon">';
		echo wp_kses_post( $data['current_flag_img'] );
		echo '</div><div id="elmls-flags" style="display: none;">';
		echo wp_kses_post( $data['flag_links'] );
		echo '</div></div>';
	}

	/**
	 * Renders the language switcher HTML.
	 *
	 * @param array $atts Shortcode attributes.
	 * @return string HTML output.
	 */
	public function shortcode_switcher( $atts ) {
		// Enqueue assets if not already enqueued.
		if ( ! wp_style_is( 'elmls-style', 'enqueued' ) ) {
			wp_enqueue_style( 'elmls-style', ELMLS_PLUGIN_URL . 'css/style.css', array(), ELMLS_Plugin::VERSION, 'all' );
		}
		if ( ! wp_script_is( 'elmls-script', 'enqueued' ) ) {
			wp_enqueue_script( 'elmls-script', ELMLS_PLUGIN_URL . 'js/script.js', array( 'jquery' ), ELMLS_Plugin::VERSION, true );
		}

		$data = $this->get_switcher_data();
		if ( ! $data ) {
			return '';
		}

		// Allow shortcode to override position.
		$atts = shortcode_atts(
			array(
				'position' => '',
			),
			$atts,
			'elmls_switcher'
		);

		$position = $atts['position'];
		if ( empty( $position ) ) {
			$position = get_site_option( 'elmls_switcher_position', 'bottom-right' );
		}

		// Build inline CSS for position.
		$css = '#elmls-container { position: relative; z-index: 9999; display: inline-block; } #elmls-flags { position: absolute; z-index: 10000; }';
		switch ( $position ) {
			case 'top-left':
				$css .= '#elmls-container { top: 0 !important; left: 0 !important; } #elmls-flags { top: 100%% !important; left: 50%% !important; transform: translateX(-50%%) !important; margin-top: 8px !important; }';
				break;
			case 'top-right':
				$css .= '#elmls-container { top: 0 !important; right: 0 !important; } #elmls-flags { top: 100%% !important; left: 50%% !important; transform: translateX(-50%%) !important; margin-top: 8px !important; }';
				break;
			case 'bottom-left':
				$css .= '#elmls-container { bottom: 0 !important; left: 0 !important; } #elmls-flags { bottom: 100%% !important; left: 50%% !important; transform: translateX(-50%%) !important; margin-bottom: 8px !important; }';
				break;
			case 'bottom-right':
			default:
				$css .= '#elmls-container { bottom: 0 !important; right: 0 !important; } #elmls-flags { bottom: 100%% !important; left: 50%% !important; transform: translateX(-50%%) !important; margin-bottom: 8px !important; }';
				break;
		}

		/** This filter is documented in the enqueue_assets method. */
		$position = apply_filters( 'elmls_switcher_position', $position );

		ob_start();
		?>
		<style><?php echo wp_kses( $css, array() ); ?></style>
		<div id="elmls-container">
			<div id="elmls-icon"><?php echo wp_kses_post( $data['current_flag_img'] ); ?></div>
			<div id="elmls-flags" style="display: none;"><?php echo wp_kses_post( $data['flag_links'] ); ?></div>
		</div>
		<?php
		return ob_get_clean();
	}
}
