<?php
/**
 * Polylang integration helpers: language context switching and currency resolution.
 *
 * Provides two independent mechanisms:
 *
 * 1. Instance methods switch_to() / restore() — temporarily set Polylang's
 *    current language for WooCommerce product queries that rely on it.
 *    These are a best-effort no-op when pll_set_current_language() is absent.
 *
 * 2. Static currency methods — resolve the WooCommerce currency for a given
 *    language via direct Polylang term-meta lookup. Works on ALL Polylang
 *    versions (including those without pll_set_current_language), in REST API
 *    contexts, CLI, and frontend alike. This is the PREFERRED approach for
 *    currency resolution — do NOT rely on pll_set_current_language() for it.
 *
 * @package BoostBot
 * @since   1.3.1
 */

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

class BoostBot_Polylang_Context {

    /** @var string|null */
    private $original_language = null;

    /** @var bool */
    private $switched = false;

    /**
     * Switch Polylang's current language to the given language.
     * Saves the original language for later restoration.
     *
     * @param string $language The target language slug (e.g. 'en', 'he').
     * @return bool Whether the switch was performed.
     */
    public function switch_to( string $language ): bool {
        if ( ! function_exists( 'pll_current_language' ) || ! function_exists( 'pll_set_current_language' ) ) {
            return false;
        }

        $this->original_language = pll_current_language();

        if ( $this->original_language === $language ) {
            return false;
        }

        pll_set_current_language( $language );
        $this->switched = true;
        return true;
    }

    /**
     * Restore Polylang's language to whatever it was before switch_to().
     */
    public function restore(): void {
        if ( ! $this->switched ) {
            return;
        }

        if ( $this->original_language && function_exists( 'pll_set_current_language' ) ) {
            pll_set_current_language( $this->original_language );
        }

        $this->switched          = false;
        $this->original_language = null;
    }

    // ──────────────────────────────────────────────────────────────
    //  Static currency resolution (direct term-meta — always works)
    // ──────────────────────────────────────────────────────────────

    /**
     * Get the WooCommerce currency code and symbol for a given language.
     *
     * Uses direct Polylang term meta lookup — works in all contexts
     * (REST API, CLI, frontend, admin) and on all Polylang versions.
     *
     * @param string $language Language slug (e.g., 'en', 'he').
     * @return array{code: string, symbol: string} Currency info with HTML entities decoded.
     */
    public static function get_currency_for_language( string $language ): array {
        $default_code   = function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : 'ILS';
        $default_symbol = function_exists( 'get_woocommerce_currency_symbol' )
            ? html_entity_decode( get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' )
            : '₪';

        if ( ! taxonomy_exists( 'language' ) ) {
            return array( 'code' => $default_code, 'symbol' => $default_symbol );
        }

        $lang_term = get_term_by( 'slug', $language, 'language' );
        if ( ! $lang_term || is_wp_error( $lang_term ) ) {
            return array( 'code' => $default_code, 'symbol' => $default_symbol );
        }

        $currency_code = get_term_meta( $lang_term->term_id, 'woocommerce_currency', true );
        if ( empty( $currency_code ) ) {
            return array( 'code' => $default_code, 'symbol' => $default_symbol );
        }

        $symbol = function_exists( 'get_woocommerce_currency_symbol' )
            ? html_entity_decode( get_woocommerce_currency_symbol( $currency_code ), ENT_QUOTES, 'UTF-8' )
            : $currency_code;

        return array( 'code' => $currency_code, 'symbol' => $symbol );
    }

    /**
     * Temporarily override WooCommerce's currency filter for a specific language.
     *
     * Use this when calling WC functions that read the currency via the
     * 'woocommerce_currency' filter (e.g. get_price_html(), wc_price()).
     * Call restore_currency() with the returned callback when done.
     *
     * @param string $language Language slug.
     * @return callable|null The filter callback (needed for removal), or null if no override was needed.
     */
    public static function override_currency_for_language( string $language ): ?callable {
        $currency = self::get_currency_for_language( $language );
        $current  = function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : '';

        if ( $currency['code'] === $current ) {
            return null;
        }

        $callback = static function () use ( $currency ) {
            return $currency['code'];
        };

        add_filter( 'woocommerce_currency', $callback, 99999 );
        return $callback;
    }

    /**
     * Remove a currency override filter previously set by override_currency_for_language().
     *
     * @param callable|null $callback The callback returned by override_currency_for_language().
     */
    public static function restore_currency( ?callable $callback ): void {
        if ( $callback ) {
            remove_filter( 'woocommerce_currency', $callback, 99999 );
        }
    }
}
