<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\Infrastructure\Compatibility;

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

use Signocore\Multilanguage\Features\LanguageDetection;
use Signocore\Multilanguage\Features\LanguageManager;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;
use Signocore\Multilanguage\Support\TranslationHelper;

/**
 * Yoast SEO compatibility — provides translated SEO meta per language.
 *
 * Yoast does not output its own hreflang tags, so our built-in
 * hreflang output works without conflicts.
 */
final class Yoast
{
	use Singleton;

	protected function init(): void
	{
		if (!defined('WPSEO_FILE')) {
			return;
		}

		add_filter('wpseo_title', [$this, 'filterMetaTitle'], 10, 2);
		add_filter('wpseo_metadesc', [$this, 'filterMetaDescription'], 10, 2);
		add_filter('wpseo_canonical', [$this, 'filterCanonicalUrl'], 10, 2);
		add_filter('wpseo_og_locale', [$this, 'filterOgLocale'], 10, 2);

		do_action('signocore_ml_yoast_loaded');
	}

	/**
	 * Filter meta title to use the translated post's Yoast title.
	 *
	 * @param string $title
	 * @param mixed $presentation
	 */
	public function filterMetaTitle(string $title, $presentation): string
	{
		$postId = $this->getQueriedPostId();
		if ($postId === null) {
			return $title;
		}

		$translatedId = $this->getTranslatedPostId($postId);
		if ($translatedId === null) {
			return $title;
		}

		$translatedTitle = get_post_meta($translatedId, '_yoast_wpseo_title', true);
		if (is_string($translatedTitle) && $translatedTitle !== '') {
			return $translatedTitle;
		}

		return $title;
	}

	/**
	 * Filter meta description to use the translated post's Yoast description.
	 *
	 * @param string $description
	 * @param mixed $presentation
	 */
	public function filterMetaDescription(string $description, $presentation): string
	{
		$postId = $this->getQueriedPostId();
		if ($postId === null) {
			return $description;
		}

		$translatedId = $this->getTranslatedPostId($postId);
		if ($translatedId === null) {
			return $description;
		}

		$translatedDesc = get_post_meta($translatedId, '_yoast_wpseo_metadesc', true);
		if (is_string($translatedDesc) && $translatedDesc !== '') {
			return $translatedDesc;
		}

		return $description;
	}

	/**
	 * Filter canonical URL to point to the correct language version.
	 *
	 * @param string $canonical
	 * @param mixed $presentation
	 */
	public function filterCanonicalUrl(string $canonical, $presentation): string
	{
		$postId = $this->getQueriedPostId();
		if ($postId === null) {
			return $canonical;
		}

		$translatedId = $this->getTranslatedPostId($postId);
		if ($translatedId === null) {
			return $canonical;
		}

		return get_permalink($translatedId) ?: $canonical;
	}

	/**
	 * Filter OG locale to match the current language.
	 *
	 * @param string $locale
	 * @param mixed $presentation
	 */
	public function filterOgLocale(string $locale, $presentation): string
	{
		$languages = LanguageManager::load()->getActiveLanguages();
		$currentLang = LanguageDetection::load()->getCurrentLanguage();

		if (isset($languages[$currentLang])) {
			return $languages[$currentLang]->locale;
		}

		return $locale;
	}

	/**
	 * Get the current queried post ID on singular pages.
	 */
	private function getQueriedPostId(): ?int
	{
		if (!is_singular()) {
			return null;
		}

		$postId = get_queried_object_id();
		return $postId > 0 ? $postId : null;
	}

	/**
	 * Get the translated post ID for the current language.
	 *
	 * Returns null if the post is already in the current language
	 * or no translation exists.
	 */
	private function getTranslatedPostId(int $postId): ?int
	{
		$currentLang = LanguageDetection::load()->getCurrentLanguage();
		$postLang = TranslationHelper::getElementLanguage($postId);

		if ($postLang === $currentLang) {
			return null;
		}

		return TranslationHelper::getTranslation($postId, $currentLang);
	}
}
