<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\Features;

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

use Signocore\Multilanguage\Application\Constants;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;
use Signocore\Multilanguage\Support\FlagHelper;
use Signocore\Multilanguage\Support\LocaleHelper;

/**
 * Injects language switcher links into selected WordPress navigation menus.
 */
final class MenuSwitcherInjection
{
	use Singleton;

	protected function init(): void
	{
		add_filter('wp_nav_menu_items', [$this, 'injectSwitcher'], 20, 2);
	}

	/**
	 * Inject language links into the menu if it matches a selected menu.
	 */
	public function injectSwitcher(string $items, object $args): string
	{
		$selectedMenus = (array) get_option(Constants::OPTION_PREFIX . 'switcher_menu_menus', []);

		if (empty($selectedMenus)) {
			return $items;
		}

		$menuId = $this->resolveMenuId($args);

		if ($menuId === 0 || !in_array((string) $menuId, $selectedMenus, true)) {
			return $items;
		}

		$languageItems = $this->renderLanguageItems();

		if ($languageItems === '') {
			return $items;
		}

		$position = (string) get_option(Constants::OPTION_PREFIX . 'switcher_menu_position', 'end');

		if ($position === 'start') {
			return $languageItems . $items;
		}

		return $items . $languageItems;
	}

	/**
	 * Resolve the menu term ID from wp_nav_menu args.
	 */
	private function resolveMenuId(object $args): int
	{
		$menu = $args->menu ?? null;

		if ($menu instanceof \WP_Term) {
			return (int) $menu->term_id;
		}

		if (is_numeric($menu) && (int) $menu > 0) {
			return (int) $menu;
		}

		// Menu passed as slug or name — resolve via theme location
		if (!empty($args->theme_location)) {
			$locations = get_nav_menu_locations();
			if (isset($locations[$args->theme_location])) {
				return (int) $locations[$args->theme_location];
			}
		}

		return 0;
	}

	/**
	 * Render language links as menu list items, respecting the switcher style.
	 */
	private function renderLanguageItems(): string
	{
		$switcher = LanguageSwitcher::load();
		$links = $switcher->getLanguageLinks();

		if (empty($links)) {
			return '';
		}

		// Hide languages that don't have a translation of the current page.
		$links = array_values(array_filter($links, fn (array $link): bool => $link['has_translation'] || $link['is_current']));

		if (count($links) <= 1) {
			return '';
		}

		$style = (string) get_option(Constants::OPTION_PREFIX . 'switcher_style', 'dropdown');
		$showFlags = (bool) get_option(Constants::OPTION_PREFIX . 'switcher_show_flags', true);
		$showNames = (bool) get_option(Constants::OPTION_PREFIX . 'switcher_show_names', true);

		if ($style === 'dropdown') {
			return $this->renderDropdown($links, $showFlags, $showNames);
		}

		if ($style === 'flags') {
			return $this->renderFlagsOnly($links);
		}

		return $this->renderFlat($links, $showFlags, $showNames);
	}

	/**
	 * Render as a WordPress submenu dropdown (parent + sub-menu).
	 *
	 * @param array<int, array{code: string, name: string, native_name: string, url: string, is_current: bool, has_translation: bool, flag_url: string}> $links
	 */
	private function renderDropdown(array $links, bool $showFlags, bool $showNames): string
	{
		$currentLink = null;
		foreach ($links as $link) {
			if ($link['is_current']) {
				$currentLink = $link;
				break;
			}
		}

		if ($currentLink === null) {
			$currentLink = $links[0];
		}

		$parentLabel = $this->buildLabel($currentLink, $showFlags, $showNames);

		$parentHreflang = LocaleHelper::getHreflangCode($currentLink['code']);

		$html = '<li class="menu-item menu-item-has-children sml-menu-switcher-item">';
		$html .= '<span class="sml-switcher-link sml-active">' . $parentLabel . '</span>';
		$html .= '<ul class="sub-menu">';

		foreach ($links as $link) {
			$classes = 'menu-item sml-menu-switcher-item';

			if ($link['is_current']) {
				$classes .= ' current-menu-item';
			}

			$hreflang = LocaleHelper::getHreflangCode($link['code']);
			$label = $this->buildLabel($link, $showFlags, $showNames);

			$html .= '<li class="' . esc_attr($classes) . '">';

			if ($link['is_current']) {
				$html .= '<span class="sml-switcher-link sml-active">' . $label . '</span>';
			} else {
				$html .= '<a href="' . esc_url($link['url']) . '" hreflang="' . esc_attr($hreflang) . '">';
				$html .= $label;
				$html .= '</a>';
			}

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

		$html .= '</ul>';
		$html .= '</li>';

		return $html;
	}

	/**
	 * Render flags-only style (no text, just flag images).
	 *
	 * @param array<int, array{code: string, name: string, native_name: string, url: string, is_current: bool, has_translation: bool, flag_url: string}> $links
	 */
	private function renderFlagsOnly(array $links): string
	{
		$html = '';

		foreach ($links as $link) {
			$classes = 'menu-item sml-menu-switcher-item';

			if ($link['is_current']) {
				$classes .= ' current-menu-item';
			}

			$hreflang = LocaleHelper::getHreflangCode($link['code']);
			$flagImg = FlagHelper::getFlagImg($link['code'], 20, 15, $link['name']);

			$html .= '<li class="' . esc_attr($classes) . '">';

			if ($link['is_current']) {
				$html .= '<span class="sml-switcher-link sml-active" title="' . esc_attr($link['name']) . '">';
				$html .= $flagImg;
				$html .= '</span>';
			} else {
				$html .= '<a href="' . esc_url($link['url']) . '" hreflang="' . esc_attr($hreflang) . '" title="' . esc_attr($link['name']) . '">';
				$html .= $flagImg;
				$html .= '</a>';
			}

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

		return $html;
	}

	/**
	 * Render flat list items (for list and inline styles).
	 *
	 * @param array<int, array{code: string, name: string, native_name: string, url: string, is_current: bool, has_translation: bool, flag_url: string}> $links
	 */
	private function renderFlat(array $links, bool $showFlags, bool $showNames): string
	{
		$html = '';

		foreach ($links as $link) {
			$classes = 'menu-item sml-menu-switcher-item';

			if ($link['is_current']) {
				$classes .= ' current-menu-item';
			}

			$hreflang = LocaleHelper::getHreflangCode($link['code']);
			$label = $this->buildLabel($link, $showFlags, $showNames);

			$html .= '<li class="' . esc_attr($classes) . '">';

			if ($link['is_current']) {
				$html .= '<span class="sml-switcher-link sml-active">' . $label . '</span>';
			} else {
				$html .= '<a href="' . esc_url($link['url']) . '" hreflang="' . esc_attr($hreflang) . '">';
				$html .= $label;
				$html .= '</a>';
			}

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

		return $html;
	}

	/**
	 * Build a label with optional flag and name.
	 *
	 * @param array{code: string, name: string, native_name: string, url: string, is_current: bool, has_translation: bool, flag_url: string} $link
	 */
	private function buildLabel(array $link, bool $showFlags, bool $showNames): string
	{
		$label = '';

		if ($showFlags && !empty($link['flag_url'])) {
			$label .= FlagHelper::getFlagImg($link['code'], 20, 15, $link['name']);
		}

		if ($showNames) {
			$label .= '<span class="sml-lang-name">' . esc_html($link['name']) . '</span>';
		}

		if ($label === '') {
			$label = esc_html($link['name']);
		}

		return $label;
	}
}
