<?php

namespace CelerSearch\Integrations\WooCommerce;

defined( 'ABSPATH' ) || exit;

use CelerSearch\Factories\IndexFactory;
use CelerSearch\Interfaces\IRegistrable;
use CelerSearch\Repositories\IndexRepository;

/**
 * Renders the shop filter UI and enqueues assets on WooCommerce shop pages
 */
class ShopFilters implements IRegistrable {

	const SCRIPT_HANDLE = 'celersearch-shop-filters';
	const STYLE_HANDLE  = 'celersearch-shop-filters';

	/**
	 * Register hooks
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'woocommerce_before_shop_loop', [ $this, 'render_filter_bar' ], 15 );
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] );
	}

	/**
	 * Enqueue JS and CSS on WooCommerce shop pages
	 *
	 * @return void
	 */
	public function enqueue_assets(): void {
		if ( ! $this->is_shop_page() ) {
			return;
		}

		$index_id = $this->get_shop_index_id();
		if ( empty( $index_id ) ) {
			return;
		}

		// Add body class to hide WooCommerce default ordering
		add_filter( 'body_class', function ( $classes ) {
			$classes[] = 'celersearch-shop-filters-active';
			return $classes;
		} );

		wp_enqueue_style(
			self::STYLE_HANDLE,
			CELERSEARCH_PLUGIN_URL . 'assets/frontend/integrations/woocommerce.css',
			[],
			CELERSEARCH_PLUGIN_VERSION
		);

		wp_enqueue_script(
			self::SCRIPT_HANDLE,
			CELERSEARCH_PLUGIN_URL . 'assets/frontend/integrations/woocommerce.js',
			[],
			CELERSEARCH_PLUGIN_VERSION,
			true
		);

		wp_localize_script(
			self::SCRIPT_HANDLE,
			'celerSearchShopFilters',
			$this->get_script_config( $index_id )
		);
	}

	/**
	 * Render filter bar HTML above the product loop
	 *
	 * @return void
	 */
	public function render_filter_bar(): void {
		if ( ! $this->is_shop_page() ) {
			return;
		}

		$index_id = $this->get_shop_index_id();
		if ( empty( $index_id ) ) {
			return;
		}

		// Get initial facet data via a MeiliSearch query
		$initial_data = $this->get_initial_facet_data( $index_id );
		$facets       = $initial_data['facets'] ?? [];
		$price_range  = $initial_data['price_range'] ?? [ 'min' => 0, 'max' => 0 ];

		// Get available attribute filters from index
		$attribute_filters = $this->get_attribute_filters( $index_id );

		$style = $this->get_filter_style();

		// Unified toolbar for both styles
		echo '<div class="cs-filters-toolbar">';

		// Sort dropdown (left)
		$this->render_sort_dropdown();

		// Search input (if enabled)
		if ( $this->is_search_enabled() ) {
			$placeholder = __( 'Search products...', 'celersearch' );
			if ( is_product_category() ) {
				$term = get_queried_object();
				if ( $term ) {
					$placeholder = sprintf( __( 'Search in %s...', 'celersearch' ), $term->name );
				}
			} elseif ( is_product_tag() ) {
				$term = get_queried_object();
				if ( $term ) {
					$placeholder = sprintf( __( 'Search in %s...', 'celersearch' ), $term->name );
				}
			}
			printf(
				'<input type="search" class="cs-search-input" placeholder="%s" aria-label="%s">',
				esc_attr( $placeholder ),
				esc_attr__( 'Search products', 'celersearch' )
			);
		}

		// Filters toggle button (right)
		$controls_id = $style === 'drawer' ? 'celersearch-drawer' : 'celersearch-collapsible';
		printf(
			'<button type="button" class="cs-filters-toggle" aria-expanded="false" aria-controls="%s">
				<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="14" y2="12"/><line x1="4" y1="18" x2="10" y2="18"/></svg>
				%s
			</button>',
			esc_attr( $controls_id ),
			esc_html__( 'Filters', 'celersearch' )
		);

		// Active pills
		echo '<div class="cs-active-filters"></div>';
		echo '</div>';

		// Drawer style: backdrop + drawer panel
		if ( $style === 'drawer' ) {
			echo '<div class="cs-drawer-backdrop" aria-hidden="true"></div>';
			echo '<div id="celersearch-drawer" class="cs-drawer" aria-hidden="true">';
			printf(
				'<div class="cs-drawer__header">
					<h3>%s</h3>
					<button type="button" class="cs-drawer__close" aria-label="%s">&times;</button>
				</div>',
				esc_html__( 'Filters', 'celersearch' ),
				esc_attr__( 'Close filters', 'celersearch' )
			);
			echo '<div class="cs-drawer__body">';
		}

		// Inline style: collapsible panel
		if ( $style === 'inline' ) {
			echo '<div id="celersearch-collapsible" class="cs-filters-collapsible">';
		}

		echo '<div id="celersearch-shop-filters" class="cs-shop-filters' . ( $style === 'drawer' ? ' cs-shop-filters--drawer' : '' ) . '">';

		// Price filter
		if ( $price_range['max'] > 0 ) {
			$currency = function_exists( 'get_woocommerce_currency_symbol' )
				? html_entity_decode( get_woocommerce_currency_symbol() )
				: '$';
			printf(
				'<div class="cs-filter cs-filter--price" data-filter="price">
					<h4 class="cs-filter__heading">%s</h4>
					<div class="cs-price-range">
						<input type="number" class="cs-price-min" min="%s" max="%s" value="%s" step="1" aria-label="%s">
						<span class="cs-price-separator">&mdash;</span>
						<input type="number" class="cs-price-max" min="%s" max="%s" value="%s" step="1" aria-label="%s">
						<span class="cs-price-currency">%s</span>
					</div>
				</div>',
				esc_html__( 'Price', 'celersearch' ),
				esc_attr( floor( $price_range['min'] ) ),
				esc_attr( ceil( $price_range['max'] ) ),
				esc_attr( floor( $price_range['min'] ) ),
				esc_attr__( 'Minimum price', 'celersearch' ),
				esc_attr( floor( $price_range['min'] ) ),
				esc_attr( ceil( $price_range['max'] ) ),
				esc_attr( ceil( $price_range['max'] ) ),
				esc_attr__( 'Maximum price', 'celersearch' ),
				esc_html( $currency )
			);
		}

		// Category filter
		if ( ! empty( $facets['taxonomies.product_cat'] ) ) {
			$this->render_checkbox_filter(
				'taxonomies.product_cat',
				__( 'Category', 'celersearch' ),
				$facets['taxonomies.product_cat']
			);
		}

		// Stock filter
		if ( isset( $facets['in_stock'] ) ) {
			printf(
				'<div class="cs-filter cs-filter--stock" data-filter="in_stock">
					<h4 class="cs-filter__heading">%s</h4>
					<label class="cs-filter__checkbox">
						<input type="checkbox" value="true"> %s
					</label>
				</div>',
				esc_html__( 'Availability', 'celersearch' ),
				esc_html__( 'In stock only', 'celersearch' )
			);
		}

		// Rating filter
		if ( ! empty( $facets['ratings.average_rating'] ) ) {
			$this->render_rating_filter( $facets['ratings.average_rating'] );
		}

		// Attribute filters (pa_color, pa_size, etc.)
		foreach ( $attribute_filters as $attr_key => $attr_label ) {
			$facet_key = 'taxonomies.' . $attr_key;
			if ( ! empty( $facets[ $facet_key ] ) ) {
				$this->render_checkbox_filter( $facet_key, $attr_label, $facets[ $facet_key ] );
			}
		}

		echo '</div>';

		// Close style-specific wrappers
		if ( $style === 'drawer' ) {
			echo '</div>'; // .cs-drawer__body
			printf(
				'<div class="cs-drawer__footer">
					<button type="button" class="cs-drawer__clear" disabled>%s</button>
				</div>',
				esc_html__( 'Reset filters', 'celersearch' )
			);
			echo '</div>'; // .cs-drawer
		}

		if ( $style === 'inline' ) {
			echo '</div>'; // .cs-filters-collapsible
		}
	}

	/**
	 * Render the custom sort dropdown
	 *
	 * @return void
	 */
	private function render_sort_dropdown(): void {
		$options = [
			'menu_order' => __( 'Default sorting', 'celersearch' ),
			'popularity' => __( 'Sort by popularity', 'celersearch' ),
			'rating'     => __( 'Sort by average rating', 'celersearch' ),
			'date'       => __( 'Sort by latest', 'celersearch' ),
			'price'      => __( 'Sort by price: low to high', 'celersearch' ),
			'price-desc' => __( 'Sort by price: high to low', 'celersearch' ),
		];

		echo '<select class="cs-sort-select" aria-label="' . esc_attr__( 'Shop order', 'celersearch' ) . '">';
		foreach ( $options as $value => $label ) {
			printf(
				'<option value="%s">%s</option>',
				esc_attr( $value ),
				esc_html( $label )
			);
		}
		echo '</select>';
	}

	/**
	 * Render a checkbox filter group
	 *
	 * @param string $filter_key
	 * @param string $heading
	 * @param array  $options
	 */
	private function render_checkbox_filter( string $filter_key, string $heading, array $options ): void {
		echo '<div class="cs-filter cs-filter--taxonomy" data-filter="' . esc_attr( $filter_key ) . '">';
		echo '<h4 class="cs-filter__heading">' . esc_html( $heading ) . '</h4>';
		echo '<ul class="cs-filter-list">';

		foreach ( $options as $name => $count ) {
			printf(
				'<li><label class="cs-filter__checkbox"><input type="checkbox" value="%s"> %s <span class="cs-count">(%d)</span></label></li>',
				esc_attr( $name ),
				esc_html( $name ),
				(int) $count
			);
		}

		echo '</ul>';
		echo '</div>';
	}

	/**
	 * Render rating filter
	 *
	 * @param array $ratings
	 */
	private function render_rating_filter( array $ratings ): void {
		echo '<div class="cs-filter cs-filter--rating" data-filter="ratings.average_rating">';
		echo '<h4 class="cs-filter__heading">' . esc_html__( 'Rating', 'celersearch' ) . '</h4>';
		echo '<ul class="cs-filter-list">';

		for ( $i = 5; $i >= 1; $i-- ) {
			$count = $ratings[ $i ] ?? 0;
			$stars = str_repeat( '&#9733;', $i ) . str_repeat( '&#9734;', 5 - $i );
			printf(
				'<li><label class="cs-filter__checkbox"><input type="checkbox" value="%d"> <span class="cs-stars">%s</span> <span class="cs-count">(%d)</span></label></li>',
				$i,
				$stars,
				(int) $count
			);
		}

		echo '</ul>';
		echo '</div>';
	}

	/**
	 * Get initial facet data by running a MeiliSearch query
	 *
	 * @param int $index_id
	 *
	 * @return array
	 */
	private function get_initial_facet_data( int $index_id ): array {
		try {
			$index = IndexFactory::create( $index_id );

			$facet_attributes = $this->get_facet_attributes_for_index( $index );

			// Build filters for current browse context
			$filters = [
				[
					'field'    => 'status',
					'operator' => '=',
					'value'    => 'publish',
				],
			];

			// If on a category archive, pre-filter
			if ( is_product_category() ) {
				$term = get_queried_object();
				if ( $term && ! is_wp_error( $term ) ) {
					$filters[] = [
						'field'    => 'taxonomies.product_cat',
						'operator' => '=',
						'value'    => $term->name,
					];
				}
			} elseif ( is_product_tag() ) {
				$term = get_queried_object();
				if ( $term && ! is_wp_error( $term ) ) {
					$filters[] = [
						'field'    => 'taxonomies.product_tag',
						'operator' => '=',
						'value'    => $term->name,
					];
				}
			}

			$params = [
				'limit'   => 0,
				'facets'  => $facet_attributes,
				'filters' => $filters,
			];

			$response = $index->search( '', $params );

			if ( $response->is_error_response() ) {
				return [];
			}

			$facet_stats = $response->get_facet_stats();

			return [
				'facets'      => $response->get_facet_distribution(),
				'price_range' => [
					'min' => $facet_stats['price']['min'] ?? 0,
					'max' => $facet_stats['price']['max'] ?? 0,
				],
			];

		} catch ( \Exception $e ) {
			return [];
		}
	}

	/**
	 * Get facet attributes for a given index
	 *
	 * @param \CelerSearch\Indices\BaseIndex $index
	 *
	 * @return array
	 */
	private function get_facet_attributes_for_index( $index ): array {
		$settings   = $index->get_settings();
		$filterable = $settings->get_filterable_attributes();
		$facets     = [];

		$wanted = [ 'taxonomies', 'in_stock', 'ratings.average_rating', 'price' ];

		foreach ( $filterable as $attr ) {
			if ( in_array( $attr, $wanted, true ) || strpos( $attr, 'taxonomies.' ) === 0 ) {
				$facets[] = $attr;
			}
		}

		if ( ! in_array( 'price', $facets, true ) ) {
			$facets[] = 'price';
		}

		return array_unique( $facets );
	}

	/**
	 * Get attribute taxonomy filters (pa_color, pa_size, etc.)
	 *
	 * @param int $index_id
	 *
	 * @return array key => label
	 */
	private function get_attribute_filters( int $index_id ): array {
		if ( ! function_exists( 'wc_get_attribute_taxonomies' ) ) {
			return [];
		}

		$attributes = wc_get_attribute_taxonomies();
		$result     = [];

		foreach ( $attributes as $attr ) {
			$taxonomy            = 'pa_' . $attr->attribute_name;
			$result[ $taxonomy ] = $attr->attribute_label;
		}

		return $result;
	}

	/**
	 * Get the shop browse index ID from settings
	 *
	 * @return int
	 */
	private function get_shop_index_id(): int {
		$settings = get_option( 'celersearch_settings', [] );

		if ( empty( $settings['enable_search'] ) ) {
			return 0;
		}

		$areas = $settings['search_areas'] ?? [];

		foreach ( $areas as $area ) {
			if ( ( $area['type'] ?? '' ) === 'woocommerce_shop_browse' && ! empty( $area['enabled'] ) ) {
				return (int) ( $area['index_id'] ?? 0 );
			}
		}

		return 0;
	}

	/**
	 * Get the filter display style from settings
	 *
	 * @return string 'drawer' or 'inline'
	 */
	private function get_filter_style(): string {
		$settings = get_option( 'celersearch_settings', [] );
		$areas    = $settings['search_areas'] ?? [];
		foreach ( $areas as $area ) {
			if ( ( $area['type'] ?? '' ) === 'woocommerce_shop_browse' && ! empty( $area['enabled'] ) ) {
				$filters_feature = $area['features']['filters'] ?? [];
				if ( is_array( $filters_feature ) ) {
					return $filters_feature['style'] ?? 'drawer';
				}
				return 'drawer';
			}
		}
		return 'drawer';
	}

	/**
	 * Check if the search field feature is enabled
	 *
	 * @return bool
	 */
	private function is_search_enabled(): bool {
		$settings = get_option( 'celersearch_settings', [] );
		$areas    = $settings['search_areas'] ?? [];
		foreach ( $areas as $area ) {
			if ( ( $area['type'] ?? '' ) === 'woocommerce_shop_browse' && ! empty( $area['enabled'] ) ) {
				$search_feature = $area['features']['search'] ?? [];
				if ( is_array( $search_feature ) ) {
					return ! empty( $search_feature['enabled'] );
				}
				return (bool) $search_feature;
			}
		}
		return false;
	}

	/**
	 * Check if current page is a WooCommerce shop page
	 *
	 * @return bool
	 */
	private function is_shop_page(): bool {
		if ( ! function_exists( 'is_shop' ) ) {
			return false;
		}

		return is_shop() || is_product_category() || is_product_tag() || is_product_taxonomy();
	}

	/**
	 * Get JS configuration
	 *
	 * @param int $index_id
	 *
	 * @return array
	 */
	private function get_script_config( int $index_id ): array {
		$config = [
			'restUrl'  => rest_url( 'celersearch/v1/shop-filter' ),
			'nonce'    => wp_create_nonce( 'wp_rest' ),
			'indexId'  => $index_id,
			'style'    => $this->get_filter_style(),
			'i18n'     => [
				'noResults'   => __( 'No products found', 'celersearch' ),
				'clearAll'    => __( 'Clear all', 'celersearch' ),
				'loading'     => __( 'Loading...', 'celersearch' ),
				'inStockOnly' => __( 'In stock only', 'celersearch' ),
				'price'       => __( 'Price', 'celersearch' ),
				'category'    => __( 'Category', 'celersearch' ),
				'rating'      => __( 'Rating', 'celersearch' ),
				'availability' => __( 'Availability', 'celersearch' ),
				'search'       => __( 'Search', 'celersearch' ),
			],
		];

		// Add current context filters (pre-selected category/tag)
		$current_filters = [];

		if ( is_product_category() ) {
			$term = get_queried_object();
			if ( $term && ! is_wp_error( $term ) ) {
				$current_filters['taxonomies.product_cat'] = [ html_entity_decode( $term->name ) ];
			}
		} elseif ( is_product_tag() ) {
			$term = get_queried_object();
			if ( $term && ! is_wp_error( $term ) ) {
				$current_filters['taxonomies.product_tag'] = [ html_entity_decode( $term->name ) ];
			}
		}

		$config['currentFilters'] = $current_filters;

		// All known filter sections so JS can create missing ones dynamically
		$attribute_filters = $this->get_attribute_filters( $index_id );
		$filter_sections   = [
			'taxonomies.product_cat' => $config['i18n']['category'],
		];
		foreach ( $attribute_filters as $attr_key => $attr_label ) {
			$filter_sections[ 'taxonomies.' . $attr_key ] = $attr_label;
		}
		$config['filterSections'] = $filter_sections;

		return apply_filters( 'celersearch_shop_filters_js_config', $config );
	}
}
