<?php
/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
 *
 * This source code is licensed under the license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @package MetaCommerce
 */

namespace WooCommerce\Facebook\Admin;

defined( 'ABSPATH' ) || exit;

use WooCommerce\Facebook\Products as Products_Handler;

/**
 * Enhanced Catalog attribute fields.
 */
class Enhanced_Catalog_Attribute_Fields {
	const FIELD_ENHANCED_CATALOG_ATTRIBUTE_PREFIX = 'wc_facebook_enhanced_catalog_attribute_';
	const OPTIONAL_SELECTOR_KEY                   = '__optional_selector';
	const FIELD_ENHANCED_CATALOG_ATTRIBUTES_ID    = 'wc_facebook_enhanced_catalog_attributes_id';
	const FIELD_CAN_SHOW_ENHANCED_ATTRIBUTES_ID   = 'wc_facebook_can_show_enhanced_catalog_attributes_id';

	const PAGE_TYPE_EDIT_CATEGORY = 'edit_category';
	const PAGE_TYPE_ADD_CATEGORY  = 'add_category';
	const PAGE_TYPE_EDIT_PRODUCT  = 'edit_product';

	/**
	 * @var string Facebook page type.
	 */
	private $page_type;

	/**
	 * @var \WP_Term
	 */
	private $term;

	/**
	 * @var \WC_Product
	 */
	private $product;

	/**
	 * @var \WooCommerce\Facebook\Products\FBCategories
	 */
	private $category_handler;

	public function __construct( $page_type, ?\WP_Term $term = null, ?\WC_Product $product = null ) {
		$this->page_type        = $page_type;
		$this->term             = $term;
		$this->product          = $product;
		$this->category_handler = facebook_for_woocommerce()->get_facebook_category_handler();
	}

	/**
	 * __get method for backward compatibility.
	 *
	 * @param string $key property name
	 * @return mixed
	 * @since 3.0.32
	 */
	public function __get( $key ) {
		// Add warning for private properties.
		if ( in_array( $key, array( 'page_type', 'term', 'product', 'category_handler' ), true ) ) {
			/* translators: %s property name. */
			_doing_it_wrong( __FUNCTION__, sprintf( esc_html__( 'The %s property is private and should not be accessed outside its class.', 'facebook-for-woocommerce' ), esc_html( $key ) ), '3.0.32' );
			return $this->$key;
		}

		return null;
	}

	public static function render_hidden_input_can_show_attributes() {
		?>
		<input type="hidden" id="<?php echo esc_attr( self::FIELD_CAN_SHOW_ENHANCED_ATTRIBUTES_ID ); ?>"
			name="<?php echo esc_attr( self::FIELD_CAN_SHOW_ENHANCED_ATTRIBUTES_ID ); ?>"
			value="true"/>
		<?php
	}

	private function extract_attribute( &$attributes, $key ) {
		$index     = array_search( $key, array_column( $attributes, 'key' ), true );
		$extracted = false === $index ? array() : array_splice( $attributes, $index, 1 );
		return empty( $extracted ) ? null : array_shift( $extracted );
	}
	public function render( $category_id ) {
		$all_attributes = (array) $this->category_handler->get_attributes_with_fallback_to_parent_category( $category_id );

		$all_attributes_with_values = array_map(
			function ( $attribute ) use ( $category_id ) {
				return array_merge( $attribute, array( 'value' => $this->get_value( $attribute['key'], $category_id ) ) );
			},
			$all_attributes
		);

		$recommended_attributes = array_filter(
			$all_attributes_with_values,
			function ( $attr ) {
				return $attr['recommended'];
			}
		);
		$optional_attributes    = array_filter(
			$all_attributes_with_values,
			function ( $attr ) {
				return ! $attr['recommended'];
			}
		);

		// Some google mappings don't have any recommendations
		// to avoid there being no attributes to see we extract color, gender
		// and size from optional.
		if ( empty( $recommended_attributes ) ) {
			$recommended_attributes = array_filter(
				array(
					$this->extract_attribute( $optional_attributes, 'color' ),
					$this->extract_attribute( $optional_attributes, 'size' ),
					$this->extract_attribute( $optional_attributes, 'gender' ),
				),
				function ( $attr ) {
					return ! is_null( $attr );
				}
			);
		}

		/**
		 * Attributes should be ordered by priority in this order: Length, Width, Height, Depth, Other measurement attributes, others.
		 */
		$priorities = array(
			'product_length' => 140,
			'product_width'  => 130,
			'product_height' => 120,
			'product_depth'  => 110,
			'default'        => 100,
		);

		$priority = array(); // Initialize priority array.
		foreach ( $recommended_attributes as $key => $attribute ) {
			$recommended_attributes[ $key ]['priority'] = 5; // Assign 5 initially to each attribute
			if ( 'measurement' === $attribute['type'] ) {
				$recommended_attributes[ $key ]['priority'] = isset( $priorities[ $attribute['key'] ] ) ? $priorities[ $attribute['key'] ] : $priorities['default'];
			}
			$priority[ $key ] = $recommended_attributes[ $key ]['priority'];
		}

		$should_render_checkbox = ! empty( $recommended_attributes );

		// Only sort if we have recommended attributes.
		if ( ! empty( $priority ) ) {
			array_multisort( $priority, SORT_DESC, $recommended_attributes );
		}
		$selector_value      = $this->get_value( self::OPTIONAL_SELECTOR_KEY, $category_id );
		$is_showing_optional = 'on' === $selector_value;

		// Only show the selector if we have natural recommendations
		if ( $should_render_checkbox ) {
			$this->render_selector_checkbox( $is_showing_optional );
		}

		foreach ( $recommended_attributes as $attribute ) {
			$this->render_attribute( $attribute, true, $is_showing_optional );
		}

		foreach ( $optional_attributes as $attribute ) {
			$this->render_attribute( $attribute, true, $is_showing_optional );
		}
	}

	private function render_selector_checkbox( $is_showing_optional ) {
		$selector_id    = self::FIELD_ENHANCED_CATALOG_ATTRIBUTE_PREFIX . self::OPTIONAL_SELECTOR_KEY;
		$selector_label = __( 'Show more attributes', 'facebook-for-woocommerce' );
		$checked_attr   = $is_showing_optional ? 'checked="checked"' : '';

		if ( self::PAGE_TYPE_EDIT_PRODUCT === $this->page_type ) {
			?>
			<p class="form-field wc-facebook-enhanced-catalog-attribute-row term-<?php echo esc_attr( $selector_id ); ?>-wrap">
				<label for="<?php echo esc_attr( $selector_id ); ?>">
					<?php echo esc_html( $selector_label ); ?>
				</label>
				<input type="checkbox" name="<?php echo esc_attr( $selector_id ); ?>" id="<?php echo esc_attr( $selector_id ); ?>" <?php echo esc_attr( $checked_attr ); ?>/>
			</p>
			<?php
		} else {
			?>
			<tr class="form-field wc-facebook-enhanced-catalog-attribute-row term-<?php echo esc_attr( $selector_id ); ?>-wrap">
				<th colspan="2" scope="row">
					<label for="<?php echo esc_attr( $selector_id ); ?>">
						<?php echo esc_html( $selector_label ); ?>
						<input type="checkbox" name="<?php echo esc_attr( $selector_id ); ?>" id="<?php echo esc_attr( $selector_id ); ?>" <?php echo esc_attr( $checked_attr ); ?>/>
					</label>
				</th>
			</tr>
			<?php
		}//end if
	}

	private function get_value( $attribute_key, $category_id ) {
		$value = null;
		if ( ! is_null( $this->product ) ) {
			$value = Products_Handler::get_enhanced_catalog_attribute( $attribute_key, $this->product );
		} elseif ( ! is_null( $this->term ) ) {
			$meta_key = \WooCommerce\Facebook\Products::ENHANCED_CATALOG_ATTRIBUTES_META_KEY_PREFIX . $attribute_key;
			$value    = get_term_meta( $this->term->term_id, $meta_key, true );
		}

		// Check if it's valid
		if ( self::OPTIONAL_SELECTOR_KEY !== $attribute_key && ! empty( $value ) ) {
			$is_valid = $this->category_handler->is_valid_value_for_attribute( $category_id, $attribute_key, $value );
			$value    = $is_valid ? $value : null;
		}
		return $value;
	}

	private function render_attribute( $attribute, $optional = false, $is_showing_optional = false ) {
		$attr_id = self::FIELD_ENHANCED_CATALOG_ATTRIBUTE_PREFIX . $attribute['key'];
		$classes = array(
			'form-field',
			'wc-facebook-enhanced-catalog-attribute-row',
			'term-' . esc_attr( $attr_id ) . '-wrap',
		);
		if ( $optional ) {
			$classes[] = 'wc-facebook-enhanced-catalog-attribute-optional-row';
			if ( ! $is_showing_optional ) {
				$classes[] = 'hidden';
			}
		}

		if ( self::PAGE_TYPE_EDIT_PRODUCT === $this->page_type ) {
			?>
			<p
				class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
				<?php $this->render_label( $attr_id, $attribute ); ?>
				<?php $this->render_field( $attr_id, $attribute ); ?>
			</p>
			<?php
		} else {
			?>
			<tr
				class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
				<th scope="row">
					<?php $this->render_label( $attr_id, $attribute ); ?>
				</th>
				<td>
					<?php $this->render_field( $attr_id, $attribute ); ?>
				</td>
			</tr>
			<?php
		}//end if
	}

	private function render_label( $attr_id, $attribute ) {
		$label = ucwords( str_replace( '_', ' ', $attribute['key'] ) );
		?>
		<label for="<?php echo esc_attr( $attr_id ); ?>">
			<?php echo esc_html( $label ); ?>
			<span class="woocommerce-help-tip" data-tip="<?php echo esc_attr( $attribute['description'] ); ?>"></span>
		</label>
		<?php
	}

	private function render_field( $attr_id, $attribute ) {
		$placeholder              = isset( $attribute['example'] ) ? $attribute['example'] : '';
		$can_have_multiple_values = isset( $attribute['can_have_multiple_values'] ) && $attribute['can_have_multiple_values'];
		switch ( $attribute['type'] ) {
			case 'boolean':
			case 'enum':
				if ( $can_have_multiple_values ) {
					$this->render_text_field( $attr_id, $attribute, $placeholder );
				} else {
					$this->render_select_field( $attr_id, $attribute );
				}
				break;

			default:
				// string
				$this->render_text_field( $attr_id, $attribute, $placeholder );
		}
	}

	private function render_select_field( $attr_id, $attribute ) {
		?>
		<select name="<?php echo esc_attr( $attr_id ); ?>" id="<?php echo esc_attr( $attr_id ); ?>">
			<option value="">--</option>
			<?php
			foreach ( $attribute['enum_values'] as $opt ) {
				$is_selected   = $attribute['value'] === $opt;
				$selected_attr = $is_selected ? 'selected="selected"' : '';
				?>
				<option value="<?php echo esc_attr( $opt ); ?>" <?php echo esc_attr( $selected_attr ); ?>> <?php echo esc_html( $opt ); ?></option>
			<?php } ?>
		</select/>
		<?php
	}

	private function render_text_field( $attr_id, $attribute, $placeholder ) {
		if ( is_array( $placeholder ) ) {
			$placeholder = implode( ', ', $placeholder );
		}
		?>
		<input type="text" value="<?php echo esc_attr( $attribute['value'] ); ?>" name="<?php echo esc_attr( $attr_id ); ?>" id="<?php echo esc_attr( $attr_id ); ?>" placeholder="<?php echo esc_attr( $placeholder ); ?>"/>
		<?php
	}
}
