<?php
/**
 * Variation Selector Widget - Render Methods
 *
 * Standalone functions called from GGM_Commerce_Widget_Variation_Selector.
 * All functions are prefixed ggmc_variation_selector_.
 *
 * @package GGM_Commerce
 */

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

/**
 * Render the premium widget content.
 *
 * @param GGM_Commerce_Widget_Variation_Selector $widget Widget instance.
 */
function ggmc_variation_selector_render_premium_content( $widget ) {
	$settings = $widget->get_settings_for_display();

	// Get product ID.
	$product_id = ggmc_variation_selector_get_product_id( $widget, $settings );

	if ( ! $product_id ) {
		ggmc_variation_selector_render_no_product_message();
		return;
	}

	// Get variations instance.
	$variations_manager = GGM_Commerce_Variations::instance();

	// Check if product has variations.
	if ( ! $variations_manager->product_has_variations( $product_id ) ) {
		// Show nothing if no variations.
		if ( ggmc_is_editor_mode() ) {
			echo '<div class="ggmc-variation-selector-notice">';
			esc_html_e( 'This product has no variations configured.', 'ggm-commerce' );
			echo '</div>';
		}
		return;
	}

	// Get variation mode first - it affects how we get config.
	$variation_mode = $variations_manager->get_product_variation_mode( $product_id );

	// Get product variation configuration (attributes used by this product).
	// For Independent mode, use the filtered config with enabled options and defaults.
	if ( 'independent' === $variation_mode ) {
		$config = $variations_manager->get_independent_mode_config( $product_id );
	} else {
		$config = $variations_manager->get_product_variation_config( $product_id );
	}

	if ( empty( $config ) ) {
		if ( ggmc_is_editor_mode() ) {
			echo '<div class="ggmc-variation-selector-notice">';
			esc_html_e( 'No variation attributes configured for this product.', 'ggm-commerce' );
			echo '</div>';
		}
		return;
	}

	// Get currency settings.
	$currency_options  = get_option( 'ggm_commerce_currency_options', array() );
	$currency_symbol   = isset( $currency_options['symbol'] ) ? $currency_options['symbol'] : '£';
	$currency_position = isset( $currency_options['position'] ) ? $currency_options['position'] : 'before';
	$base_price        = ggmc_variation_selector_get_product_base_price( $product_id );

	// For Independent mode: no pre-generated variations, build attribute options for JS.
	// For Combined mode: get variations and prepare data.
	if ( 'independent' === $variation_mode ) {
		$variations        = array(); // No pre-generated variations.
		$variation_data    = array();
		$default_variation = null;

		// Build attribute options data for JS price calculation.
		$attribute_options = array();
		foreach ( $config as $attr ) {
			$attr_id                        = (string) $attr['variation_type_id'];
			$attribute_options[ $attr_id ]  = array();
			if ( ! empty( $attr['options'] ) ) {
				foreach ( $attr['options'] as $opt ) {
					$attribute_options[ $attr_id ][] = array(
						'value'          => $opt['value'],
						'label'          => isset( $opt['label'] ) ? $opt['label'] : $opt['value'],
						'price_modifier' => isset( $opt['price_modifier'] ) ? (float) $opt['price_modifier'] : 0,
					);
				}
			}
		}
	} else {
		// Combined mode.
		$variations        = $variations_manager->get_variations( $product_id );
		$variation_data    = ggmc_variation_selector_prepare_variation_data( $variations, $product_id );
		$attribute_options = array(); // Not needed for combined mode.

		// Determine default variation.
		$default_variation = null;
		foreach ( $variations as $variation ) {
			if ( ! empty( $variation['is_default'] ) ) {
				$default_variation = $variation;
				break;
			}
		}
	}

	?>
	<div class="ggmc-variation-selector"
		data-product-id="<?php echo esc_attr( $product_id ); ?>"
		data-variations="<?php echo esc_attr( wp_json_encode( $variation_data ) ); ?>"
		data-hide-out-of-stock="<?php echo esc_attr( 'yes' === $settings['hide_out_of_stock'] ? '1' : '0' ); ?>"
		data-show-price-change="<?php echo esc_attr( 'yes' === $settings['show_price_change'] ? '1' : '0' ); ?>"
		data-currency-symbol="<?php echo esc_attr( $currency_symbol ); ?>"
		data-currency-position="<?php echo esc_attr( $currency_position ); ?>"
		data-variation-mode="<?php echo esc_attr( $variation_mode ); ?>"
		data-base-price="<?php echo esc_attr( $base_price ); ?>"
		data-attribute-options="<?php echo esc_attr( wp_json_encode( $attribute_options ) ); ?>">

		<?php foreach ( $config as $attribute ) : ?>
			<?php
			$display_type = ggmc_variation_selector_get_attribute_display_type( $attribute, $settings );
			// For Independent mode, default comes from per-product config; for Combined, from variation.
			if ( 'independent' === $variation_mode ) {
				$default_value = isset( $attribute['default_value'] ) ? $attribute['default_value'] : '';
			} else {
				$default_value = ggmc_variation_selector_get_default_attribute_value( $attribute, $default_variation );
			}
			?>
			<div class="ggmc-variation-attribute-row"
				data-attribute-id="<?php echo esc_attr( $attribute['variation_type_id'] ); ?>"
				data-attribute-slug="<?php echo esc_attr( $attribute['slug'] ); ?>">

				<?php if ( 'yes' === $settings['show_attribute_label'] ) : ?>
					<div class="ggmc-variation-attribute-header">
						<span class="ggmc-variation-attribute-label">
							<?php echo esc_html( $attribute['name'] ); ?>:
						</span>
						<?php if ( 'yes' === $settings['show_selected_value'] ) : ?>
							<span class="ggmc-variation-selected-value"
								data-default="<?php echo esc_attr( $default_value ); ?>">
								<?php echo esc_html( ggmc_variation_selector_get_option_label( $attribute, $default_value ) ); ?>
							</span>
						<?php endif; ?>
					</div>
				<?php endif; ?>

				<?php
				// Render the appropriate display type.
				switch ( $display_type ) {
					case 'select':
						ggmc_variation_selector_render_select( $attribute, $default_value, $settings );
						break;
					case 'color':
						ggmc_variation_selector_render_color_swatches( $attribute, $default_value, $settings );
						break;
					case 'image':
						ggmc_variation_selector_render_image_swatches( $attribute, $default_value, $settings );
						break;
					case 'button':
					default:
						ggmc_variation_selector_render_buttons( $attribute, $default_value, $settings );
						break;
				}
				?>
			</div>
		<?php endforeach; ?>

		<?php if ( 'yes' === $settings['show_price_change'] ) : ?>
			<div class="ggmc-variation-price-wrapper" style="display: none;">
				<span class="ggmc-variation-price"></span>
			</div>
		<?php endif; ?>

		<!-- Hidden inputs for form submission -->
		<input type="hidden" name="variation_id" class="ggmc-selected-variation-id" value="">
		<input type="hidden" name="variation_data" class="ggmc-selected-variation-data" value="">

		<?php if ( ! empty( $settings['clear_selection_text'] ) ) : ?>
			<button type="button" class="ggmc-variation-clear" style="display: none;">
				<?php echo esc_html( $settings['clear_selection_text'] ); ?>
			</button>
		<?php endif; ?>

	</div>
	<?php
}

/**
 * Get product ID from settings or URL.
 *
 * @param GGM_Commerce_Widget_Variation_Selector $widget   Widget instance.
 * @param array                                  $settings Widget settings.
 * @return int|false Product ID or false.
 */
function ggmc_variation_selector_get_product_id( $widget, $settings ) {
	// Check for explicit product ID in settings.
	if ( ! empty( $settings['product_id'] ) ) {
		return intval( $settings['product_id'] );
	}

	// Check for product in URL (product-details page).
	global $wp_query;
	if ( isset( $wp_query->query_vars['ggmc_product'] ) ) {
		$slug = sanitize_title( $wp_query->query_vars['ggmc_product'] );
		return ggmc_variation_selector_get_product_id_by_slug( $slug );
	}

	// Check for product_id in query string.
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended
	if ( isset( $_GET['product_id'] ) ) {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return intval( $_GET['product_id'] );
	}

	// Check for GGM Commerce Preview product (from page settings).
	// This uses the base widget's preview system.
	$preview_product = $widget->get_product_data();
	if ( $preview_product && ! empty( $preview_product->id ) ) {
		return intval( $preview_product->id );
	}

	// In editor mode with no preview product, try to get a sample product with variations.
	if ( ggmc_is_editor_mode() ) {
		return ggmc_variation_selector_get_sample_product_with_variations();
	}

	return false;
}

/**
 * Get product ID by slug.
 *
 * @param string $slug Product slug.
 * @return int|false Product ID or false.
 */
function ggmc_variation_selector_get_product_id_by_slug( $slug ) {
	global $wpdb;

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	return $wpdb->get_var(
		$wpdb->prepare(
			"SELECT id FROM {$wpdb->prefix}ggmc_products WHERE slug = %s AND status = 'published'",
			$slug
		)
	);
}

/**
 * Get a sample product with variations for editor preview.
 *
 * @return int|false Product ID or false.
 */
function ggmc_variation_selector_get_sample_product_with_variations() {
	global $wpdb;

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	return $wpdb->get_var(
		"SELECT id FROM {$wpdb->prefix}ggmc_products WHERE has_variations = 1 AND status = 'published' LIMIT 1"
	);
}

/**
 * Render no product message.
 */
function ggmc_variation_selector_render_no_product_message() {
	if ( ggmc_is_editor_mode() ) {
		echo '<div class="ggmc-variation-selector-notice">';
		esc_html_e( 'No product found. This widget needs to be placed on a product details page or have a Product ID specified.', 'ggm-commerce' );
		echo '</div>';
	}
}

/**
 * Prepare variation data for JavaScript.
 *
 * @param array $variations Product variations.
 * @param int   $product_id Product ID.
 * @return array Prepared variation data.
 */
function ggmc_variation_selector_prepare_variation_data( $variations, $product_id ) {
	$variations_manager = GGM_Commerce_Variations::instance();
	$data               = array();

	foreach ( $variations as $variation ) {
		// Build attribute key - use string keys for consistent JavaScript matching.
		$attr_key = array();
		foreach ( $variation['attributes'] as $attr ) {
			$attr_key[ (string) $attr['variation_type_id'] ] = (string) $attr['option_value'];
		}

		$price     = $variations_manager->get_variation_price( $variation['id'] );
		$available = $variations_manager->check_availability( $variation['id'] );

		$data[] = array(
			'id'           => $variation['id'],
			'attributes'   => $attr_key,
			'price'        => $price,
			'price_type'   => isset( $variation['price_type'] ) ? $variation['price_type'] : 'absolute',
			'stock_status' => $variation['stock_status'],
			'available'    => $available,
			'sku'          => $variation['sku'],
			'image_id'     => $variation['image_id'],
			'images'       => $variations_manager->get_variation_images( $variation['id'] ),
			'is_default'   => ! empty( $variation['is_default'] ),
		);
	}

	return $data;
}

/**
 * Get display type for attribute.
 *
 * @param array $attribute Attribute data.
 * @param array $settings  Widget settings.
 * @return string Display type.
 */
function ggmc_variation_selector_get_attribute_display_type( $attribute, $settings ) {
	if ( 'auto' !== $settings['default_display_type'] ) {
		// Map settings value to display type.
		$type_map = array(
			'select'   => 'select',
			'buttons'  => 'button',
			'swatches' => $attribute['input_type'], // Use input type for swatches.
		);
		return isset( $type_map[ $settings['default_display_type'] ] )
			? $type_map[ $settings['default_display_type'] ]
			: $attribute['input_type'];
	}

	return $attribute['input_type'];
}

/**
 * Get default value for an attribute.
 *
 * @param array      $attribute        Attribute data.
 * @param array|null $default_variation Default variation.
 * @return string Default value.
 */
function ggmc_variation_selector_get_default_attribute_value( $attribute, $default_variation ) {
	if ( $default_variation ) {
		foreach ( $default_variation['attributes'] as $attr ) {
			if ( (int) $attr['variation_type_id'] === (int) $attribute['variation_type_id'] ) {
				return $attr['option_value'];
			}
		}
	}

	// No default - let user choose (shows "Choose Color", "Choose Size" etc.)
	return '';
}

/**
 * Normalize options to ensure consistent format.
 * Options can be stored as simple strings ["Red", "Blue"] or objects [{"value": "red", "label": "Red"}].
 * This method converts both formats to [{value: "...", label: "...", color: "...", image: "..."}].
 *
 * @param array $options Raw options array.
 * @return array Normalized options with value, label, and optional color/image keys.
 */
function ggmc_variation_selector_normalize_options( $options ) {
	if ( empty( $options ) || ! is_array( $options ) ) {
		return array();
	}

	$normalized = array();
	foreach ( $options as $option ) {
		if ( is_array( $option ) && isset( $option['value'] ) ) {
			// Already in object format - preserve all properties.
			$normalized_option = array(
				'value' => $option['value'],
				'label' => isset( $option['label'] ) ? $option['label'] : $option['value'],
			);
			// Preserve color property for color swatches.
			if ( isset( $option['color'] ) ) {
				$normalized_option['color'] = $option['color'];
			}
			// Preserve image property for image swatches.
			if ( isset( $option['image'] ) ) {
				$normalized_option['image'] = $option['image'];
			}
			// Preserve price_modifier for independent mode.
			if ( isset( $option['price_modifier'] ) ) {
				$normalized_option['price_modifier'] = $option['price_modifier'];
			}
			$normalized[] = $normalized_option;
		} elseif ( is_string( $option ) ) {
			// Simple string format - use same value for both.
			$normalized[] = array(
				'value' => $option,
				'label' => $option,
			);
		}
	}

	return $normalized;
}

/**
 * Get option label from value.
 *
 * @param array  $attribute Attribute data.
 * @param string $value     Option value.
 * @return string Option label.
 */
function ggmc_variation_selector_get_option_label( $attribute, $value ) {
	if ( empty( $attribute['options'] ) ) {
		return $value;
	}

	$options = ggmc_variation_selector_normalize_options( $attribute['options'] );
	foreach ( $options as $option ) {
		if ( $option['value'] === $value ) {
			return $option['label'];
		}
	}

	return $value;
}

/**
 * Render select dropdown.
 *
 * @param array  $attribute     Attribute data.
 * @param string $default_value Default value.
 * @param array  $settings      Widget settings.
 */
function ggmc_variation_selector_render_select( $attribute, $default_value, $settings ) {
	$options = ggmc_variation_selector_normalize_options( $attribute['options'] );
	?>
	<select class="ggmc-variation-select"
		data-attribute-id="<?php echo esc_attr( $attribute['variation_type_id'] ); ?>">
		<?php // translators: %s: attribute name (e.g., Color, Size). ?>
		<option value=""><?php echo esc_html( sprintf( __( 'Choose %s', 'ggm-commerce' ), $attribute['name'] ) ); ?></option>
		<?php foreach ( $options as $option ) : ?>
			<option value="<?php echo esc_attr( $option['value'] ); ?>"
				<?php selected( $option['value'], $default_value ); ?>>
				<?php echo esc_html( $option['label'] ); ?>
			</option>
		<?php endforeach; ?>
	</select>
	<?php
}

/**
 * Render button options.
 *
 * @param array  $attribute     Attribute data.
 * @param string $default_value Default value.
 * @param array  $settings      Widget settings.
 */
function ggmc_variation_selector_render_buttons( $attribute, $default_value, $settings ) {
	$options      = ggmc_variation_selector_normalize_options( $attribute['options'] );
	$layout_class = 'grid' === $settings['button_layout'] ? 'layout-grid' : 'layout-inline';
	?>
	<div class="ggmc-variation-options <?php echo esc_attr( $layout_class ); ?>"
		data-attribute-id="<?php echo esc_attr( $attribute['variation_type_id'] ); ?>">
		<?php foreach ( $options as $option ) : ?>
			<button type="button"
				class="ggmc-variation-button<?php echo $option['value'] === $default_value ? ' selected' : ''; ?>"
				data-value="<?php echo esc_attr( $option['value'] ); ?>">
				<?php echo esc_html( $option['label'] ); ?>
			</button>
		<?php endforeach; ?>
	</div>
	<?php
}

/**
 * Render color swatches.
 *
 * @param array  $attribute     Attribute data.
 * @param string $default_value Default value.
 * @param array  $settings      Widget settings.
 */
function ggmc_variation_selector_render_color_swatches( $attribute, $default_value, $settings ) {
	$options      = ggmc_variation_selector_normalize_options( $attribute['options'] );
	$layout_class = 'grid' === $settings['button_layout'] ? 'layout-grid' : 'layout-inline';
	?>
	<div class="ggmc-variation-options ggmc-variation-swatches <?php echo esc_attr( $layout_class ); ?>"
		data-attribute-id="<?php echo esc_attr( $attribute['variation_type_id'] ); ?>">
		<?php foreach ( $options as $option ) : ?>
			<?php
			$color = isset( $option['color'] ) ? $option['color'] : '#cccccc';
			?>
			<button type="button"
				class="ggmc-variation-swatch ggmc-variation-color-swatch<?php echo $option['value'] === $default_value ? ' selected' : ''; ?>"
				data-value="<?php echo esc_attr( $option['value'] ); ?>"
				title="<?php echo esc_attr( $option['label'] ); ?>"
				style="background-color: <?php echo esc_attr( $color ); ?>">
				<span class="screen-reader-text"><?php echo esc_html( $option['label'] ); ?></span>
			</button>
		<?php endforeach; ?>
	</div>
	<?php
}

/**
 * Render image swatches.
 *
 * @param array  $attribute     Attribute data.
 * @param string $default_value Default value.
 * @param array  $settings      Widget settings.
 */
function ggmc_variation_selector_render_image_swatches( $attribute, $default_value, $settings ) {
	$options      = ggmc_variation_selector_normalize_options( $attribute['options'] );
	$layout_class = 'grid' === $settings['button_layout'] ? 'layout-grid' : 'layout-inline';
	?>
	<div class="ggmc-variation-options ggmc-variation-swatches <?php echo esc_attr( $layout_class ); ?>"
		data-attribute-id="<?php echo esc_attr( $attribute['variation_type_id'] ); ?>">
		<?php foreach ( $options as $option ) : ?>
			<?php
			$image_id  = isset( $option['image'] ) ? intval( $option['image'] ) : 0;
			$image_url = $image_id ? wp_get_attachment_image_url( $image_id, 'thumbnail' ) : '';
			?>
			<button type="button"
				class="ggmc-variation-swatch ggmc-variation-image-swatch<?php echo $option['value'] === $default_value ? ' selected' : ''; ?>"
				data-value="<?php echo esc_attr( $option['value'] ); ?>"
				title="<?php echo esc_attr( $option['label'] ); ?>">
				<?php if ( $image_url ) : ?>
					<img src="<?php echo esc_url( $image_url ); ?>" alt="<?php echo esc_attr( $option['label'] ); ?>">
				<?php else : ?>
					<span class="ggmc-swatch-label"><?php echo esc_html( $option['label'] ); ?></span>
				<?php endif; ?>
			</button>
		<?php endforeach; ?>
	</div>
	<?php
}

/**
 * Get base price for a product.
 *
 * @param int $product_id Product ID.
 * @return float Base price.
 */
function ggmc_variation_selector_get_product_base_price( $product_id ) {
	global $wpdb;

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	$product = $wpdb->get_row(
		$wpdb->prepare(
			"SELECT price, sale_price FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
			$product_id
		),
		ARRAY_A
	);

	if ( ! $product ) {
		return 0;
	}

	// Use sale price if available, otherwise regular price.
	if ( ! empty( $product['sale_price'] ) && floatval( $product['sale_price'] ) > 0 ) {
		return floatval( $product['sale_price'] );
	}

	return ! empty( $product['price'] ) ? floatval( $product['price'] ) : 0;
}
