<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if ( ! class_exists( 'WP_List_Table' ) ) {
	include_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class W2PShopTemplatesTable extends WP_List_Table {


	public W2PShop $w2pshop;
	public W2PShopDbHelper $db_helper;

	public array $linked_templates     = array();
	public array $not_linked_templates = array();
	public string $order_by            = '';
	public string $search_key          = '';
	public int $items_per_page         = 15;
	public $items                      = null;

	function __construct( array $options = array() ) {
		parent::__construct( $options );
		$this->w2pshop   = new W2PShop();
		$this->db_helper = new W2PShopDbHelper();
	}

	/**
	 * [REQUIRED] this is a default column renderer
	 *
	 * @param $item
	 * @param $column_name
	 *
	 * @return mixed|void
	 */
	public function column_default( $item, $column_name ) {
		return ( is_array( $item ) ) ? $item[ $column_name ] : $item->{$column_name};
	}

	/**
	 * [REQUIRED] this is a checkbox column renderer
	 *
	 * @param $item - row (key, value array)
	 *
	 * @return string
	 */
	public function column_cb( $item ): string {
		if ( is_array( $item ) ) {
			if ( array_key_exists( 'ProductID', $item ) ) {
				$product_id = $item['ProductID'];
			} else {
				$product_id = $item['id']; // Default to the ID
			}
		} else {
			if ( property_exists( $item, 'ProductID' ) ) {
				$product_id = $item->ProductID;
			} else if ( property_exists( $item, 'key' ) ) {
				$product_id = $item->key;
			} else {
				$product_id = $item->id; // Default to the ID
			}
		}

		return sprintf( '<input type="checkbox" name="id[]" value="%s" />', $product_id );
	}

	/**
	 * Create view filters for the table
	 *
	 * @return array
	 */
	public function get_views(): array {
		$views   = array();
		if (isset( $_REQUEST['w2pshop_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash($_REQUEST['w2pshop_nonce'])), 'w2pshop_switch_view' ))
		{
			$current = ( ! empty( $_REQUEST['w2pshop_view'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_view'] )) : 'all' );
		} else {
			$current = 'all';
		}
		$_linked_templates_count     = count( $this->linked_templates );
		$_not_linked_templates_count = count( $this->not_linked_templates );

		// All link
		$total_count  = $_linked_templates_count + $_not_linked_templates_count;
		$class        = ( $current == 'all' ? ' class="current"' : '' );
		$href         = esc_url( remove_query_arg( 'w2pshop_view' ) );
		$views['All'] = "<a href='{$href}' {$class}>All<span class=\"count\">&nbsp;({$total_count})</span></a>";

		// Linked link
		$class           = ( $current == 'linked' ? ' class="current"' : '' );
		$href            = esc_url( add_query_arg( array('w2pshop_view' => 'linked', 'w2pshop_nonce'  => wp_create_nonce( 'w2pshop_switch_view')) ) );
		$views['Linked'] = "<a href='{$href}' {$class}>Linked To Product<span class=\"count\">&nbsp;({$_linked_templates_count})</span></a>";

		// Not Linked link
		$class              = ( $current == 'not_linked' ? ' class="current"' : '' );
		$href               = esc_url( add_query_arg(  array('w2pshop_view' => 'not_linked', 'w2pshop_nonce'  => wp_create_nonce( 'w2pshop_switch_view' ) )));
		$views['NotLinked'] = "<a href='{$href}' {$class}>Not Linked To Product<span class=\"count\">&nbsp;({$_not_linked_templates_count})</span></a>";

		return $views;
	}

	/**
	 * Sets linked products to items based on a lookup key and a compare identifier.
	 *
	 * @param string $lookup_key The lookup key used to find linked products.
	 * @param string $compare_identifier The identifier used to compare items and products.
	 * @param string $source_compare_identifier
	 */
	public function set_linked_products_to_items( string $lookup_key, string $compare_identifier, string $source_compare_identifier = "" ): void {
		if (empty( $lookup_key )) {
			return;
		}

		$source_compare_identifier = $source_compare_identifier ?: $compare_identifier;

		// Prepare product meta once
		$w2pshop_products = $this->w2pshop->get_products();
		$products_meta = [];
		foreach ($w2pshop_products as $product) {
			$meta = get_post_meta($product->ID, '_w2pshop_product', true);
			if (!empty($meta[$lookup_key])) {
				$products_meta[] = [
					'product' => $product,
					'linked_items' => $meta[$lookup_key]
				];
			}
		}

		// Build lookup map
		$lookup_map = [];
		foreach ($products_meta as $entry) {
			foreach ($entry['linked_items'] as $linked_item) {
				if ($linked_item) {
					$key = $linked_item->{$compare_identifier};
					$lookup_map[$key][] = [
						'post_id' => $entry['product']->ID,
						'product_title' => $entry['product']->post_title
					];
				}
			}
		}

		// Assign linked products to items
		foreach ($this->items as $item) {
			$key = $item->{$source_compare_identifier};
			$item->Products = $lookup_map[$key] ?? [];
		}
	}

	/**
	 * Sets the items based on a search key.
	 *
	 * @param array $all_items The array of all items.
	 * @param string $search_key The search key to filter items.
	 * @return void
	 */
	public function set_items_based_on_search(array $all_items, string $search_key = '' ): void {
        if (isset($_SERVER['REQUEST_METHOD']) && "POST" === $_SERVER['REQUEST_METHOD']) {
	        if ( isset( $_REQUEST['w2pshop_template_page_nonce'] ) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['w2pshop_template_page_nonce'])), 'w2pshop_template_page_nonce' ) )
	        {
		        $_search = isset($_REQUEST['s']) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : '';
	        } else {
		        $_search = '';
	        }
        } else {
            $_search = '';
        }
		$this->search_key = $search_key;

		if ( ! empty( $_search ) && ! empty( $this->search_key ) ) {
			$this->items = array_values(
				array_filter(
					$all_items,
					function ( $item ) use ( $_search ) {
						$_search_key = $this->search_key;
						return str_contains( strtolower( $item->{$_search_key} ), strtolower( $_search ) );
					},
					ARRAY_FILTER_USE_BOTH
				)
			);
		} else {
			$this->items = $all_items;
		}
	}

	/**
	 * Set the items if the view is filtered
	 *
	 * @return void
	 */
	public function set_items_based_on_view(): void {
		for ( $i = 0; $i < count( $this->items ); ++$i ) {
			if ( count( $this->items[ $i ]->Products ) > 0 ) {
				$this->linked_templates[] = $this->items[ $i ];
			} else {
				$this->not_linked_templates[] = $this->items[ $i ];
			}
		}
		if (isset( $_REQUEST['w2pshop_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash($_REQUEST['w2pshop_nonce'])), 'w2pshop_switch_view' ) )
		{
			if ( isset( $_REQUEST['w2pshop_view'] ) ) {
				$filter_view = sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_view'] ));
				switch ( $filter_view ) {
					case 'linked':
						$this->items = $this->linked_templates;
						break;
					case 'not_linked':
						$this->items = $this->not_linked_templates;
						break;
				}
			}
		}
	}

	/**
	 * Sorts the items by $_REQUEST['orderby']
	 *
	 * This will sort $this->items if $_REQUEST['orderby'] is set
	 *
	 * @return void
	 */
	public function sort_items_by_order(): void {
		if ( isset( $_REQUEST['orderby'] ) && isset( $_REQUEST['w2pshop_template_page_nonce'] ) && wp_verify_nonce( sanitize_text_field(wp_unslash($_REQUEST['w2pshop_template_page_nonce'])), 'w2pshop_template_page_nonce' ) ) {
			$this->order_by = sanitize_text_field( wp_unslash($_REQUEST['orderby'] ));
            if (isset($_REQUEST['order'])) {
                $order = sanitize_text_field(wp_unslash($_REQUEST['order']));
            }
			if ( $order == 'asc' ) {
				usort(
					$this->items,
					function ( $a, $b ) {
						return ( is_array( $a ) ) ?
						strcmp( $a[ $this->order_by ], $b[ $this->order_by ] ) :
						strcmp( $a->{$this->order_by}, $b->{$this->order_by} );
					}
				);
			} else {
				usort(
					$this->items,
					function ( $a, $b ) {
						return ( is_array( $a ) ) ?
						strcmp( $b[ $this->order_by ], $a[ $this->order_by ] ) :
						strcmp( $b->{$this->order_by}, $a->{$this->order_by} );
					}
				);
			}
		}

		// Once sorted, we can add pagination.
		$this->set_pagination_args(
			array(
				'total_items' => count( $this->items ),
				'per_page'    => $this->items_per_page,
			)
		);

		// Once pagination is set, we will set the page view based on the current page.
		$this->set_paged_view();
	}

	/**
	 * Set the page view based on the current page (pagination)
	 *
	 * @return void
	 */
	private function set_paged_view(): void {
		// Get the current page number
		$paged = $this->get_pagenum();

		// Calculate the starting index and length for the pagination
		$start_index = ( $paged - 1 ) * $this->items_per_page;

		// Slice the items array to get the items for the current page
		$paged_array = array_slice( $this->items, $start_index, $this->items_per_page );

		// Update the items array with the items for the current page
		if ( count( $paged_array ) > 0 ) {
			$this->items = $paged_array;
		}
	}
}
