<?php namespace BulkPriceEditor\ProductFilters\Filters;

use BulkPriceEditor\PriceEditorPage\Services\LookupService;
use BulkPriceEditor\PriceEditorPage\Widgets\Widget;
use BulkPriceEditor\ProductQuery\ProductQuery;
use WC_Product_Variable;
use WP_Term;

class IncludedProducts extends Filter {
	
	public function getTitle(): string {
		return __( 'Included Products', 'bulk-price-editor' );
	}
	
	public function getIncludedProducts( string $return = 'ids', bool $includeChild = false ): array {
		
		$productIds = $this->sanitizeArrayIds( $this->getFilterValue( 'bpe_included_product_ids', array() ) );
		
		if ( $includeChild ) {
			$productIds = $this->flattenArray( array_map( function ( $productId ) {
				$product = wc_get_product( $productId );
				
				if ( $product instanceof WC_Product_Variable ) {
					return array( $product->get_id(), ...$product->get_children() );
				}
				
				return $productId;
				
			}, $productIds ) );
		}
		
		if ( 'ids' === $return ) {
			return $productIds;
		}
		
		$products = array();
		
		foreach ( $this->sanitizeArrayIds( $productIds ) as $productId ) {
			$product = wc_get_product( $productId );
			
			if ( $product ) {
				$products[ $product->get_id() ] = $product->get_name() . ' (#' . $product->get_id() . ')';
			}
		}
		
		return $products;
	}
	
	public function getIncludedCategories( string $return = 'ids', bool $includeChild = false ): ?array {
		$categoriesIds = $this->sanitizeArrayIds( $this->getFilterValue( 'bpe_included_category_ids', array() ) );

		if ( $includeChild ) {
			$categoriesIds = $this->flattenArray( array_map( function ( $categoryId ) {
				$children = get_term_children( $categoryId, 'product_cat' );
				
				if ( is_array( $children ) ) {
					return array( $categoryId, ...$children );
				}
				
				return $categoryId;
			}, $categoriesIds ) );
		}
		
		if ( 'ids' === $return ) {
			return $categoriesIds;
		}
		
		$categories = array();
		
		foreach ( $categoriesIds as $categoryId ) {
			$category = get_term( $categoryId, 'product_cat' );
			
			if ( $category instanceof WP_Term ) {
				$categories[ $category->term_id ] = $category->name;
			}
		}
		
		return $categories;
	}
	
	public function filterQuery( ProductQuery $query ): void {
		
		$products = $this->getIncludedProducts( 'ids', true );
		
		if ( ! empty( $products ) ) {
			$query->args['include'] = $products;
		}
		
		$categories = $this->getIncludedCategories( 'ids', true );
		
		if ( empty( $categories ) ) {
			return;
		}
		
		$taxQuery = $query->args['tax_query'] ?? array();
		
		$taxQuery[] = array(
			'taxonomy' => 'product_cat',
			'field'    => 'term_id',
			'terms'    => $categories,
			'operator' => 'IN',
		);

		$query->args['tax_query'] = $taxQuery;
	}
	
	public function getSectionArgs(): array {
		return array(
			'open' => ! empty( $this->getIncludedCategories() ) || ! empty( $this->getIncludedProducts() ),
		);
	}
	
	public function renderFields( Widget $widget ) {
		
		$widget->renderSelect2( array(
			'id'                => 'bpe_included_category_ids',
			'attributes'        => 'multiple',
			'label'             => __( 'Include product categories', 'bulk-price-editor' ),
			'placeholder'       => __( 'Select product categories', 'bulk-price-editor' ),
			'search_action'     => LookupService::CATEGORIES_SEARCH_ACTION,
			'value'             => $this->getIncludedCategories( 'array', false ),
			'custom_attributes' => array(
				'data-product-filter' => 'yes',
			),
		) );
		
		$widget->renderSelect2( array(
			'id'                => 'bpe_included_product_ids',
			'label'             => __( 'Include products', 'bulk-price-editor' ),
			'placeholder'       => __( 'Select products', 'bulk-price-editor' ),
			'search_action'     => 'woocommerce_json_search_products_and_variations',
			'value'             => $this->getIncludedProducts( 'array', false ),
			'custom_attributes' => array(
				'data-product-filter' => 'yes',
			),
		) );
	}
	
	protected function flattenArray( array $array ): array {
		$result = [];
		foreach ( $array as $item ) {
			if ( is_array( $item ) ) {
				$result = array_merge( $result, $this->flattenArray( $item ) );
			} else {
				$result[] = $item;
			}
		}
		
		return $result;
	}
}
