<?php

/**
 * Class to define an Admin Table for showing subscribers of a giveaway
 */

namespace Simple_Giveaways;

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

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class SG_Subscriber_Entries_Table extends \WP_List_Table {

	/**
	 * Settings
	 *
	 * @var null|array
	 */
	public $settings = null;

	/**
	 * Form Fields
	 *
	 * @var null|array
	 */
	protected $subscriber = null;

	/**
	 * Caching Subscriber Emails by Subscriber ID.
	 *
	 * @var array
	 */
	protected $subscriber_emails = array();

	/**
	 * Action object.
	 *
	 * @var null
	 */
	protected $action_object = null;

	/** Class constructor */
	public function __construct() {

		parent::__construct(
			array(
				'singular' => __( 'Entry', 'giveasap' ), // singular name of the listed records
				'plural'   => __( 'Entries', 'giveasap' ), // plural name of the listed records
				'ajax'     => false, // should this table support ajax?
			)
		);

		$this->_column_headers = $this->get_columns();
	}

	/**
	 * Get the settings
	 */
	public function get_settings() {
		if ( null === $this->settings ) {
			$this->settings = giveasap_get_settings();
		}

		return $this->settings;
	}

	/**
	 * Get the settings
	 */
	public function get_subscriber() {
		if ( null === $this->subscriber ) {
			$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
			if ( $subscriber_id ) {
				$this->subscriber = giveasap_get_subscriber( $subscriber_id );
			}
		}

		return $this->subscriber;
	}

	/**
	 * Get the subscriber email from the cache or from DB
	 *
	 * @param integer $subscriber_id
	 *
	 * @return string
	 */
	public function get_subscriber_email( $subscriber_id ) {

		if ( ! isset( $this->subscriber_emails[ $subscriber_id ] ) ) {
			$user = giveasap_get_user_by_id( $subscriber_id );
			if ( ! $user ) {
				return '-';
			}
			$this->subscriber_emails[ $subscriber_id ] = $user->email;
		}

		return $this->subscriber_emails[ $subscriber_id ];
	}

	/**
	 * Retrieve user's data from the database
	 *
	 * @param int $per_page
	 * @param int $page_number
	 *
	 * @return mixed
	 */
	public static function get_entries( $per_page = 5, $page_number = 1 ) {

		global $wpdb;

		$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
		$giveaway_id   = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
		$action_type   = isset( $_REQUEST['action_type'] ) ? Helpers::unslash_and_clean( $_REQUEST['action_type'] ) : '';

		$sql  = 'SELECT sg_entries.*, subscribers.email, giveaways.post_title as giveaway_title FROM ' . $wpdb->giveasap_actions . ' as sg_entries';
		$sql .= ' LEFT JOIN ' . $wpdb->giveasap_entries . ' as subscribers on subscribers.id=sg_entries.subscriber_id';
		$sql .= ' LEFT JOIN ' . $wpdb->posts . ' as giveaways on giveaways.ID=sg_entries.giveaway_id';

		$sql .= ' WHERE 1=1';

		if ( $subscriber_id ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.subscriber_id = %d', $subscriber_id );
		}

		if ( $giveaway_id ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.giveaway_id = %d', $giveaway_id );
		}

		if ( $action_type ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.action = %s', $action_type );
		}

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			$sql .= ' ORDER BY ' . esc_sql( $_REQUEST['orderby'] );
			$sql .= ! empty( $_REQUEST['order'] ) ? ' ' . esc_sql( $_REQUEST['order'] ) : ' ASC';
		}

		$sql .= ' LIMIT ' . $per_page;

		$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;

		$result = $wpdb->get_results( $sql, 'ARRAY_A' );

		return $result;
	}

	/**
	 * Delete a user record.
	 *
	 * @param int $id customer ID
	 */
	public static function delete_action( $id ) {
		global $wpdb;

		$action = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->giveasap_actions WHERE id=%d", $id ), ARRAY_A );

		if ( ! $action ) {
			return;
		}
		$ret = $wpdb->delete(
			$wpdb->giveasap_actions,
			array( 'id' => $id ),
			array( '%d' )
		);

		if ( false !== $ret ) {
			$subscriber = giveasap_get_subscriber( $action['subscriber_id'] );
			$subscriber->remove_entries( $action['entries'] );
		}
	}

	/**
	 * Returns the count of records in the database.
	 *
	 * @return null|string
	 */
	public static function record_count() {
		global $wpdb;

		$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
		$giveaway_id   = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
		$action_type   = isset( $_REQUEST['action_type'] ) ? Helpers::unslash_and_clean( $_REQUEST['action_type'] ) : '';

		$sql = 'SELECT COUNT(*) FROM ' . $wpdb->giveasap_actions . ' as sg_entries';

		$sql .= ' WHERE 1=1';

		if ( $subscriber_id ) {
			$sql .= $wpdb->prepare( ' AND subscriber_id = %d', $subscriber_id );
		}

		if ( $giveaway_id ) {
			$sql .= $wpdb->prepare( ' AND giveaway_id = %d', $giveaway_id );
		}

		if ( $action_type ) {
			$sql .= $wpdb->prepare( ' AND action = %s', $action_type );
		}

		return $wpdb->get_var( $sql );
	}

	/** Text displayed when no user data is available */
	public function no_items() {
		esc_html_e( 'No Entries.', 'giveasap' );
	}

	/**
	 * Render a column when no column specific method exists.
	 *
	 * @param array  $item
	 * @param string $column_name
	 *
	 * @return mixed
	 */
	public function column_default( $item, $column_name ) {
		return $item[ $column_name ];
	}

	/**
	 * Return the Giveaway
	 *
	 * @param $item
	 */
	public function column_giveaway( $item ) {
		return $item['giveaway_title'] ? $item['giveaway_title'] : get_the_title( $item['giveaway_id'] );
	}

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_actions( $item ) {
		$resend_nonce = wp_create_nonce( 'giveasap_delete_entry' );

		$subscriber_actions = array();
		$resend_args        = array(
			'post_type'    => 'giveasap',
			'page'         => esc_attr( Helpers::unslash_and_clean( $_REQUEST['page'] ) ),
			'action'       => 'delete_action_entry',
			'action_id'    => absint( $item['id'] ),
			'subscriber'   => absint( $item['subscriber_id'] ),
			'delete_nonce' => $resend_nonce,
			'paged'        => isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1,
		);

		$delete_url = add_query_arg( $resend_args, admin_url( 'edit.php' ) );

		if ( isset( $_REQUEST['id'] ) ) {
			$resend_args['id'] = absint( $_REQUEST['id'] );
		}

		if ( 'completed' !== $item['status'] ) {
			$resend_args['action']          = 'complete_action_entry';
			$complete_url                   = add_query_arg( $resend_args, admin_url( 'edit.php' ) );
			$subscriber_actions['complete'] = '<a class="button button-small sg-tooltip" href="' . esc_attr( $complete_url ) . '" title="' . __( 'Complete the Entry', 'giveasap' ) . '"><span class="fal fa-check"></span></a>';
		}

		if ( 'invalid' !== $item['status'] ) {
			$resend_args['action']         = 'invalid_action_entry';
			$complete_url                  = add_query_arg( $resend_args, admin_url( 'edit.php' ) );
			$subscriber_actions['invalid'] = '<a class="button button-small sg-tooltip" href="' . esc_attr( $complete_url ) . '" title="' . __( 'Invalidate the Entry', 'giveasap' ) . '"><span class="fal fa-ban"></span></a>';
		}

		$subscriber_actions['delete'] = '<a class="button button-small sg-button-red sg-tooltip" href="' . esc_attr( $delete_url ) . '" title="' . __( 'Delete the Entry', 'giveasap' ) . '"><span class="fal fa-trash"></span></a>';

		$subscriber_actions = apply_filters( 'sg_admin_subscriber_entries_actions_column', $subscriber_actions, $item );
		$html               = '';
		if ( $subscriber_actions ) {
			$html = implode( ' ', $subscriber_actions );
		}
		return $html;
	}

	/**
	 * Render the bulk edit checkbox
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="bulk-delete[]" value="%s" />',
			$item['id']
		);
	}

	/**
	 * Show the column email
	 *
	 * @param array $item
	 */
	public function column_email( $item ) {

		$email = $item['email'] ? $item['email'] : '-';

		if ( $email ) {
			$actions = array(
				'entries' => sprintf( '<a href="edit.php?post_type=giveasap&page=%s&subscriber=%d">' . __( 'All Entries', 'giveasap' ) . '</a>', 'giveasap-subscriber-entries', absint( $item['subscriber_id'] ) ),
			);

			$email .= $this->row_actions( $actions );
		}

		return $email;
	}

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_title( $item ) {
		$data = maybe_unserialize( $item['data'] );

		if ( isset( $data['title'] ) ) {
			return $data['title'];
		}
	}

	/**
	 * @param $item
	 *
	 * @return string
	 */
	public function column_status( $item ) {
		return '<span class="sg-badge sg-entries-status sg-status sg-status-' . esc_attr( $item['status'] ) . '">' . esc_html( $item['status'] ) . '</span>';
	}

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_value( $item ) {
		$registered_actions = giveasap_get_registered_actions();
		if ( ! isset( $registered_actions[ $item['action'] ] ) ) {
			return apply_filters( 'sg_extra_action_not_registered_column_value', '-', $item );
		}

		if ( ! class_exists( $registered_actions[ $item['action'] ] ) ) {
			return '-';
		}

		$action        = $registered_actions[ $item['action'] ];
		$action_object = new $action();
		$action_object->prepare_value_for_entries_table( $item );

		return $action_object->get_value_for_entries_table( maybe_unserialize( $item['data'] ) );
	}

	/**
	 *  Associative array of columns
	 *
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			// 'cb'      => '<input type="checkbox" />',
			'email'   => __( 'Email', 'giveasap' ),
			'action'  => __( 'Action', 'giveasap' ),
			'title'   => __( 'Title', 'giveasap' ),
			'value'   => __( 'Value', 'giveasap' ),
			'entries' => __( 'Entries', 'giveasap' ),
			'status'  => __( 'Status', 'giveasap' ),
		);

		if ( null !== $this->get_subscriber() ) {
			unset( $columns['email'] );
		}

		$giveaway_id = isset( $_GET['giveaway'] ) ? absint( $_GET['giveaway'] ) : 0;

		if ( ! $giveaway_id ) {
			$columns['giveaway'] = __( 'Giveaway', 'giveasap' );
		}

		$columns['actions'] = __( 'Actions', 'giveasap' );

		return $columns;
	}

	/**
	 * Columns to make sortable.
	 *
	 * @return array
	 */
	public function get_sortable_columns() {
		$sortable_columns = array(
			'entries' => array( 'entries', true ),
			'email'   => array( 'email', true ),
		);

		return $sortable_columns;
	}

	/**
	 * Returns an associative array containing the bulk action
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		$actions = array(
			// 'bulk-delete' => 'Delete'
		);

		return $actions;
	}

	/**
	 * Handles data query and filter, sorting, and pagination.
	 */
	public function prepare_items() {

		$columns               = $this->get_columns();
		$hidden                = array();
		$sortable              = $this->get_sortable_columns();
		$this->_column_headers = array( $columns, $hidden, $sortable );

		/** Process bulk action */
		$this->process_bulk_action();

		if ( isset( $_REQUEST['user_unblocked'] ) ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php printf( __( 'Subscriber Unblocked: %s', 'giveasap' ), esc_html( $_REQUEST['user_unblocked'] ) ); ?></p>
			</div>
			<?php
		}

		do_action( 'sg_subscriber_admin_list_before_items' );

		$per_page     = $this->get_items_per_page( 'sg_subscribers_per_page', 10 );
		$current_page = $this->get_pagenum();
		$total_items  = self::record_count();

		$this->set_pagination_args(
			[
				'total_items' => $total_items, // WE have to calculate the total number of items
				'per_page'    => $per_page, // WE have to determine how many items to show on a page
			]
		);

		$this->items = self::get_entries( $per_page, $current_page );

	}

	public function process_bulk_action() {

		// Detect when a bulk action is being triggered...
		if ( 'delete' === $this->current_action() ) {

			// In our file that handles the request, verify the nonce.
			$nonce = esc_attr( $_REQUEST['delete_nonce'] );

			if ( ! wp_verify_nonce( $nonce, 'giveasap_delete_customer' ) ) {
				die( 'Go get a life script kiddies' );
			} else {
				self::delete_action( absint( $_GET['user'] ) );
			}
		}

		if ( 'activate' === $this->current_action() ) {
			giveasap_activate_user( absint( $_GET['user'] ) );
		}

		// If the delete bulk action is triggered
		if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'bulk-delete' )
			 || ( isset( $_POST['action2'] ) && $_POST['action2'] == 'bulk-delete' )
		) {

			$delete_ids = esc_sql( $_POST['bulk-delete'] );

			// loop over the array of record IDs and delete them
			foreach ( $delete_ids as $id ) {
				self::delete_action( $id );

			}
		}
	}



	/**
	 * Extra controls to be displayed between bulk actions and pagination
	 *
	 * @since 2.10.0
	 *
	 * @param string $which
	 */
	public function extra_tablenav( $which ) {
		if ( 'top' === $which ) {

			$giveaway    = false;
			$action_type = isset( $_REQUEST['action_type'] ) ? Helpers::unslash_and_clean( $_REQUEST['action_type'] ) : '';

			if ( isset( $_REQUEST['giveaway'] ) ) {
				$giveaway = giveasap_get_giveaway( absint( $_REQUEST['giveaway'] ) );
			}

			?>
			<div class="alignleft actions">
				<select name="giveaway" placeholder="<?php echo esc_attr__( 'Search for a giveaway', 'giveasap' ); ?>" class="sg-select2" style="width: 200px;">
					<?php
					if ( $giveaway ) {
						?>
							<option value="<?php echo esc_attr( $giveaway->get_id() ); ?>"><?php echo wp_kses_post( $giveaway->get_post()->post_title ); ?></option>
							<?php
					}
					?>
				</select>
				<label for="sg_action_type">
					<?php
						esc_html_e( 'Action Type', 'giveasap' );
					?>
					<select id="sg_action_type" name="action_type" style="width: 200px;float:none;">
						<option value=""><?php esc_html_e( 'Show all', 'giveasap' ); ?></option>
					<?php
					$actions = giveasap_get_registered_actions();
					foreach ( $actions as $action_slug => $action_class ) {
						if ( ! class_exists( $action_class ) ) {
							continue;
						}

						$action_object = new $action_class();

						?>
						<option <?php selected( $action_type, $action_object->get_slug(), true ); ?> value="<?php echo esc_attr( $action_object->get_slug() ); ?>"><?php echo esc_html( $action_object->get_title() ); ?></option>
						<?php
					}
					?>
					</select>
				</label>
				<button class="button ga-filter-entries"><?php esc_html_e( 'Filter', 'giveasap' ); ?></button>

				<?php
				$subscriber_id  = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
				$giveaway_id    = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
				$action_type    = isset( $_REQUEST['action_type'] ) ? Helpers::unslash_and_clean( $_REQUEST['action_type'] ) : '';
				$export_payload = array(
					'subscriber' => $subscriber_id,
					'giveaway'   => $giveaway_id,
					'action'     => $action_type,
				);

				?>

				<button type="submit" name="sg_export_entries" value="<?php echo esc_attr( wp_json_encode( $export_payload ) ); ?>" class="button button-secondary"><?php esc_html_e( 'Export Entries', 'giveasap' ); ?></button>
			</div>
			<?php
		}
	}

	/**
	 * Display the pagination.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which
	 */
	public function pagination( $which ) {
		if ( empty( $this->_pagination_args ) ) {
			return;
		}

		$total_items     = $this->_pagination_args['total_items'];
		$total_pages     = $this->_pagination_args['total_pages'];
		$infinite_scroll = false;
		if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
			$infinite_scroll = $this->_pagination_args['infinite_scroll'];
		}

		if ( 'top' === $which && $total_pages > 1 ) {
			$this->screen->render_screen_reader_content( 'heading_pagination' );
		}

		$output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';

		$current              = $this->get_pagenum();
		$removable_query_args = wp_removable_query_args();

		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

		$current_url = remove_query_arg( $removable_query_args, $current_url );
		$current_url = remove_query_arg( 'user_notified', $current_url );
		$current_url = remove_query_arg( 'user_blocked', $current_url );
		$current_url = remove_query_arg( 'user_unblocked', $current_url );
		$page_links  = array();

		if ( isset( $_REQUEST['giveaway'] ) ) {
			$current_url = add_query_arg( 'giveaway', absint( $_REQUEST['giveaway'] ), $current_url );
		}

		$total_pages_before = '<span class="paging-input">';
		$total_pages_after  = '</span></span>';

		$disable_first = $disable_last = $disable_prev = $disable_next = false;

		if ( $current == 1 ) {
			$disable_first = true;
			$disable_prev  = true;
		}
		if ( $current == 2 ) {
			$disable_first = true;
		}
		if ( $current == $total_pages ) {
			$disable_last = true;
			$disable_next = true;
		}
		if ( $current == $total_pages - 1 ) {
			$disable_last = true;
		}

		if ( $disable_first ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( remove_query_arg( 'paged', $current_url ) ),
				__( 'First page' ),
				'&laquo;'
			);
		}

		if ( $disable_prev ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', max( 1, $current - 1 ), $current_url ) ),
				__( 'Previous page' ),
				'&lsaquo;'
			);
		}

		if ( 'bottom' === $which ) {
			$html_current_page  = $current;
			$total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
		} else {
			$html_current_page = sprintf(
				"%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
				'<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
				$current,
				strlen( $total_pages )
			);
		}
		$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
		$page_links[]     = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;

		if ( $disable_next ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='next-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', min( $total_pages, $current + 1 ), $current_url ) ),
				__( 'Next page' ),
				'&rsaquo;'
			);
		}

		if ( $disable_last ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='last-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
				__( 'Last page' ),
				'&raquo;'
			);
		}

		$pagination_links_class = 'pagination-links';
		if ( ! empty( $infinite_scroll ) ) {
			$pagination_links_class .= ' hide-if-js';
		}
		$output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';

		if ( $total_pages ) {
			$page_class = $total_pages < 2 ? ' one-page' : '';
		} else {
			$page_class = ' no-pages';
		}
		$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";

		echo $this->_pagination;
	}
}
