<?php
/**
 * Prepare localized payloads for the admin and frontend bundles.
 *
 * @package B3WVS\VariationSwatches\Assets
 */

namespace B3WVS\VariationSwatches\Assets;

defined( 'ABSPATH' ) || exit;

/**
 * Class Localizer
 */
class Localizer {

	/**
	 * Collect aggregated swatch usage statistics for admin onboarding UI.
	 *
	 * @return array<string,mixed>
	 */
	private function get_usage_stats() {
		$empty = array(
			'terms_total'                     => 0,
			'attribute_taxonomies_configured' => 0,
			'products_with_overrides'         => 0,
			'by_type'                         => array(
				'color'  => 0,
				'button' => 0,
			),
		);

		if ( ! function_exists( 'wc_get_products' ) ) {
			return $empty;
		}

		$cached = get_transient( 'b3_wvs_usage_stats_v1' );
		if ( is_array( $cached ) ) {
			return array_replace_recursive( $empty, $cached );
		}

		if ( ! function_exists( 'wc_get_products' ) ) {
			set_transient( 'b3_wvs_usage_stats_v1', $empty, MINUTE_IN_SECONDS * 5 );
			return $empty;
		}

		$used_taxonomies = array();
		$term_type_cache = array();
		$product_ids     = wc_get_products(
			array(
				'limit'  => -1,
				'return' => 'ids',
				'type'   => 'variable',
				'status' => array( 'publish', 'private', 'draft', 'pending', 'future' ),
			)
		);

		if ( ! is_array( $product_ids ) ) {
			$product_ids = array();
		}

		foreach ( $product_ids as $product_id ) {
			$product_id = absint( $product_id );
			if ( ! $product_id ) {
				continue;
			}

			$product = wc_get_product( $product_id );
			if ( ! $product || ! method_exists( $product, 'get_attributes' ) || ! $product->is_type( 'variable' ) ) {
				continue;
			}

			$attributes = $product->get_attributes();
			if ( ! is_array( $attributes ) || empty( $attributes ) ) {
				continue;
			}

			$overrides = get_post_meta( $product_id, '_b3_wvs_overrides', true );
			if ( ! is_array( $overrides ) ) {
				$overrides = array();
			}

			foreach ( $attributes as $attribute ) {
				if ( ! is_object( $attribute ) || ! method_exists( $attribute, 'get_variation' ) || ! $attribute->get_variation() ) {
					continue;
				}

				$attribute_name = method_exists( $attribute, 'get_name' ) ? (string) $attribute->get_name() : '';
				$options        = method_exists( $attribute, 'get_options' ) ? $attribute->get_options() : array();

				if ( '' === $attribute_name || ! is_array( $options ) || empty( $options ) ) {
					continue;
				}

				if ( method_exists( $attribute, 'is_taxonomy' ) && $attribute->is_taxonomy() && taxonomy_exists( $attribute_name ) ) {
					foreach ( $options as $term_id ) {
						$type = $this->get_term_usage_type( absint( $term_id ), $term_type_cache );
						if ( '' === $type || ! isset( $empty['by_type'][ $type ] ) ) {
							continue;
						}

						++$empty['by_type'][ $type ];
						$used_taxonomies[ sanitize_key( $attribute_name ) ] = true;
					}

					continue;
				}

				foreach ( $options as $option ) {
					$option_key = (string) $option;
					$override   = isset( $overrides[ $attribute_name ][ $option_key ] ) && is_array( $overrides[ $attribute_name ][ $option_key ] )
						? $overrides[ $attribute_name ][ $option_key ]
						: array();

					$type = $this->get_override_usage_type( $override );
					if ( '' === $type || ! isset( $empty['by_type'][ $type ] ) ) {
						continue;
					}

					++$empty['by_type'][ $type ];
				}
			}
		}

		$empty['terms_total']                     = array_sum( $empty['by_type'] );
		$empty['attribute_taxonomies_configured'] = count( $used_taxonomies );

		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregated stats are cached in b3_wvs_usage_stats_v1 transient.
		$overrides_count                  = $wpdb->get_var(
			$wpdb->prepare(
				"
				SELECT COUNT(DISTINCT p.ID)
				FROM {$wpdb->postmeta} pm
				INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
				WHERE pm.meta_key = %s
					AND pm.meta_value <> ''
					AND pm.meta_value <> 'a:0:{}'
					AND p.post_type = 'product'
					AND p.post_status NOT IN ('auto-draft', 'trash')
				",
				'_b3_wvs_overrides'
			)
		);
		$empty['products_with_overrides'] = absint( $overrides_count );

		$empty = apply_filters( 'b3wvs_usage_stats_payload', $empty );

		set_transient( 'b3_wvs_usage_stats_v1', $empty, MINUTE_IN_SECONDS * 5 );
		return $empty;
	}

	/**
	 * Resolve the effective swatch type for a taxonomy term as rendered on the frontend.
	 *
	 * @param int   $term_id         Term ID.
	 * @param array $term_type_cache Runtime cache keyed by term ID.
	 * @return string
	 */
	private function get_term_usage_type( $term_id, &$term_type_cache ) {
		if ( $term_id <= 0 ) {
			return '';
		}

		if ( isset( $term_type_cache[ $term_id ] ) ) {
			return $term_type_cache[ $term_id ];
		}

		$term = get_term( $term_id );
		if ( ! $term || is_wp_error( $term ) ) {
			$term_type_cache[ $term_id ] = '';
			return '';
		}

		$type = $this->normalize_shared_usage_type(
			array(
				'type'  => (string) get_term_meta( $term_id, 'b3_wvs_type', true ),
				'color' => (string) get_term_meta( $term_id, 'b3_wvs_color', true ),
			)
		);

		$term_type_cache[ $term_id ] = $type;
		return $type;
	}

	/**
	 * Resolve the effective swatch type for a custom-attribute override payload.
	 *
	 * @param array $override Override payload.
	 * @return string
	 */
	private function get_override_usage_type( $override ) {
		if ( ! is_array( $override ) || empty( $override ) ) {
			return '';
		}

		$raw = array(
			'type'       => isset( $override['type'] ) ? (string) $override['type'] : '',
			'color'      => isset( $override['color'] ) ? (string) $override['color'] : '',
			'hide_label' => ! empty( $override['hide_label'] ),
		);

		return $this->normalize_shared_usage_type( $raw );
	}

	/**
	 * Normalize only the shared swatch types without invoking extension logic.
	 *
	 * @param array $raw Raw shared swatch payload.
	 * @return string
	 */
	private function normalize_shared_usage_type( $raw ) {
		$type      = isset( $raw['type'] ) ? sanitize_key( (string) $raw['type'] ) : '';
		$has_color = '' !== trim( isset( $raw['color'] ) ? (string) $raw['color'] : '' );

		if ( ! in_array( $type, array( '', 'button', 'color' ), true ) ) {
			return '';
		}

		if ( '' === $type && $has_color ) {
			return 'color';
		}

		if ( 'color' === $type && ! $has_color ) {
			return 'button';
		}

		return $type;
	}
	/**
	 * Localize data for JS.
	 *
	 * @param string $handle Asset handle (frontend/admin).
	 */
	public function localize_data( $handle ) {
		$is_admin_context   = 0 === strpos( (string) $handle, 'admin' );
		$effective_settings = \b3wvs_get_effective_settings();
		$form_settings      = $effective_settings;
		$preview_settings   = $effective_settings;

		global $_wp_admin_css_colors;
		$current_color_scheme = get_user_option( 'admin_color' );
		$admin_color          = '#46a5e5';

		if ( ! empty( $_wp_admin_css_colors ) && isset( $_wp_admin_css_colors[ $current_color_scheme ] ) ) {
			$colors      = $_wp_admin_css_colors[ $current_color_scheme ]->colors;
			$admin_color = ! empty( $colors[2] ) ? $colors[2] : ( ! empty( $colors[0] ) ? $colors[0] : $admin_color );
		}

		$data = array(
			'ajax_url'            => admin_url( 'admin-ajax.php' ),
			'nonce'               => wp_create_nonce( 'wp_rest' ),
			'refresh_panel_nonce' => wp_create_nonce( 'b3wvs_refresh_panel' ),
			'rest_url'            => esc_url_raw( rest_url( 'b3-wvs/v1' ) ),
			'admin_urls'          => array(
				'getting_started' => admin_url( 'admin.php?page=b3-swatches-settings' ),
				'settings'        => admin_url( 'admin.php?page=b3-swatches-settings' ),
				'attributes'      => admin_url( 'edit.php?post_type=product&page=product_attributes' ),
				'products'        => admin_url( 'edit.php?post_type=product' ),
			),
			'settings'            => $form_settings,
			'previewSettings'     => $preview_settings, // Effective settings for live preview.
			'admin_color'         => $admin_color,
			'usage_stats'         => $is_admin_context ? $this->get_usage_stats() : array(),
		);

		$data = apply_filters( 'b3wvs_localized_payload', $data, $effective_settings, $is_admin_context );

		wp_localize_script( 'b3-wvs-' . $handle . ( ( defined( 'B3_WVS_DEV' ) && B3_WVS_DEV ) ? '-dev' : '' ), 'b3WvsData', $data );
	}
}
