<?php

namespace Blocksy\Extensions\WoocommerceExtra;

class Waitlist_Table extends \WP_List_Table {	
	protected function extra_tablenav($which) {
		?>
		<div class="alignleft actions has-searchbox">
			<?php
				if ('top' === $which) {
					$this->search_box(esc_html__('Search Products', 'blocksy-companion'), 'blocksy-companion');
				}
			?>
		</div>
		<?php
		
		do_action('manage_posts_extra_tablenav', $which);
	}

	public function get_hidden_columns() {
		return [];
	}

	public function column_default($item, $column_name) {
		if (isset($item[$column_name])) {
			return apply_filters(
				'blocksy:ext:woocommerce-extra:waitlist:products:column_default',
				esc_html($item[$column_name]), $item, $column_name
			);
		}
	}

	public function column_cb($item) {
		return blocksy_safe_sprintf(
			'<input type="checkbox" name="products_ids[]" value="%1$s" />',
			! empty($item['variation_id']) ? $item['variation_id'] : $item['product_id']
		);
	}

	public function column_thumb($item) {
		$product_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id'];
		$product = wc_get_product($product_id);

		if (! $product) {
			return '';
		}
		?>
		<a href="<?php echo esc_url(get_edit_post_link($product->get_id())); ?>">
			<?php echo $product->get_image('thumbnail'); // phpcs:ignore. ?>
		</a>
		<?php
	}

	public function column_action($item) {
		?>
			<a href="<?php echo esc_url(
				add_query_arg(
					[
						'page' => 'blocksy-waitlist-page',
						'tab' => 'users',
						'product_id' => $item['product_id'],
						'variation_id' => $item['variation_id'],
					],
					admin_url('edit.php?post_type=product')
				)
			); ?>" class="button">
				<?php esc_html_e('View Subscribers', 'blocksy-compaion'); ?>
			</a>
		<?php
	}

	public function column_name($item) {
		$product_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id'];
		$product = wc_get_product($product_id);

		if (! $product) {
			return '';
		}

		$product_edit_url = get_edit_post_link($item['product_id']);

		$actions = [
			'product_id' => blocksy_safe_sprintf('ID: %s', esc_html($item['product_id'])),
			'edit' => blocksy_safe_sprintf(
				'<a href="%s" title="%s">%s</a>',
				$product_edit_url,
				esc_html__('Edit this item', 'blocksy-compaion'),
				esc_html__('Edit', 'blocksy-compaion')
			),
			'view_product' => blocksy_safe_sprintf(
				'<a href="%s" title="%s" rel="permalink">%s</a>',
				$product->get_permalink(),
				esc_html__('View Product', 'blocksy-compaion'),
				esc_html__('View Product', 'blocksy-compaion')
			),
		];

		if ('variation' === $product->get_type()) {
			$attributes = [];

			foreach ($product->get_attributes() as $taxonomy => $value) {
				$attribute_values = wc_get_product_terms($product->get_parent_id(), $taxonomy, ['fields' => 'all']);

				$value_name = $value;

				foreach ($attribute_values as $attribute_value) {
					if ($attribute_value->slug === $value) {
						$value_name = esc_html($attribute_value->name);

						break;
					}
				}

				$attributes[wc_attribute_label($taxonomy)] = $value_name;
			}
		}

		?>
		<div class="product-details">
			<strong>
				<a class="row-title" href="<?php echo esc_url($product_edit_url); ?>">
					<?php echo esc_html($product->get_title()); ?>
				</a>
			</strong>

			<?php if (isset($attributes) && ! empty($attributes)) : ?>
				<table cellspacing="0" class="product-variations">
					<?php foreach ($attributes as $label => $value) : ?>
						<tr>
							<th><?php echo wp_kses_post(ucfirst($label)); ?>:</th>
							<td><?php echo wp_kses_post(ucfirst($value)); ?></td>
						</tr>
					<?php endforeach; ?>
				</table>
			<?php endif; ?>

			<?php echo $this->row_actions($actions); // phpcs:ignore. ?>
		</div>
		<?php
	}

	public function column_is_in_stock($item) {
		$product_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id'];
		$product = wc_get_product($product_id);

		if (! $product) {
			return '';
		}

		if ($product->is_in_stock()) {
			$status_class = 'instock';
			$status_label = esc_html__('In stock', 'blocksy-compaion');
		} else {
			$status_class = 'outofstock';
			$status_label = esc_html__('Out of stock', 'blocksy-compaion');
		}

		ob_start();
		?>
		<mark class="<?php echo esc_attr($status_class); ?>">
			<?php echo esc_html($status_label); ?>
		</mark>
		<?php

		return ob_get_clean();
	}

	public function column_price($item) {
		$product_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id'];
		$product = wc_get_product($product_id);

		if (! $product) {
			return '';
		}

		return $product->get_price_html();
	}

	public function column_users($item) {
		$user_count = $item['user_count'];

		return blocksy_safe_sprintf(
			'<a href="%s">%d</a>',
			esc_url(
				add_query_arg(
					[
						'page' => 'blocksy-waitlist-page',
						'tab' => 'users',
						'product_id' => $item['product_id'],
						'variation_id' => $item['variation_id'],
					],
					admin_url('edit.php?post_type=product')
				)
			),
			$user_count
		);
	}

	public function column_statuses($item) {
		$user_count = $item['user_count'];
		$failed = $item['failed_count'];
		$pending = $item['pending_count'];

		$content = blocksy_safe_sprintf(
			'<a href="%s">%s: %d</a>',
			esc_url(
				add_query_arg(
					[
						'page' => 'blocksy-waitlist-page',
						'tab' => 'users',
						'product_id' => $item['product_id'],
						'variation_id' => $item['variation_id'],
					],
					admin_url('edit.php?post_type=product')
				)
			),
			esc_html__('Subscribers', 'blocksy-compaion'),
			$user_count
		);

		if ($pending > 0) {
			$content .= blocksy_safe_sprintf(
				'<div class="pending">%s: %d</div>',
				esc_html__('Pending entries', 'blocksy-compaion'),
				$pending
			);
		}

		if ($failed > 0) {
			$content .= blocksy_safe_sprintf(
				'<div class="failed">%s: %d</div>',
				esc_html__('Failed entries', 'blocksy-compaion'),
				$failed
			);
		}

		return $content;
	}

	public function get_columns() {
		return [
			'cb' => '<input type="checkbox" />',
			'thumb' => '<span class="wc-image tips" data-tip="' . esc_attr__('Image', 'blocksy-compaion') . '">' . esc_html__('Image', 'blocksy-compaion') . '</span>',
			'name' => esc_html__('Name', 'blocksy-compaion'),
			'is_in_stock' => esc_html__('Stock', 'blocksy-compaion'),
			'price' => esc_html__('Price', 'blocksy-compaion'),
			'statuses' => esc_html__('Status', 'blocksy-compaion'),
			'action' => esc_html__('', 'blocksy-compaion'),
		];
	}

	public function get_sortable_columns() {
		return [];
	}

	public function get_bulk_actions() {
		return [
			'delete' => esc_html__('Delete', 'blocksy-compaion'),
		];
	}

	public function process_bulk_action() {
		if (
			! isset($_REQUEST['_wpnonce'])
			||
			! wp_verify_nonce($_REQUEST['_wpnonce'], 'bulk-' . $this->_args['plural'])
		) {
			return;
		}

		$products_ids = isset($_REQUEST['products_ids']) ? array_map('intval', (array) $_REQUEST['products_ids']) : false;

		if (
			'delete' === $this->current_action()
			&&
			! empty($products_ids)
		) {
			foreach ($products_ids as $product_id) {
				try {
					ProductWaitlistDb::unsubscribe_by_product($product_id);
				} catch (Exception $e) {
					continue;
				}
			}

			wp_safe_redirect(admin_url('/edit.php?post_type=product&page=blocksy-waitlist-page'));
			die();
		}

		$users_emails = isset($_REQUEST['users_emails']) ? array_map('sanitize_email', (array) $_REQUEST['users_emails']) : false;
		$product_id = isset($_REQUEST['product_id']) ? intval($_REQUEST['product_id']) : false;
		$variation_id = isset($_REQUEST['variation_id']) ? intval($_REQUEST['variation_id']) : false;

		if (
			'delete' === $this->current_action()
			&&
			! empty($users_emails)
			&&
			! empty($product_id)
		) {
			foreach ($users_emails as $users_email) {
				try {
					$product_id = $variation_id ? $variation_id : $product_id;
					
					ProductWaitlistDb::unsubscribe_by_product($product_id, $users_email);
				} catch (Exception $e) {
					continue;
				}
			}

			wp_safe_redirect(
				add_query_arg(
					[
						'page' => 'blocksy-waitlist-page',
						'tab' => 'users',
						'product_id' => $_REQUEST['product_id'],
						'variation_id' => $_REQUEST['variation_id'],
					],
					admin_url('edit.php?post_type=product')
				)
			);
			die();
		}

		if (
			'retry' === $this->current_action()
			&&
			! empty($users_emails)
			&&
			! empty($product_id)
		) {
			$backInStockScheduler = new BackInStockEmailScheduler();
			$product = wc_get_product($product_id);

			if ($variation_id) {
				$product = wc_get_product($variation_id);
			}

			if (
				! $product
				||
				$product->get_stock_status() === 'outofstock'
			) {
				return;
			}

			$waitlists_to_process = [];

			foreach ($users_emails as $user_email) {
				$waitlist = ProductWaitlistDb::get_waitlists_from_db($product, $user_email, '', true);

				if (! empty($waitlist)) {
					$waitlists_to_process[] = $waitlist[0];
				}
			}

			if (empty($waitlists_to_process)) {
				return;
			}

			$waitlists_to_process = array_filter($waitlists_to_process, function ($waitlist) {
				return $waitlist->state === 'failed' || $waitlist->state === 'new';
			});

			$backInStockScheduler->initiate($waitlists_to_process);
		}
	}

	public function prepare_items() {
		$columns = $this->get_columns();
		$hidden = $this->get_hidden_columns();
		$sortable = $this->get_sortable_columns();
		$user_id = get_current_user_id();

		$data = $this->table_data();
		usort($data, [$this, 'sort_data']);

		$per_page = ! empty(get_user_meta($user_id, 'waitlist_per_page', true)) ? get_user_meta($user_id, 'waitlist_per_page', true) : 20;
		$current_page = $this->get_pagenum();
		$total_items = count($data);

		$this->set_pagination_args(
			[
				'total_items' => $total_items,
				'per_page' => $per_page,
			]
		);

		$data = array_slice($data, (($current_page - 1) * $per_page), $per_page);

		$this->_column_headers = [$columns, $hidden, $sortable];
		$this->items = $data;

		$this->process_bulk_action();
	}

	private function table_data() {
		global $wpdb;

		$where_query = [];
		$search = isset($_REQUEST['s']) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : false; // phpcs:ignore.

		if ($search) {
			$where_query[] = $wpdb->prepare("$wpdb->posts.`post_title` LIKE %s", '%' . $wpdb->esc_like($search) . '%');
		}

		$where_query[] = $wpdb->prepare("$wpdb->blocksy_waitlists.`confirmed` = %d", 1);

		$where_query_text = ! empty($where_query) ? ' WHERE ' . implode(' AND ', $where_query) : '';

		if (! wp_cache_get('blocksy_waitlist_table_data')) {
			$waitlists = $wpdb->get_results(//phpcs:ignore;
				"SELECT
					$wpdb->blocksy_waitlists.`subscription_id`,
					$wpdb->blocksy_waitlists.`product_id`,
					$wpdb->blocksy_waitlists.`variation_id`,
					COUNT($wpdb->blocksy_waitlists.`user_id`) as `user_count`,
					SUM(CASE WHEN $wpdb->blocksy_waitlists.`state` = 'new' THEN 1 ELSE 0 END) AS new_count,
					SUM(CASE WHEN $wpdb->blocksy_waitlists.`state` = 'pending' THEN 1 ELSE 0 END) AS pending_count,
					SUM(CASE WHEN $wpdb->blocksy_waitlists.`state` = 'failed' THEN 1 ELSE 0 END) AS failed_count,
					$wpdb->blocksy_waitlists.`created_date_gmt` as `created_date`
				FROM $wpdb->blocksy_waitlists
				INNER JOIN $wpdb->posts
					ON $wpdb->posts.`ID` = $wpdb->blocksy_waitlists.`product_id`"
				. $where_query_text .
				" GROUP BY
					$wpdb->blocksy_waitlists.`product_id`,
					$wpdb->blocksy_waitlists.`variation_id`
				LIMIT 50;",
				ARRAY_A
			);

			$waitlists = array_filter($waitlists, function ($waitlist) {
				if ($waitlist['variation_id']) {
					$product = wc_get_product($waitlist['variation_id']);
				} else {
					$product = wc_get_product($waitlist['product_id']);
				}
	
				return !!$product;
			});

			wp_cache_set(
				'blocksy_waitlist_table_data',
				$waitlists
			);
		}

		return wp_cache_get('blocksy_waitlist_table_data');
	}

	private function sort_data($a, $b) {
		// Set defaults.
		$order_by = 'created_date';
		$order = 'desc';

		// If orderby is set, use this as the sort column.
		if (! empty($_GET['orderby'])) { // phpcs:ignore.
			$order_by = $_GET['orderby']; // phpcs:ignore.
		}

		// If order is set use this as the order.
		if (! empty($_GET['order'])) { // phpcs:ignore.
			$order = $_GET['order']; // phpcs:ignore.
		}

		$result = strcmp($a[$order_by], $b[$order_by]);

		if (is_numeric($a[$order_by]) && is_numeric($a[$order_by])) {
			$result = $a[$order_by] - $b[$order_by];
		}

		if ('asc' === $order) {
			return $result;
		}

		return -$result;
	}

}
