<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\Features;

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

use Signocore\Multilanguage\Application\Constants;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;

/**
 * Handles nav menu translation per language.
 *
 * Each language gets its own copy of a nav menu, linked via _sml_menu_group term meta.
 */
final class MenuTranslation
{
	use Singleton;

	private const META_KEY_GROUP = '_sml_menu_group';

	private const META_KEY_LANG = '_sml_menu_lang';

	protected function init(): void
	{
		add_filter('wp_nav_menu_args', [$this, 'filterMenuArgs']);

		if (is_admin()) {
			add_action('admin_init', [$this, 'registerAdminHooks']);
		}
	}

	/**
	 * Register admin-side hooks for menu translation management.
	 */
	public function registerAdminHooks(): void
	{
		add_action('admin_footer-nav-menus.php', [$this, 'renderMenuTranslationUi']);
		add_action('wp_update_nav_menu', [$this, 'handleMenuSave']);
	}

	/**
	 * Swap the menu to the language-specific version based on current language.
	 *
	 * @param array<string, mixed> $args
	 * @return array<string, mixed>
	 */
	public function filterMenuArgs(array $args): array
	{
		if (is_admin()) {
			return $args;
		}

		$currentLang = LanguageDetection::load()->getCurrentLanguage();
		$defaultLang = LanguageManager::load()->getDefaultLanguageCode();

		if ($currentLang === $defaultLang) {
			return $args;
		}

		$menuId = $this->resolveMenuId($args);
		if ($menuId === 0) {
			return $args;
		}

		$translations = $this->getMenuTranslations($menuId);

		if (isset($translations[$currentLang])) {
			$translatedMenuId = $translations[$currentLang];

			// Verify the translated menu exists
			$menu = wp_get_nav_menu_object($translatedMenuId);
			if ($menu !== false) {
				$args['menu'] = $translatedMenuId;
			}
		}

		return $args;
	}

	/**
	 * Resolve the menu ID from wp_nav_menu args.
	 */
	private function resolveMenuId(array $args): int
	{
		// Try explicit menu parameter first
		if (!empty($args['menu'])) {
			$menu = wp_get_nav_menu_object($args['menu']);
			if ($menu !== false) {
				return (int) $menu->term_id;
			}
		}

		// Try theme location
		if (!empty($args['theme_location'])) {
			$locations = get_nav_menu_locations();
			$location = (string) $args['theme_location'];

			if (isset($locations[$location])) {
				return (int) $locations[$location];
			}
		}

		return 0;
	}

	/**
	 * Create a new empty menu for a specific language, linked to a source menu.
	 *
	 * @return int|false The new menu ID or false on failure.
	 */
	public function createMenuTranslation(int $sourceMenuId, string $langCode): int|false
	{
		$sourceMenu = wp_get_nav_menu_object($sourceMenuId);
		if ($sourceMenu === false) {
			return false;
		}

		$newMenuName = $sourceMenu->name . ' (' . strtoupper($langCode) . ')';
		$newMenuId = wp_create_nav_menu($newMenuName);

		if (is_wp_error($newMenuId)) {
			return false;
		}

		$this->linkMenuTranslation($sourceMenuId, $newMenuId, $langCode);

		return $newMenuId;
	}

	/**
	 * Link a target menu as a translation of a source menu for a given language.
	 */
	public function linkMenuTranslation(int $sourceMenuId, int $targetMenuId, string $langCode): bool
	{
		// Ensure the source menu has a group
		$groupId = $this->getOrCreateGroupId($sourceMenuId);

		// Assign the same group to the target menu
		update_term_meta($targetMenuId, self::META_KEY_GROUP, $groupId);
		update_term_meta($targetMenuId, self::META_KEY_LANG, $langCode);

		// Ensure source menu has its language meta set (default language)
		$sourceLang = get_term_meta($sourceMenuId, self::META_KEY_LANG, true);
		if (empty($sourceLang)) {
			$defaultLang = LanguageManager::load()->getDefaultLanguageCode();
			update_term_meta($sourceMenuId, self::META_KEY_LANG, $defaultLang);
		}

		return true;
	}

	/**
	 * Get all menu translations for a given menu, keyed by language code.
	 *
	 * @return array<string, int>
	 */
	public function getMenuTranslations(int $menuId): array
	{
		$groupId = get_term_meta($menuId, self::META_KEY_GROUP, true);

		if (empty($groupId)) {
			return [];
		}

		$allMenus = wp_get_nav_menus();
		$translations = [];

		foreach ($allMenus as $menu) {
			$menuGroupId = get_term_meta((int) $menu->term_id, self::META_KEY_GROUP, true);

			if ($menuGroupId === $groupId) {
				$menuLang = get_term_meta((int) $menu->term_id, self::META_KEY_LANG, true);
				if (is_string($menuLang) && $menuLang !== '') {
					$translations[$menuLang] = (int) $menu->term_id;
				}
			}
		}

		return $translations;
	}

	/**
	 * Get or create a translation group ID for a menu.
	 */
	private function getOrCreateGroupId(int $menuId): string
	{
		$groupId = get_term_meta($menuId, self::META_KEY_GROUP, true);

		if (!empty($groupId) && is_string($groupId)) {
			return $groupId;
		}

		// Generate a unique group ID
		$groupId = 'sml_menu_' . $menuId . '_' . wp_generate_password(8, false);
		update_term_meta($menuId, self::META_KEY_GROUP, $groupId);

		return $groupId;
	}

	/**
	 * Handle saving menu translation links from admin.
	 */
	public function handleMenuSave(int $menuId): void
	{
		if (!current_user_can('edit_theme_options')) {
			return;
		}

		if (!isset($_POST['sml_menu_nonce'])) {
			return;
		}

		if (!wp_verify_nonce($_POST['sml_menu_nonce'], 'sml_menu_translation')) {
			return;
		}

		// Handle creating new translations
		if (isset($_POST['sml_create_menu_translation'])) {
			$langCode = sanitize_text_field($_POST['sml_create_menu_translation']);
			$langManager = LanguageManager::load();

			if ($langManager->isActiveLanguage($langCode)) {
				$this->createMenuTranslation($menuId, $langCode);
			}
		}

		// Handle linking existing menus
		if (isset($_POST['sml_link_menu']) && is_array($_POST['sml_link_menu'])) {
			foreach ($_POST['sml_link_menu'] as $langCode => $targetMenuId) {
				$langCode = sanitize_text_field($langCode);
				$targetMenuId = (int) $targetMenuId;

				if ($targetMenuId > 0) {
					$this->linkMenuTranslation($menuId, $targetMenuId, $langCode);
				}
			}
		}
	}

	/**
	 * Render the menu translation UI on the Appearance > Menus screen.
	 */
	public function renderMenuTranslationUi(): void
	{
		if (!current_user_can('edit_theme_options')) {
			return;
		}

		$langManager = LanguageManager::load();
		$languages = $langManager->getActiveLanguages();

		if (count($languages) < 2) {
			return;
		}

		$currentMenuId = $this->getCurrentAdminMenuId();
		if ($currentMenuId === 0) {
			return;
		}

		$translations = $this->getMenuTranslations($currentMenuId);
		$currentMenuLang = get_term_meta($currentMenuId, self::META_KEY_LANG, true);
		$defaultLang = $langManager->getDefaultLanguageCode();
		$allMenus = wp_get_nav_menus();

		if (empty($currentMenuLang)) {
			$currentMenuLang = $defaultLang;
		}

		?>
		<script>
		(function() {
			var wrapper = document.getElementById('nav-menu-header');
			if (!wrapper) return;

			var container = document.createElement('div');
			container.className = 'sml-menu-translations';
			container.style.cssText = 'padding: 10px 0; border-top: 1px solid #ddd; margin-top: 10px;';
			container.innerHTML = <?php echo wp_json_encode($this->getMenuTranslationHtml($languages, $translations, $currentMenuId, (string) $currentMenuLang, $allMenus)); ?>;

			var form = wrapper.closest('form');
			if (form) {
				var manageLocations = form.querySelector('.menu-settings');
				if (manageLocations) {
					manageLocations.parentNode.insertBefore(container, manageLocations);
				} else {
					form.appendChild(container);
				}
			}
		})();
		</script>
		<?php
	}

	/**
	 * Generate the HTML for the menu translation management section.
	 *
	 * @param array<string, object> $languages
	 * @param array<string, int> $translations
	 * @param array<int, \WP_Term> $allMenus
	 */
	private function getMenuTranslationHtml(
		array $languages,
		array $translations,
		int $currentMenuId,
		string $currentMenuLang,
		array $allMenus
	): string {
		$html = '<h3>' . esc_html__('Menu Translations', 'signocore-multilanguage') . '</h3>';
		$html .= wp_nonce_field('sml_menu_translation', 'sml_menu_nonce', true, false);
		$html .= '<table class="widefat" style="margin-top: 8px;">';
		$html .= '<thead><tr>';
		$html .= '<th>' . esc_html__('Language', 'signocore-multilanguage') . '</th>';
		$html .= '<th>' . esc_html__('Menu', 'signocore-multilanguage') . '</th>';
		$html .= '<th>' . esc_html__('Actions', 'signocore-multilanguage') . '</th>';
		$html .= '</tr></thead><tbody>';

		foreach ($languages as $lang) {
			if ($lang->code === $currentMenuLang) {
				$html .= '<tr>';
				$html .= '<td><strong>' . esc_html($lang->name) . '</strong></td>';
				$html .= '<td>' . esc_html__('Current menu', 'signocore-multilanguage') . '</td>';
				$html .= '<td>&mdash;</td>';
				$html .= '</tr>';
				continue;
			}

			$html .= '<tr>';
			$html .= '<td>' . esc_html($lang->name) . '</td>';

			if (isset($translations[$lang->code])) {
				$linkedMenu = wp_get_nav_menu_object($translations[$lang->code]);
				$menuName = $linkedMenu !== false ? $linkedMenu->name : __('(Unknown)', 'signocore-multilanguage');
				$editUrl = admin_url('nav-menus.php?action=edit&menu=' . $translations[$lang->code]);

				$html .= '<td>' . esc_html($menuName) . '</td>';
				$html .= '<td><a href="' . esc_url($editUrl) . '" class="button button-small">' . esc_html__('Edit', 'signocore-multilanguage') . '</a></td>';
			} else {
				$html .= '<td>';
				$html .= '<select name="sml_link_menu[' . esc_attr($lang->code) . ']" style="width: 200px;">';
				$html .= '<option value="0">' . esc_html__('-- None --', 'signocore-multilanguage') . '</option>';

				foreach ($allMenus as $menu) {
					if ((int) $menu->term_id === $currentMenuId) {
						continue;
					}
					$html .= '<option value="' . (int) $menu->term_id . '">' . esc_html($menu->name) . '</option>';
				}

				$html .= '</select>';
				$html .= '</td>';
				$html .= '<td>';
				$html .= '<button type="submit" name="sml_create_menu_translation" value="' . esc_attr($lang->code) . '" class="button button-small">' . esc_html__('Create', 'signocore-multilanguage') . '</button>';
				$html .= '</td>';
			}

			$html .= '</tr>';
		}

		$html .= '</tbody></table>';

		return $html;
	}

	/**
	 * Get the currently edited menu ID in admin.
	 */
	private function getCurrentAdminMenuId(): int
	{
		if (isset($_REQUEST['menu'])) {
			return (int) $_REQUEST['menu'];
		}

		$locations = get_nav_menu_locations();
		if (!empty($locations)) {
			return (int) reset($locations);
		}

		$menus = wp_get_nav_menus();
		if (!empty($menus)) {
			return (int) $menus[0]->term_id;
		}

		return 0;
	}
}
