<?php
declare(strict_types=1);

namespace forge12\floating_menu\component\floatingmenu {

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

	/**
	 * Handles WPML compatibility for the Floating Menu plugin.
	 *
	 * - Registers menu item strings (name, title) for WPML String Translation.
	 * - Translates menu item strings on frontend output.
	 * - Converts stored page IDs to their translated equivalents.
	 *
	 * @since 1.4.0
	 */
	class WPMLIntegration {

		/**
		 * Register all WPML-related hooks.
		 */
		public function __construct() {
			add_action( 'save_post_floating_menu', [ $this, 'register_link_strings' ], 20, 2 );
			add_filter( 'f12_floating_menu_get_links', [ $this, 'translate_links' ], 10, 2 );
			add_filter( 'f12_floating_menu_is_visible_on_post', [ $this, 'translate_page_ids' ], 10, 3 );
		}

		/**
		 * Register translatable strings from menu items when a floating menu is saved.
		 *
		 * @param int      $post_id The floating menu post ID.
		 * @param \WP_Post $post    The floating menu post object.
		 *
		 * @return void
		 */
		public function register_link_strings( int $post_id, \WP_Post $post ): void {
			if ( ! function_exists( 'icl_register_string' ) ) {
				return;
			}

			if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
				return;
			}

			$links = get_post_meta( $post_id, '_floating_links', true );

			if ( ! is_array( $links ) ) {
				return;
			}

			foreach ( $links as $index => $link ) {
				if ( ! empty( $link['name'] ) ) {
					icl_register_string(
						'f12-floating-menu',
						"menu_{$post_id}_link_{$index}_name",
						$link['name']
					);
				}

				if ( ! empty( $link['title'] ) ) {
					icl_register_string(
						'f12-floating-menu',
						"menu_{$post_id}_link_{$index}_title",
						$link['title']
					);
				}
			}
		}

		/**
		 * Translate menu item name and title fields for the current language.
		 *
		 * @param array $links   The menu items array.
		 * @param int   $post_id The floating menu post ID.
		 *
		 * @return array
		 */
		public function translate_links( array $links, int $post_id ): array {
			if ( ! function_exists( 'icl_t' ) ) {
				return $links;
			}

			foreach ( $links as $index => &$link ) {
				if ( ! empty( $link['name'] ) ) {
					$link['name'] = icl_t(
						'f12-floating-menu',
						"menu_{$post_id}_link_{$index}_name",
						$link['name']
					);
				}

				if ( ! empty( $link['title'] ) ) {
					$link['title'] = icl_t(
						'f12-floating-menu',
						"menu_{$post_id}_link_{$index}_title",
						$link['title']
					);
				}

				if ( ! empty( $link['link'] ) ) {
					$link['link'] = $this->translate_url( $link['link'] );
				}
			}

			return $links;
		}

		/**
		 * Translate an internal URL to the current language equivalent.
		 *
		 * Resolves the URL to a post ID, finds the WPML translation,
		 * and returns the translated permalink. Falls back to the
		 * original URL for external links or if no translation exists.
		 *
		 * @param string $url The original URL.
		 *
		 * @return string The translated URL or the original if not translatable.
		 */
		private function translate_url( string $url ): string {
			$path = trim( $url, '/' );

			if ( strpos( $path, 'http' ) === 0 || strpos( $path, 'tel:' ) === 0 || strpos( $path, 'mailto:' ) === 0 ) {
				return $url;
			}

			$default_lang = apply_filters( 'wpml_default_language', '' );
			do_action( 'wpml_switch_language', $default_lang );

			$page = get_page_by_path( $path );

			do_action( 'wpml_switch_language', null );

			if ( ! $page ) {
				return $url;
			}

			$translated_id = apply_filters( 'wpml_object_id', $page->ID, $page->post_type, true );

			if ( $translated_id === $page->ID ) {
				return $url;
			}

			$translated_url = get_permalink( $translated_id );

			if ( ! $translated_url ) {
				return $url;
			}

			return $translated_url;
		}

		/**
		 * Check if the current post is a translation of any stored page ID.
		 *
		 * When a floating menu is configured to show on page 42 (EN),
		 * this ensures it also shows on page 87 (DE translation of 42).
		 *
		 * @param bool     $is_visible Whether the menu is currently visible.
		 * @param \WP_Post $post       The current post.
		 * @param array    $page_ids   The configured page IDs from settings.
		 *
		 * @return bool
		 */
		public function translate_page_ids( bool $is_visible, \WP_Post $post, array $page_ids ): bool {
			if ( $is_visible ) {
				return true;
			}

			foreach ( $page_ids as $page_id ) {
				$page_id = absint( trim( (string) $page_id ) );

				if ( 0 === $page_id ) {
					continue;
				}

				$translated_id = apply_filters( 'wpml_object_id', $page_id, $post->post_type, true );

				if ( (int) $translated_id === $post->ID ) {
					return true;
				}
			}

			return false;
		}
	}
}
