<?php
declare( strict_types=1 );

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching

/**
 * The admin-specific functionality of the plugin.
 *
 * @link       https://webequipe.com
 * @since      1.0.0
 *
 * @package    Webequipe_Spin_Win_Wheel
 * @subpackage Webequipe_Spin_Win_Wheel/admin
 */

/**
 * The admin-specific functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    Webequipe_Spin_Win_Wheel
 * @subpackage Webequipe_Spin_Win_Wheel/admin
 * @author     Webequipe <support@webequipe.com>
 */

require_once __DIR__ . '/../includes/class-webequipe-spin-win-wheel-functions.php';

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

/**
 * webequipe_sww_Spin_List class
 *
 * Handles the admin list table for spins (wheels).
 *
 * @package    Webequipe_Spin_Win_Wheel
 */
class Webequipe_Spin_Win_Wheel_Spin_List extends WP_List_Table {

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct(
			[
				'singular' => 'Wheel',
				'plural'   => 'Wheels',
				'ajax'     => false,
			]
		);
	}

	/**
	 * Message shown when no spins are found.
	 *
	 * @return void
	 */
	public function no_items() {
		esc_html_e( 'No Wheel found', 'webequipe-spin-win-wheel' );
	}

	/**
	 * Define columns for the table.
	 *
	 * @return array
	 */
	public function get_columns() {
		return [
			'cb'          => '<input type="checkbox" />',
			'spin_title'  => __( 'Name', 'webequipe-spin-win-wheel' ),
			'shortcode'   => __( 'Shortcode', 'webequipe-spin-win-wheel' ),
			'spin_count'  => __( 'Number of Response', 'webequipe-spin-win-wheel' ),
			'spin_status' => __( 'Status', 'webequipe-spin-win-wheel' ),
			'created_at'  => __( 'Date', 'webequipe-spin-win-wheel' ),
		];
	}

	/**
	 * Define sortable columns.
	 *
	 * @return array
	 */
	public function get_sortable_columns() {
		return [
			'spin_title'  => [ 'spin_title', true ],
			'spin_status' => [ 'spin_status', true ],
			'created_at'  => [ 'created_at', true ],
		];
	}

	/**
	 * Print column headers with nonce for sorting links.
	 *
	 * @param bool $with_id Whether to set the id attribute or not.
	 * @return void
	 */
	public function print_column_headers( $with_id = true ) {
		parent::print_column_headers( $with_id );

		// Add nonce to sorting links via JavaScript.
		$nonce = wp_create_nonce( 'wsww_spin_list_sort' );
		
		// Collect script content to be added via wp_add_inline_script().
		ob_start();
		?>
		(function() {
			var nonce = <?php echo wp_json_encode( $nonce ); ?>;
			var links = document.querySelectorAll( '.wp-list-table thead th.sortable a, .wp-list-table thead th.sorted a' );
			links.forEach( function( link ) {
				if ( link.href ) {
					try {
						var url = new URL( link.href, window.location.href );
						if ( url.searchParams.has( 'orderby' ) || url.searchParams.has( 'order' ) ) {
							url.searchParams.set( 'wsww_spin_list_sort_nonce', nonce );
							link.href = url.toString();
						}
					} catch ( e ) {
						// Fallback for older browsers.
						if ( link.href.indexOf( 'orderby' ) !== -1 || link.href.indexOf( 'order=' ) !== -1 ) {
							var separator = link.href.indexOf( '?' ) !== -1 ? '&' : '?';
							link.href = link.href + separator + 'wsww_spin_list_sort_nonce=' + encodeURIComponent( nonce );
						}
					}
				}
			});
		})();
		<?php
		$script_content = ob_get_clean();
		
		// Store script content to be added via wp_add_inline_script() in admin_footer.
		if ( class_exists( 'Webequipe_Spin_Win_Wheel_Admin' ) ) {
			Webequipe_Spin_Win_Wheel_Admin::add_admin_inline_script_content( $script_content );
		}
	}

	/**
	 * Define bulk actions.
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		return [
			'trash' => __( 'Move to Trash', 'webequipe-spin-win-wheel' ),
		];
	}

	/**
	 * Add top table controls (search) so controls stay on one line.
	 *
	 * @param string $which Table nav position.
	 * @return void
	 */
	public function extra_tablenav( $which ) {
		if ( 'top' !== $which ) {
			return;
		}

		$search_raw = filter_input( INPUT_GET, 's', FILTER_DEFAULT );
		$search_term = is_string( $search_raw ) ? sanitize_text_field( wp_unslash( $search_raw ) ) : '';
		?>
		<div class="alignleft actions wsww-spin-search">
			<label class="screen-reader-text" for="search-input-spin"><?php esc_html_e( 'Search Wheels', 'webequipe-spin-win-wheel' ); ?></label>
			<input type="search"
				id="search-input-spin"
				name="s"
				value="<?php echo esc_attr( $search_term ); ?>"
				placeholder="<?php esc_attr_e( 'Search by wheel name...', 'webequipe-spin-win-wheel' ); ?>" />
			<input type="submit" id="search-submit-spin" class="button" value="<?php esc_attr_e( 'Search', 'webequipe-spin-win-wheel' ); ?>" />
		</div>
		<?php
	}

	/**
	 * Default column rendering.
	 *
	 * @param object $item        The current item.
	 * @param string $column_name The name of the column.
	 * @return string
	 */
	protected function column_default( $item, $column_name ) {
		switch ( $column_name ) {
			case 'shortcode':
				return '<input type="text" class="shortcode-clipboard" value="[wsww-spin id=' . intval( $item->id ) . ']" readonly />';

			case 'spin_count':
				return $this->get_spin_count( $item->id );

			case 'spin_status':
				return $this->get_spin_status( $item->spin_status );

			case 'created_at':
				return esc_html(
					webequipe_sww_format_mysql_datetime_display(
						isset( $item->created_at ) ? $item->created_at : null
					)
				);

			default:
				return isset( $item->$column_name ) ? esc_html( $item->$column_name ) : '';
		}
	}

	/**
	 * Render the "spin_title" column with row actions.
	 *
	 * @param object $item The current item.
	 * @return string
	 */
	public function column_spin_title( $item ) {
		$actions = [];

		$actions['edit'] = sprintf(
			'<a href="%s">%s</a>',
			esc_url( wp_nonce_url( admin_url( 'admin.php?page=wsww-spin&action=edit&id=' . intval( $item->id ) ), 'wsww_spin_action' ) ),
			__( 'Edit', 'webequipe-spin-win-wheel' )
		);

		$actions['delete'] = sprintf(
			'<a href="%s" class="submitdelete" onclick="return confirm(\'%s\');">%s</a>',
			esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=wsww-spin-delete-spin&id=' . intval( $item->id ) ), 'wsww-spin-delete-spin' ) ),
			esc_js( __( 'Are you sure?', 'webequipe-spin-win-wheel' ) ),
			esc_html__( 'Delete', 'webequipe-spin-win-wheel' )
		);

		return sprintf(
			'<a href="%1$s"><strong>%2$s</strong></a> %3$s',
			esc_url( wp_nonce_url( admin_url( 'admin.php?page=wsww-spin&action=edit&id=' . intval( $item->id ) ), 'wsww_spin_action' ) ),
			esc_html( $item->spin_title ),
			$this->row_actions( $actions )
		);
	}

	/**
	 * Render checkbox column.
	 *
	 * @param object $item The current item.
	 * @return string
	 */
	protected function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="spin_id[]" value="%d" />',
			absint( $item->id )
		);
	}

	/**
	 * Define the primary column.
	 *
	 * @return string
	 */
	protected function get_primary_column_name() {
		return 'spin_title';
	}

	/**
	 * Get the number of times a spin has been used.
	 *
	 * @param int $spin_id Spin ID.
	 * @return int
	 */
	private function get_spin_count( $spin_id ) {
		global $wpdb;

		$cache_key   = 'wsww_spin_count_' . absint( $spin_id );
		$cache_group = 'webequipe-spin-win-wheel';

		$count = wp_cache_get( $cache_key, $cache_group );

		if ( false === $count ) {
			$count = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}spin_emails WHERE spin_id = %d",
					absint( $spin_id )
				)
			);

			wp_cache_set( $cache_key, $count, $cache_group, 600 );
		}

		return $count;
	}

	/**
	 * Format spin status for display.
	 *
	 * @param string $status Spin status.
	 * @return string
	 */
	private function get_spin_status( $status ) {
		$status_labels = [
			'active'   => '<span style="color: #00a32a; font-weight: bold;">' . __( 'Active', 'webequipe-spin-win-wheel' ) . '</span>',
			'inactive' => '<span style="color: #d63638; font-weight: bold;">' . __( 'Inactive', 'webequipe-spin-win-wheel' ) . '</span>',
		];

		return isset( $status_labels[ $status ] ) ? $status_labels[ $status ] : esc_html( $status );
	}

    /**
     * Prepare table items with pagination.
     *
     * @return void
     */
    public function prepare_items() {
        $columns  = $this->get_columns();
        $hidden   = [];
        $sortable = $this->get_sortable_columns();

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

        $per_page     = 20;
        $current_page = $this->get_pagenum();
        $offset       = ( $current_page - 1 ) * $per_page;

        $args = [
            'number' => $per_page,
            'offset' => $offset,
        ];

        // Verify nonce before processing sorting parameters.
        $has_valid_sort_nonce = isset( $_REQUEST['wsww_spin_list_sort_nonce'] )
            && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['wsww_spin_list_sort_nonce'] ) ), 'wsww_spin_list_sort' );

        if ( $has_valid_sort_nonce && isset( $_REQUEST['orderby'] ) ) {
            $requested_orderby = sanitize_key( wp_unslash( $_REQUEST['orderby'] ) );
            $allowed_orderby = array_keys( $sortable );
            if ( in_array( $requested_orderby, $allowed_orderby, true ) ) {
                $args['orderby'] = $requested_orderby;
            }
        }

        if ( $has_valid_sort_nonce && isset( $_REQUEST['order'] ) ) {
            $requested_order = strtolower( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) );
            $allowed_order = [ 'asc', 'desc' ];
            if ( in_array( $requested_order, $allowed_order, true ) ) {
                $args['order'] = $requested_order;
            }
        }

        // Fetch the spins with applied arguments.
        $this->items = webequipe_sww_get_spins( $args );

        // Setup pagination.
        $this->set_pagination_args(
            [
                'total_items' => webequipe_sww_spin_count(),
                'per_page'    => $per_page,
            ]
        );
    }

}
