<?php
/**
 * Prodigy categories data mapper
 *
 * @version    2.6.0
 * @package    Prodigy
 * @subpackage Prodigy/includes
 */
namespace Prodigy\Includes\Frontend\Mappers;

use Prodigy\Includes\Helpers\Prodigy_Page;
use Prodigy\includes\models\Prodigy_Product_Attributes;
use Prodigy\Includes\Models\Prodigy_Taxonomies;
use Prodigy\Includes\Prodigy;

defined( 'ABSPATH' ) || exit;

class Prodigy_Categories_Data_Mapper extends Prodigy_Main_Data_Mapper {
	const DESCENDING_SORT            = 'DESC';
	const WIDGET_DISPLAY_GRID_TYPE   = 'grid';
	const WIDGET_DISPLAY_SLIDER_TYPE = 'slider';
	const COUNT_COLUMNS_CATEGORY     = 5;
	const FAKE_IMG_URL = 'https://prodigycommerce-public-files.s3.us-east-2.amazonaws.com/wordpress/default-category.jpg';
	const FAKE_TITLE = 'Title category';
	public array $arrows_mapper = array(
		'on'  => 'yes',
		'off' => 'no',
		''    => 'no',
		'yes' => 'yes',
	);

	public array $show_product_count_mapper = array(
		'no'  => false,
		'yes' => true,
		'on'  => true,
		'off' => false,
	);

	/**
	 * Number of categories
	 *
	 * @var int
	 */
	private $total_count;


	/**
	 *
	 * @param $shortcode_params
	 *
	 * @return mixed
	 */
	public function get_categories( $shortcode_params ) {
		$query = $this->get_categories_query_builder( $shortcode_params );

		return $this->request_maker->do_categories_request( $query );
	}

	/**
	 * @param array $categories
	 * @param array $settings
	 *
	 * @return array
	 */
	public function format_data( array $categories, array $settings ): array {

		if ( ! empty( $categories ) ) {
			$categories_data = array();

			if ( ! empty( $categories ) ) {
				foreach ( $categories as $key => $category ) {
					$categories_data[ $key ]['id']      = $category['id'];
					$categories_data[ $key ]['name']    = $category['attributes']['name'];
					$categories_data[ $key ]['count']   = $category['attributes']['products-count'];
					$categories_data[ $key ]['img_url'] = $category['attributes']['image-url'];
				}
			}
		}

		return $categories_data ?? array();
	}

	/**
	 * @param int $columns
	 * @param int $rows
	 *
	 * @return float|int
	 */
	public function get_items_per_page( int $columns, int $rows ): int {
		return $columns * $rows;
	}

	/**
	 * @param array $options
	 *
	 * @return array
	 * @throws \Random\RandomException
	 */
	public function get_default_parameters( array $options ): array {
		$options['categories'] = $this->get_categories( $options );
		if ( isset( $options['categories']['data'] ) ) {
			$options['categories'] = $this->format_data( $options['categories']['data'], $options );
		} else {
			$options['categories'] = $this->getFakeData( self::COUNT_COLUMNS_CATEGORY );
		}

		$options['categories'] = $this->categories_preparation( $options['categories'] );
		$options['show_count'] = $options['show_product_count'];
		$options['attr']       = $options;

		return $options;
	}

	/**
	 * @param array $categories
	 *
	 * @return array
	 */
	private function categories_preparation( array $categories ): array {
		foreach ( $categories as $key => $category ) {
			$category_term                   = Prodigy_Product_Attributes::get_term_id_by_meta_key(
				Prodigy::PRODIGY_HOSTED_CATEGORY_RELATION,
				(int) $category['id']
			);
			$categories[ $key ]['local_url'] = get_category_link( $category_term->term_id ?? '' );
		}

		return $categories;
	}

	/**
	 * @param int $countCategory
	 *
	 * @return array
	 * @throws \Random\RandomException
	 */
	public function getFakeData( int $countCategory = 4 ): array {
		$categoriesData = array(
			'id'      => 0,
			'name'    => self::FAKE_TITLE,
			'count'   => random_int( 1, 10 ),
			'img_url' => self::FAKE_IMG_URL,
		);

		return array_fill( 0, $countCategory, $categoriesData );
	}

	/**
	 * @param array $params
	 *
	 * @return array
	 */
	public function get_categories_query_builder( array $params ): array {
		$attributes = array();

		$this->extract_ids_from_params( $params, $attributes );
		$this->extract_slugs_from_params( $params, $attributes );
		$this->handle_sorting( $params, $attributes );

		if ( isset( $params['show_product_count'] ) ) {
			$attributes['show_product_count'] = $params['show_product_count'];
		}

		if ( ! empty( $params ) && $params['display'] === self::WIDGET_DISPLAY_GRID_TYPE ) {
			$attributes['page']  = array(
				'size'   => (int) $params['limit'] > 0 ? (int) $params['limit'] : '',
				'number' => $params['pg'] ?? 1,
			);
			$attributes['limit'] = $params['items_per_page_number'] ?? null;
		}

		if ( ! Prodigy_Page::prodigy_is_frontend() ) {
			$attributes['admin'] = true;
		}

		return $attributes;
	}

	/**
	 * @param array $params
	 * @param array $attributes
	 *
	 * @return void
	 */
	private function extract_ids_from_params( array $params, array &$attributes ) {
		$parsed_ids = $this->parse_param_as_array( $params['parent_ids'] ?? '' );
		if ( ! empty( $parsed_ids ) ) {
			$attributes['parent_ids'] = $parsed_ids;
		}

		$parsed_ids = $this->parse_param_as_array( $params['category_ids'] ?? '' );
		if ( ! empty( $parsed_ids ) ) {
			$attributes['ids'] = $parsed_ids;
			$this->total_count = count( $parsed_ids );
		}
	}

	/**
	 * @param array $params
	 * @param array $attributes
	 *
	 * @return void
	 */
	private function extract_slugs_from_params( array $params, array &$attributes ) {
		$slugs = $this->parse_param_as_array( $params['category_slugs'] ?? '' );
		foreach ( $slugs as $key => $category_slug ) {
			$category = Prodigy_Taxonomies::get_taxonomy_by_different_slugs( Prodigy::get_prodigy_category_type(), $category_slug );
			if ( ! empty( $category->term_id ) ) {
				$remote_id                 = get_term_meta( (int) $category->term_id, Prodigy::PRODIGY_HOSTED_CATEGORY_RELATION, true );
				$attributes['ids'][ $key ] = $remote_id;
			}
		}
		$this->total_count = isset( $attributes['ids'] ) ? count( $attributes['ids'] ) : 0;
	}

	/**
	 * @param array $params
	 * @param array $attributes
	 *
	 * @return void
	 */
	private function handle_sorting( array $params, array &$attributes ) {
		if ( isset( $params['orderby'] ) ) {
			$sort = self::mapping_sort_params( $params['orderby'] );
			if ( isset( $params['order'] ) && strtolower( $params['order'] ) === strtolower( self::DESCENDING_SORT ) ) {
				$sort = '-' . $sort;
			}
			$attributes['sort'] = $sort;
		}
	}

	/**
	 * @param string $param
	 *
	 * @return array
	 */
	private function parse_param_as_array( string $param ): array {
		return array_filter( array_map( 'trim', explode( ',', $param ) ) );
	}
}
