<?php
declare( strict_types=1 );

namespace FiboFilters\Integrations\Multilingual;

use FiboFilters\Config\Env;
use FiboFilters\Filters\StoreFilters;

/**
 * Class Polylang
 */
class Polylang implements ProviderInterface {
	/** @var StoreFilters */
	private $store_filters;

	public function __construct( StoreFilters $store_filters ) {
		$this->store_filters = $store_filters;
	}

	public function init(): void {
	}

	public function is_active(): bool {
		return defined( 'POLYLANG_ROOT_FILE' );
	}

	public function get_name(): string {
		return 'Polylang';
	}

	public function get_languages( bool $include_invalid ): array { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		if ( ! function_exists( 'pll_languages_list' ) ) {
			return [];
		}
		return pll_languages_list(
			[
				'hide_empty' => false,
				'fields'     => 'slug',
			]
		);
	}

	public function get_current_language(): string {
		/** @var string $current_language */
		$current_language = pll_current_language( 'slug' );

		if ( empty( $current_language ) ) {
			$current_language = $this->get_default_language();
		}

		return (string) $current_language;
	}

	public function get_default_language(): string {
		if ( ! function_exists( 'pll_default_language' ) ) {
			return '';
		}
		/** @var string $language */
		$language = pll_default_language( 'slug' );

		return (string) $language;
	}

	public function get_post_language( int $post_id, string $post_type = 'product' ): string { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		return (string) pll_get_post_language( $post_id, 'slug' );
	}

	public function get_term_language( int $term_id, string $taxonomy ): string { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		return (string) pll_get_term_language( $term_id, 'slug' );
	}

	public function get_permalink( string $post_id, string $permalink = '', string $language = '', string $default_language = '' ): string { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		return $permalink;
	}

	public function get_terms_in_all_languages( string $taxonomy, array $languages, string $current_language ): array { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$result = get_terms(
			[
				'taxonomy'   => $taxonomy,
				'hide_empty' => true,
				'lang'       => '', // Query terms in all languages.
			]
		);
		if ( is_wp_error( $result ) ) {
			return [];
		}
		return $result;
	}

	public function get_terms_in_language( array $args = [], string $language = '', string $current_language = '' ): array { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$args = wp_parse_args(
			$args,
			[
				'taxonomy'   => '',
				'hide_empty' => true,
				'lang'       => $language,
			]
		);

		/** @var \WP_Error|\WP_Term[] $result */
		$result = get_terms( $args );
		if ( is_wp_error( $result ) ) {
			return [];
		}
		return $result;
	}

	public function get_term( int $term_id, string $taxonomy, string $language, string $current_language = '' ): ?\WP_Term { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$term    = null;
		$term_id = pll_get_term( $term_id, $language );

		if ( $term_id ) {
			$term = get_term( $term_id, $taxonomy );
		}

		return is_object( $term ) && is_a( $term, 'WP_Term' ) ? $term : null;
	}

	// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
	public function switch_language( string $language = '' ): void {
		if ( ! function_exists( 'PLL' ) ) {
			return;
		}

		$language_model = PLL()->model->get_language( $language );
		if ( $language_model === false ) {
			return;
		}

		PLL()->curlang = $language_model;
	}

	public function register_strings_for_translation(): void {
		if ( ! function_exists( 'pll_register_string' ) ) {
			return;
		}
		$filters = $this->store_filters->get_all_filters();

		foreach ( $filters as $filter ) {
			pll_register_string( $filter['label'], $filter['label'], Env::$plugin_slug );
			if ( $filter['type'] === 'category' ) {
				pll_register_string( $filter['label_category'], $filter['label_category'], Env::$plugin_slug );
				pll_register_string( $filter['label_subcategory'], $filter['label_subcategory'], Env::$plugin_slug );
			}
			if ( $filter['type'] === 'radio' && ! empty( $filter['any_label'] ) ) {
				pll_register_string( $filter['any_label'], $filter['any_label'], Env::$plugin_slug );
			}
		}
	}

	public function perform_frontend_actions(): void {
		$this->translate_strings();
		$this->adjust_config();
	}

	private function translate_strings(): void {
		add_filter(
			'fibofilters/filter/get_data',
			function ( $data, $context ) {
				if ( ! function_exists( 'pll__' ) ) {
					return $data;
				}
				if ( $context === 'frontend-filtering' ) {
					$data['label'] = pll__( $data['label'] );
					if ( $data['type'] === 'category' ) {
						$data['label_category']    = pll__( $data['label_category'] );
						$data['label_subcategory'] = pll__( $data['label_subcategory'] );
					}
				}
				return $data;
			},
			10,
			2
		);

		// Translate the phrase from the filter settings for "Any" value.
		add_filter(
			'fibofilters/filter/radio/any_label',
			function ( $any_label ) {
				if ( ! function_exists( 'pll__' ) ) {
					return $any_label;
				}

				return pll__( $any_label );
			}
		);
	}

	private function adjust_config() {
		if ( ! function_exists( 'PLL' ) ) {
			return;
		}

		/**
		 * Fix the URL of the descriptors JSON file to be in a subdomain or own domain of the current language.
		 *
		 * URL modifications:
		 * - force_lang === 2: The language is set from the subdomain name in pretty permalinks.
		 * - force_lang === 3: The language is set from different domains.
		 */
		if ( PLL()->options['force_lang'] === 2 || PLL()->options['force_lang'] === 3 ) {
			add_filter(
				'fibofilters/config/descriptors_json_url',
				function ( $url ) {
					if ( strpos( $url, '.json' ) !== false ) {
						$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
					}
					return $url;
				},
				20
			);
		}

		/**
		 * Add a language to the REST API endpoint.
		 *
		 * Without the "lang" attribute in the REST API, the language is not recognized
		 * and our plugin returns descriptors from the default language.
		 *
		 * URL modifications:
		 * - force_lang === 1: The language is set from the directory name in pretty permalinks.
		 * - force_lang === 2: The language is set from the subdomain name in pretty permalinks.
		 * - force_lang === 3: The language is set from different domains.
		 */
		if ( PLL()->options['force_lang'] === 1 || PLL()->options['force_lang'] === 2 || PLL()->options['force_lang'] === 3 ) {
			add_filter(
				'fibofilters/config/descriptors_endpoint',
				function ( $url ) {
					if ( $this->get_current_language() !== $this->get_default_language() ) {
						$url = add_query_arg( [ 'lang' => $this->get_current_language() ], $url );
					}

					return $url;
				}
			);
			add_filter(
				'fibofilters/config/updated_descriptors_endpoint',
				function ( $url ) {
					if ( $this->get_current_language() !== $this->get_default_language() ) {
						$url = add_query_arg( [ 'lang' => $this->get_current_language() ], $url );
					}

					return $url;
				}
			);
		}
	}
}
