<?php
declare(strict_types=1);

namespace Ekesto\CacheWarmup\Multilingual\Adapters;

use Ekesto\CacheWarmup\Multilingual\LanguageAdapterInterface;

/**
 * Polylang language adapter for multilingual URL and post-language resolution.
 */
final class PolylangAdapter implements LanguageAdapterInterface
{
    /**
     * Detect whether Polylang integrations are available.
     *
     * @return bool
     */
    public function isActive(): bool
    {
        return defined('POLYLANG_VERSION')
            && function_exists('pll_default_language')
            && function_exists('pll_get_post_language');
    }

    /**
     * Return the stable adapter key.
     *
     * @return string
     */
    public function getKey(): string
    {
        return 'polylang';
    }

    /**
     * Resolve the Polylang default language code.
     *
     * @return string|null Lowercased language code, or null when unavailable.
     */
    public function getDefaultLanguage(): ?string
    {
        if (!$this->isActive()) {
            return null;
        }

        return $this->normalizeLanguage(pll_default_language('slug'));
    }

    /**
     * Resolve the Polylang language code for a specific post.
     *
     * @param int $postId WordPress post ID.
     * @param string $postType Post type key.
     * @return string|null Lowercased language code, or null when unavailable.
     */
    public function getPostLanguage(int $postId, string $postType): ?string
    {
        if (!$this->isActive() || $postId <= 0 || $postType === '') {
            return null;
        }

        return $this->normalizeLanguage(pll_get_post_language($postId, 'slug'));
    }

    /**
     * Resolve the Polylang language code for a URL.
     *
     * @param string $url Absolute URL.
     * @return string|null Lowercased language code, or null when unavailable.
     */
    public function getUrlLanguage(string $url): ?string
    {
        if (!$this->isActive() || $url === '') {
            return null;
        }

        $postId = url_to_postid($url);
        if ($postId <= 0) {
            return null;
        }

        $postType = get_post_type($postId);
        if (!is_string($postType) || $postType === '') {
            return null;
        }

        return $this->getPostLanguage($postId, $postType);
    }

    /**
     * Resolve a post permalink in the post's own Polylang language.
     *
     * @param int $postId WordPress post ID.
     * @param string $postType Post type key.
     * @param string $url Raw permalink URL.
     * @return string Localized permalink URL.
     */
    public function resolvePostPermalink(int $postId, string $postType, string $url): string
    {
        if ($url === '' || !$this->isActive() || !function_exists('pll_get_post')) {
            return $url;
        }

        $language = $this->getPostLanguage($postId, $postType);
        if ($language === null) {
            return $url;
        }

        $localizedPostId = (int) pll_get_post($postId, $language);
        if ($localizedPostId <= 0) {
            return $url;
        }

        $localizedUrl = (string) get_permalink($localizedPostId);
        return $localizedUrl !== '' ? $localizedUrl : $url;
    }

    /**
     * Normalize language values from third-party APIs.
     *
     * @param mixed $language
     * @return string|null
     */
    private function normalizeLanguage($language): ?string
    {
        if (!is_string($language)) {
            return null;
        }

        $language = trim($language);
        return $language !== '' ? strtolower($language) : null;
    }
}
