<?php
declare( strict_types=1 );

namespace FiboFilters\API;

use FiboFilters\Filters\StoreFilters;
use FiboFilters\Index\Sources;
use FiboFilters\Index\Values;
use FiboFilters\Struct\QueryContext;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;

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

/**
 * Class SEORules
 */
class SEORules {
	/** @var Values */
	private $values;

	/** @var Sources */
	private $sources;

	/** @var StoreFilters */
	private $store_filters;

	/**
	 * SEORules constructor.
	 *
	 * @param Values       $values
	 * @param Sources      $sources
	 * @param StoreFilters $store_filters
	 */
	public function __construct( Values $values, Sources $sources, StoreFilters $store_filters ) {
		$this->values        = $values;
		$this->sources       = $sources;
		$this->store_filters = $store_filters;
	}

	/**
	 * @param WP_REST_Request $request Request.
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function get_filter_values( WP_REST_Request $request ) {
		$filter = $request->get_param( 'filter' );
		$ctx    = new QueryContext();

		$source = $this->store_filters->get_filter_prop_by_other_prop_value( 'source', 'url_slug', $filter );
		if ( empty( $source ) ) {
			return new WP_Error( 'fibofilters_source_not_found' );
		}

		$source_id = $this->sources->get_source_id_by_name( $source, $ctx );
		if ( empty( $source_id ) ) {
			return new WP_Error( 'fibofilters_source_not_found' );
		}

		$values = $this->values->get_values_by_source_id( $source_id, $ctx );

		$result = array_map(
			function ( $item ) {
				return [
					'value' => $item['label_url'],
					'label' => $item['label'],
				];
			},
			$values
		);

		return new WP_REST_Response( $result );
	}

	/**
	 * @return WP_Error|WP_REST_Response
	 */
	public function get_base_view_values() {
		$result = [
			[
				'group_label' => _x( 'General', '[admin]', 'fibofilters' ),
				'options'     => [
					[
						'value' => 'shop:main',
						'label' => _x( 'Main shop page', '[admin]', 'fibofilters' ),
					],
				],
			],
		];

		$categories = $this->get_flatten_taxonomy_tree( 'product_cat' );

		if ( ! empty( $categories ) ) {
			$categories = array_merge(
				[
					[
						'value' => 'product_cat:any',
						'label' => _x( 'Any product category', '[admin]', 'fibofilters' ),
					],
				],
				$categories
			);

			$result[] = [
				'group_label' => _x( 'Product categories', '[admin]', 'fibofilters' ),
				'options'     => $categories,
			];
		}

		return new WP_REST_Response( $result );
	}

	private function get_flatten_taxonomy_tree( string $taxonomy ): array {
		$terms = get_terms(
			[
				'taxonomy'   => $taxonomy,
				'hide_empty' => false,
			]
		);

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

		$term_map = [];
		foreach ( $terms as $term ) {
			if ( $term->slug === 'uncategorized' ) {
				continue;
			}
			$term->children             = [];
			$term_map[ $term->term_id ] = $term;
		}

		$root_terms = [];
		foreach ( $term_map as $term ) {
			if ( $term->parent && isset( $term_map[ $term->parent ] ) ) {
				$term_map[ $term->parent ]->children[] = $term;
			} else {
				$root_terms[] = $term;
			}
		}

		$result = [];

		$flatten_tree = function ( $terms, $prefix = '' ) use ( &$flatten_tree, &$result, $taxonomy ) {
			foreach ( $terms as $term ) {
				$label    = $prefix ? $prefix . ' → ' . $term->name : $term->name;
				$result[] = [
					'value' => $taxonomy . ':' . $term->term_id,
					'label' => $label,
				];
				if ( ! empty( $term->children ) ) {
					$flatten_tree( $term->children, $label );
				}
			}
		};

		$flatten_tree( $root_terms );

		return $result;
	}
}
