<?php
declare( strict_types=1 );

namespace FiboFilters\SeoRules;

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

/**
 * Resolves base_view from SeoRule into a base URL,
 * builds final URLs for filter combinations,
 * and maps current request context to base_view strings.
 */
class SeoRuleUrlResolver {
	/**
	 * Parses base_view string into type and arg.
	 *
	 * @param string $base_view The base view string from SeoRule.
	 *
	 * @return array
	 */
	public static function parse_base_view( string $base_view ): array {
		$parts = explode( ':', $base_view, 2 );

		$type = trim( $parts[0] ?? '' );
		$arg  = trim( $parts[1] ?? '' );

		return [ $type, $arg ];
	}

	/**
	 * Map Request::get_context() structure to SeoRule::base_view string.
	 *
	 * @param array $context Context from fibofilters/request/get_context.
	 *
	 * @return string base_view like "shop:main" or "product_cat:225" or '' when unsupported.
	 */
	public function resolve_base_view_from_context( array $context ): string {
		$conditions = $context['conditions'] ?? [];
		$details    = $context['details'] ?? [];

		if (
			! empty( $conditions['is_product_taxonomy'] ) &&
			! empty( $details['taxonomy'] ) &&
			! empty( $details['term_id'] )
		) {
			$taxonomy = $details['taxonomy'];
			$term_id  = (int) $details['term_id'];

			if ( $term_id > 0 && in_array( $taxonomy, [ 'product_cat', 'product_tag' ], true ) ) {
				return $taxonomy . ':' . $term_id;
			}

			return '';
		}

		if ( ! empty( $conditions['is_shop'] ) ) {
			return 'shop:main';
		}

		return '';
	}

	/**
	 * Builds final URLs for a given filter combination as a normalized list of rows.
	 *
	 * Each row is an array with keys:
	 * [
	 *   'url'     => 'https://...',
	 *   'context' => [ ... ] optional context data, e.g. for "product_cat:any" case.
	 * ].
	 *
	 * @param SeoRule $rule        Seo rule.
	 * @param array   $combination Filter combination data.
	 *
	 * @return array[]
	 */
	public function build_url_rows_from_combination( SeoRule $rule, array $combination ): array {
		$query_args = $this->build_query_args_from_combination( $combination );
		$base_view  = $rule->get_base_view();

		list( $type, $arg ) = self::parse_base_view( $base_view );

		// Special case: product_cat:any.
		if ( $type === 'product_cat' && $arg === 'any' ) {
			return $this->build_rows_for_any_product_cat( $query_args );
		}

		// Other cases: shop:main, product_cat:ID, product_tag:ID, etc.
		$base_url = $this->resolve_base_view_to_url( $base_view );

		return [
			[
				'url' => add_query_arg( $query_args, $base_url ),
			],
		];
	}

	/**
	 * Builds query args array from filter combination.
	 *
	 * @param array $combination Filter combination data.
	 *
	 * @return array
	 */
	private function build_query_args_from_combination( array $combination ): array {
		$query_args = [];

		foreach ( $combination as $slug => $data ) {
			if ( ! empty( $data['slug'] ) ) {
				$query_args[ $slug ] = $data['slug'];
			}
		}

		return $query_args;
	}

	/**
	 * Builds URL rows for "product_cat:any"
	 *  - retrieves all product_cat categories,
	 *  - creates a separate URL for each,
	 *  - adds context with taxonomy + term_id (then used in {@see SeoRuleEngine}).
	 *
	 * @param array $query_args Query args to append to each URL.
	 *
	 * @return array[]
	 */
	private function build_rows_for_any_product_cat( array $query_args ): array {
		$terms = get_terms(
			[
				'taxonomy'   => 'product_cat',
				'hide_empty' => false,
				'fields'     => 'all',
			]
		);

		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return [];
		}

		// Sort by slug to have consistent order.
		usort(
			$terms,
			static function ( \WP_Term $a, \WP_Term $b ): int {
				return strcmp( $a->slug, $b->slug );
			}
		);

		$rows = [];

		foreach ( $terms as $term ) {
			$term_id = $term->term_id;

			if ( $term_id <= 0 ) {
				continue;
			}

			$cat_base_view = 'product_cat:' . $term_id;
			$base_url      = $this->resolve_base_view_to_url( $cat_base_view );

			$rows[] = [
				'url'     => add_query_arg( $query_args, $base_url ),
				'context' => [
					'taxonomy' => 'product_cat',
					'term_id'  => $term_id,
				],
			];
		}

		return $rows;
	}

	/**
	 * Resolve base_view (e.g. "shop:main", "product_cat:225") to a base URL.
	 *
	 * @param string $base_view The base view string from SeoRule.
	 */
	private function resolve_base_view_to_url( string $base_view ): string {

		list( $type, $arg ) = self::parse_base_view( $base_view );

		switch ( $type ) {
			case 'shop':
				return $this->get_default_shop_or_archive_url();
			case 'product_cat':
			case 'product_tag':
				$term_id = (int) $arg;

				if ( $term_id > 0 && function_exists( 'get_term_link' ) ) {
					$taxonomy = ( $type === 'product_cat' ) ? 'product_cat' : 'product_tag';

					$link = get_term_link( $term_id, $taxonomy );
					if ( ! is_wp_error( $link ) ) {
						return $link;
					}
				}
				return $this->get_product_archive_or_home_url();
			default:
				return $this->get_product_archive_or_home_url();
		}
	}

	/**
	 * Returns WooCommerce shop page URL if configured,
	 * otherwise product archive or home URL.
	 */
	private function get_default_shop_or_archive_url(): string {
		if ( function_exists( 'wc_get_page_permalink' ) ) {
			$url = wc_get_page_permalink( 'shop' );
			if ( $url ) {
				return $url;
			}
		}

		return $this->get_product_archive_or_home_url();
	}

	/**
	 * Returns product archive URL if available, otherwise home URL.
	 */
	private function get_product_archive_or_home_url(): string {
		$url = get_post_type_archive_link( 'product' );

		if ( ! $url ) {
			$url = home_url( '/' );
		}

		return $url;
	}
}
