<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

/********************************************************************
 * Copyright (C) 2025 Upvimeo.com (https://upvimeo.com)
 *
 * This file is part of Upvimeo
 *
 * Upvimeo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * Upvimeo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Upvimeo. If not, see <https://www.gnu.org/licenses/>.
 **********************************************************************/

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

/**
 * Class UpVimeo_List_Table
 *
 * Responsible for displaying the admin table
 *
 * @license GPLv2
 * @copyright Upvimeo.com (https://upvimeo.com)
 * @since 1.0.0
 */
class UpVimeo_List_Table extends \WP_List_Table
{

	/**
	 * Is authors only
	 * @var int
	 */
	protected $author_uploads_only;

	/**
	 * @var UpVimeo_Settings_Helper
	 */
	protected $settings_helper;

	/**
	 * @var UpVimeo_Db_Helper
	 */
	protected $db_helper;

	/**
	 * @var UpVimeo_Api_Helper
	 */
	protected $api_helper;

	/**
	 * @var UpVimeo_Logger
	 */
	protected $logger;

	/**
	 * @var UpVimeo_Flash
	 */
	protected $flash;

	/**
	 * Enable or disable local pages for videos
	 * @var bool
	 */
	protected $front_pages;

	/**
	 * Thumbnails support
	 * @var
	 */
	protected $thumbs_support;

	/**
	 * The log tag
	 * @var string
	 */
	protected $logtag = 'upvimeo-ADMIN-LIST';

	/**
	 * Has description enabled
	 * @var bool
	 */
	protected $show_description = false;

	/**
	 * Show link instead of shortcode
	 * @var bool
	 */
	protected $show_link = false;

	/**
	 * The page status
	 * @var
	 */
	protected $page_status;

	/**
	 * UpVimeo_List_Table constructor.
	 */
	public function __construct()
	{
		parent::__construct(array(
			'singular' => 'video',
			'plural' => 'videos',
			'ajax' => false
		));
		$this->settings_helper = new UpVimeo_Settings_Helper();
		$this->author_uploads_only = (int) $this->settings_helper->get('UPVIMEO_author_uploads_only');

		$user = wp_get_current_user();
		if (isset($user->roles) && in_array('administrator', (array) $user->roles)) {
			$this->author_uploads_only = 0;
		}

		$this->db_helper = new UpVimeo_Db_Helper();
		$this->api_helper = new UpVimeo_Api_Helper();
		$this->logger = new UpVimeo_Logger();
		$this->flash = new UpVimeo_Flash();
		$this->show_description = UpVimeo_Admin_Screen_Options::get_option('description') === 'on' ? true : false;
		$this->show_link = UpVimeo_Admin_Screen_Options::get_option('link_insteadof_shortcode') === 'on' ? true : false;

		$this->front_pages = (int) $this->settings_helper->get('UPVIMEO_enable_single_pages');
		$this->thumbs_support = (int) $this->settings_helper->get('UPVIMEO_exp_thumbs_support');
	}


	public function get_table_classes()
	{
		return array('widefat', 'fixed', 'striped', $this->_args['plural']);
	}

	/**
	 * Message to show if no designation found
	 *
	 * @return void
	 */
	public function no_items()
	{
		esc_html_e('No videos found', 'upvimeo-direct-uploads');
	}

	/**
	 * Default column values if no callback found
	 *
	 * @param  object  $item
	 * @param  string  $column_name
	 *
	 * @return string
	 */
	public function column_default($item, $column_name)
	{

		// Remote Item
		if (isset($item->uri)) {
			switch ($column_name) {
				case 'embed':
					return '-'; // Or a generated embed code?
				case 'author':
					return '-'; // API user?
				case 'size':
					// Try to find size in upload data or stats
					return '-';
				case 'duration':
					$seconds = isset($item->duration) ? (int) $item->duration : 0;
					return gmdate(($seconds > 3600 ? 'H:i:s' : 'i:s'), $seconds);
				case 'uploaded_at':
					return date_i18n(get_option('date_format'), strtotime($item->created_time));
				default:
					return isset($item->$column_name) ? $item->$column_name : '';
			}
		}

		switch ($column_name) {
			case 'embed':
				if (!$this->show_link) {
					$vimeo_id = $this->db_helper->get_vimeo_id($item->ID);

					return '<code class="embed-code">[upvimeo_video id="' . $vimeo_id . '"]</code>' . sprintf('<span class="upvimeo-copy-embed-code dashicons dashicons-admin-links" title="%s"></span>', esc_html__('Copy to clipboard', 'upvimeo-direct-uploads'));
				} else {
					$link = $this->db_helper->get_vimeo_link($item->ID);

					return sprintf('<code class="embed-code">%s</code> <span class="upvimeo-copy-embed-code dashicons dashicons-admin-links" title="%s"></span>', $link, esc_html__('Copy to clipboard', 'upvimeo-direct-uploads'));
				}
			case 'author':
				return upvimeo_get_user_edit_link($item->post_author);
			case 'size':
				$size = get_post_meta($item->ID, 'UPVIMEO_size', true);

				return is_numeric($size) ? upvimeo_format_bytes($size) : esc_html__('Not available', 'upvimeo-direct-uploads');
			case 'uploaded_at':
				return get_the_date(get_option('date_format'), $item);
			default:
				return isset($item->$column_name) ? $item->$column_name : '';
		}
	}

	/**
	 * Get the column names
	 *
	 * @return array
	 */
	public function get_columns()
	{
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$type = isset($_GET['type']) ? sanitize_text_field(wp_unslash($_GET['type'])) : 'local';

		if ($type === 'vimeo') {
			return [
				'cb' => '<input type="checkbox" />',
				'image' => esc_html__('Image', 'upvimeo-direct-uploads'),
				'title' => esc_html__('Title', 'upvimeo-direct-uploads'),
				'duration' => esc_html__('Duration', 'upvimeo-direct-uploads'),
				'privacy' => esc_html__('Privacy', 'upvimeo-direct-uploads'),
				'uploaded_at' => esc_html__('Uploaded', 'upvimeo-direct-uploads'),
			];
		}

		$columns = array(
			'cb' => '<input type="checkbox" />',
		);
		$columns['title'] = esc_html__('Title', 'upvimeo-direct-uploads');
		$columns['embed'] = esc_html__('Embed', 'upvimeo-direct-uploads');
		$columns['author'] = esc_html__('Author', 'upvimeo-direct-uploads');
		$columns['size'] = esc_html__('Size', 'upvimeo-direct-uploads');
		$columns['uploaded_at'] = esc_html__('Uploaded', 'upvimeo-direct-uploads');

		return $columns;
	}

	/**
	 * Render the designation name column
	 *
	 * @param  object  $item
	 *
	 * @return string
	 */
	public function column_title($item)
	{
		// Check if it's a remote video
		if (isset($item->uri)) {
			return $this->column_title_remote($item);
		}

		$actions = array();
		$can_delete = $this->api_helper->can_delete() ? 1 : 0;
		$vimeo_uri = $this->db_helper->get_vimeo_uri($item->ID);
		$vimeo_id = $this->db_helper->get_vimeo_id($item->ID);
		$url_vimeo = $this->db_helper->get_vimeo_link($item->ID);
		$url_edit = admin_url('admin.php?page=' . UpVimeo_Admin::PAGE_EDIT . '&id=' . $item->ID);
		$url_edit = wp_nonce_url($url_edit, 'upvimeo_action', 'upvimeo_nonce');
		$url_local = get_permalink($item->ID);

		$actions['edit'] = sprintf('<a href="%s" data-id="%d" title="%s">%s</a>', $url_edit, $item->ID, esc_html__('Manage this video', 'upvimeo-direct-uploads'), esc_html__('Manage', 'upvimeo-direct-uploads'));
		$actions['vimeo'] = sprintf('<a href="%s" target="_blank" data-id="%d" title="%s">%s</a>', $url_vimeo, $item->ID, esc_html__('Vimeo video link', 'upvimeo-direct-uploads'), esc_html__('Vimeo Link', 'upvimeo-direct-uploads'));
		if ($this->front_pages) {
			$actions['view'] = sprintf('<a href="%s" data-id="%d" title="%s">%s</a>', $url_local, $item->ID, esc_html__('View the video on the front-end', 'upvimeo-direct-uploads'), esc_html__('View', 'upvimeo-direct-uploads'));
		}

		$delete_cap = apply_filters('UPVIMEO_vimeo_cap_delete', 'delete_posts');
		if (current_user_can($delete_cap)) {
			$actions['delete'] = sprintf('<a href="#" class="submitdelete upvimeo-delete" data-vimeo-uri="%s"  data-can-delete="%d" data-id="%d" title="%s">%s</a>', $vimeo_uri, $item->ID, $can_delete, esc_html__('Delete video from vimeo', 'upvimeo-direct-uploads'), esc_html__('Delete', 'upvimeo-direct-uploads'));
		}

		$thumbnail = '';
		$thumbnail_class = '';

		if (!empty($vimeo_id) && $this->thumbs_support) {
			$thumb_url = upvimeo_get_thumbnail($item->ID);
			if (!empty($thumb_url)) {
				$thumbnail_class = 'wvv-thumb-link';
				$thumbnail = '<img src="' . esc_url($thumb_url) . '"/>';
			}
		}

		$description = '';
		if ($this->show_description) {
			$description = wp_trim_words($item->post_content, 30);
		}

		return sprintf(
			'<a class="%s" href="%s">%s<strong>%s</strong></a> %s %s',
			esc_attr($thumbnail_class),
			esc_url($url_edit),
			$thumbnail,
			esc_html($item->post_title),
			esc_html($description),
			$this->row_actions($actions)
		);
	}

	/**
	 * Render Image Column
	 * @param $item
	 * @return string
	 */
	public function column_image($item)
	{
		$thumbnail_html = '';
		if (isset($item->pictures) && isset($item->pictures['sizes'])) {
			$thumb = end($item->pictures['sizes']);
			if (isset($item->pictures['sizes'][2])) { // 295w or something similar
				$thumb = $item->pictures['sizes'][2];
			} elseif (isset($item->pictures['sizes'][1])) {
				$thumb = $item->pictures['sizes'][1];
			}

			if (isset($thumb['link'])) {
				$thumbnail_html = sprintf(
					'<div class="upvimeo-remote-video-thumb">
						<img src="%s" alt="%s">
						<div class="upvimeo-play-overlay">
							<div class="upvimeo-play-icon"></div>
						</div>
					</div>',
					esc_url($thumb['link']),
					esc_attr($item->name)
				);
			}
		} else {
			$thumbnail_html = '<div class="upvimeo-remote-video-thumb" style="background:#333;"></div>';
		}

		return $thumbnail_html;
	}

	/**
	 * Render Privacy Column
	 * @param $item
	 * @return string
	 */
	public function column_privacy($item)
	{
		$privacy = isset($item->privacy) && isset($item->privacy['view']) ? $item->privacy['view'] : 'anybody';
		$label = ucfirst($privacy);
		$icon = 'dashicons-visibility';

		if ($privacy === 'disable') {
			$icon = 'dashicons-hidden';
			$label = esc_html__('Private', 'upvimeo-direct-uploads');
		} elseif ($privacy === 'nobody') {
			$icon = 'dashicons-lock';
			$label = esc_html__('Only Me', 'upvimeo-direct-uploads');
		} elseif ($privacy === 'password') {
			$icon = 'dashicons-privacy';
		}

		return sprintf('<span class="upvimeo-privacy-badge"><span class="dashicons %s"></span> %s</span>', $icon, $label);
	}

	/**
	 * Render the remote video title column
	 *
	 * @param  object  $item
	 *
	 * @return string
	 */
	public function column_title_remote($item)
	{
		$actions = array();
		$vimeo_uri = $item->uri;
		$vimeo_id = str_replace('/videos/', '', $vimeo_uri);
		$url_vimeo = $item->link;

		// Check import status
		$is_imported = false;
		$existing_post_id = $this->db_helper->get_post_id($vimeo_id);

		if ($existing_post_id) {
			$is_imported = true;
		}

		if (!$is_imported) {
			// Import Action
			$actions['import'] = sprintf(
				'<a href="#" class="upvimeo-import-video" data-vimeo-id="%s" data-vimeo-uri="%s" data-title="%s" data-duration="%s" data-width="%s" data-height="%s" title="%s">%s</a>',
				esc_attr($vimeo_id),
				esc_attr($vimeo_uri),
				esc_attr($item->name),
				esc_attr($item->duration),
				esc_attr($item->width),
				esc_attr($item->height),
				esc_html__('Import this video to WordPress', 'upvimeo-direct-uploads'),
				esc_html__('Import', 'upvimeo-direct-uploads')
			);
		}

		$actions['vimeo'] = sprintf('<a href="%s" target="_blank" title="%s">%s</a>', $url_vimeo, esc_html__('Vimeo video link', 'upvimeo-direct-uploads'), esc_html__('Vimeo Link', 'upvimeo-direct-uploads'));

		$status_badge = '';
		if ($is_imported) {
			$status_badge = sprintf('<span class="upvimeo-badge-imported"><span class="dashicons dashicons-yes" style="font-size:14px;width:14px;height:14px;vertical-align:middle;"></span> %s</span>', esc_html__('Imported', 'upvimeo-direct-uploads'));
		}

		return sprintf(
			'<a class="upvimeo-remote-title" href="%s" target="_blank">%s</a> %s <div class="upvimeo-remote-meta">%s</div> %s',
			esc_url($url_vimeo),
			esc_html($item->name),
			$status_badge,
			'',
			$this->row_actions($actions)
		);
	}

	/**
	 * Get sortable columns
	 *
	 * @return array
	 */
	public function get_sortable_columns()
	{
		$sortable_columns = array();

		return $sortable_columns;
	}

	/**
	 * Set the bulk actions
	 *
	 * @return array
	 */
	public function get_bulk_actions()
	{
		$actions = array(
			'delete' => esc_html__('Delete', 'upvimeo-direct-uploads'),
		);

		return $actions;
	}

	/**
	 * Render the checkbox column
	 *
	 * @param  object  $item
	 *
	 * @return string
	 */
	public function column_cb($item)
	{
		$id = isset($item->ID) ? $item->ID : (isset($item->uri) ? $item->uri : 0);
		return sprintf(
			'<input type="checkbox" name="record_id[]" value="%s" />',
			$id
		);
	}

	/**
	 * The views
	 * @return array
	 */
	protected function get_views()
	{
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$current = isset($_GET['type']) ? sanitize_text_field(wp_unslash($_GET['type'])) : 'local';
		return [
			'local' => sprintf('<a class="%s" href="%s">%s</a>', $current === 'local' ? 'current' : '', add_query_arg(['type' => null], admin_url('admin.php?page=' . UpVimeo_Admin::PAGE_VIMEO)), esc_html__('Local', 'upvimeo-direct-uploads')),
			'vimeo' => sprintf('<a class="%s" href="%s">%s</a>', $current === 'vimeo' ? 'current' : '', add_query_arg(['type' => 'vimeo'], admin_url('admin.php?page=' . UpVimeo_Admin::PAGE_VIMEO)), esc_html__('Vimeo (Remote)', 'upvimeo-direct-uploads')),
		];
	}

	/**
	 * Prepare the class items
	 *
	 * @return void
	 */
	public function prepare_items()
	{

		$this->process_bulk_actions();

		global $wp_query;

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

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$type = isset($_GET['type']) ? sanitize_text_field(wp_unslash($_GET['type'])) : 'local';

		if ($type === 'vimeo') {
			$query = [
				'page' => $current_page,
				'per_page' => $per_page,
				'sort' => 'date',
				'direction' => 'desc',
			];
			// API Call
			$data = null;
			try {
				$data = $this->api_helper->get_my_videos($query);
			} catch (\Vimeify\Vimeo\Exceptions\VimeoRequestException $e) {
				// Log error or just show empty list
				// Error message could be passed to view but for now just empty list
			}

			$this->items = [];
			if ($data && isset($data['results']) && is_array($data['results'])) {
				foreach ($data['results'] as $row) {
					$this->items[] = (object) $row;
				}
			}

			$total_items = isset($data['paging']['total']) ? $data['paging']['total'] : 0;

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

			return;
		}

		// Local Items (Fallback)
		$offset = ($current_page - 1) * $per_page;
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$this->page_status = isset($_GET['status']) ? sanitize_text_field(wp_unslash($_GET['status'])) : '2';

		$args = array(
			'offset' => $offset,
			'number' => $per_page,
		);

		if ($this->author_uploads_only && !current_user_can('administrator')) {
			$args['author'] = get_current_user_id();
		} else {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$filter_author_ID = isset($_REQUEST['author']) ? absint(wp_unslash($_REQUEST['author'])) : 0;
			if ($filter_author_ID > 0) {
				$args['author'] = $filter_author_ID;
			}
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!empty($_REQUEST['s'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $args['s'] = sanitize_text_field(wp_unslash($_REQUEST['s']));
        }

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (isset($_REQUEST['orderby']) && isset($_REQUEST['order'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $args['orderby'] = sanitize_text_field(wp_unslash($_REQUEST['orderby']));
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $args['order'] = sanitize_text_field(wp_unslash($_REQUEST['order']));
        }
		$wp_query = $this->db_helper->get_videos($args, 'query');
		$this->items = $wp_query->get_posts();

		$this->set_pagination_args(array(
			'total_items' => $wp_query->found_posts,
			'per_page' => $per_page,
		));
	}

	/**
	 * Extra controls to be displayed between bulk actions and pagination
	 *
	 * @param  string  $which
	 *
	 * @since 3.1.0
	 *
	 */
	protected function extra_tablenav($which)
	{
		if ($which == "top") {
?>

			<?php if (!$this->author_uploads_only): ?>
				<div class="alignleft actions bulkactions">
					<?php
					$filter_author = false;
					// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        			$filter_author_ID = isset($_REQUEST['author']) ? absint(wp_unslash($_REQUEST['author'])) : 0;
					if ($filter_author_ID) {
						$filter_author = get_user_by('id', $filter_author_ID);
					}
					?>
					<div class="alignleft actions">
						<label class="screen-reader-text" for="author"><?php esc_html_e('Filter by author', 'upvimeo-direct-uploads'); ?></label>
						<select name="author" id="author" class="postform upvimeo-select2 upvimeo-select2-clearable"
							data-action="UPVIMEO_user_search" data-placeholder="<?php esc_html_e('Filter by author', 'upvimeo-direct-uploads'); ?>">
							<?php if (!empty($filter_author)): ?>
								<option selected value="<?php echo esc_attr($filter_author->ID); ?>">
									<?php echo esc_html($filter_author->display_name); ?>
								</option>
							<?php endif; ?>
						</select>
						<button type="submit" name="filter_action" id="post-query-submit" value="Filter"
							class="button"><?php esc_html_e('Filter', 'upvimeo-direct-uploads'); ?></button>
						<a href="" class="upvimeo-clear-selection" data-target=".upvimeo-select2-clearable"
							style="<?php echo esc_attr($filter_author ? '' : 'display:none;'); ?>"><?php esc_html_e('Clear', 'upvimeo-direct-uploads'); ?></a>
					</div>
				</div>
			<?php endif; ?>

<?php
		}
	}

	/**
	 * Process the bulk actions
	 */
	protected function process_bulk_actions()
	{

		$action = $this->current_action();

		if ( empty( $action ) || '-1' === $action ) {
			return;
		}

		$capabilities = array('delete' => apply_filters('UPVIMEO_vimeo_cap_delete', 'delete_posts'));
		$capability = isset($capabilities[$action]) ? $capabilities[$action] : 'delete_posts';

		if ( ! current_user_can( $capability ) ) {
			wp_die( esc_html__( "Permission denied. You don't have access to perform this action.", 'upvimeo-direct-uploads' ), esc_html__( 'Error', 'upvimeo-direct-uploads' ) );
		}

		// security check!
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash($_REQUEST['_wpnonce']) ) : '';
		$action_name = 'bulk-' . $this->_args['plural'];
		if ( ! wp_verify_nonce( $nonce, $action_name ) ) {
			wp_die( esc_html__( "Permission denied. Security check failed.", 'upvimeo-direct-uploads' ), esc_html__( 'Error', 'upvimeo-direct-uploads' ) );
		}
		$countV = 0;
		$countD = 0;
		switch ($action) {
			case 'delete':
				if (!$this->api_helper->can_delete()) {
					$signature = $this->flash->flash_message(esc_html__('Unable to delete video(s). The required Vimeo API scope "delete" is missing.', 'upvimeo-direct-uploads'), 'error');
					wp_safe_redirect($this->flash->get_current_url($signature));
					exit;
				}
				// phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$records = isset($_REQUEST['record_id']) ? array_map('sanitize_text_field', wp_unslash((array) $_REQUEST['record_id'])) : array();
				foreach ($records as $record) {
					$vimeo_uri = $this->db_helper->get_vimeo_uri($record);
					if (!empty($vimeo_uri)) {

						try {
							$response = $this->api_helper->delete($vimeo_uri);
							usleep(100000);
							$this->logger->log('Delete response: ', $this->logtag);
							$this->logger->log($response, $this->logtag);
							$this->logger->log(sprintf('Remote video %s deleted', $vimeo_uri), $this->logtag);
							$countV++;
						} catch (\Vimeify\Vimeo\Exceptions\VimeoRequestException $e) {
							$this->logger->log(sprintf('Unable to delete remote video %s. (Error: %s)', $vimeo_uri, $e->getMessage()), $this->logtag);
						}
					}
					if (wp_delete_post($record, true)) {
						$this->logger->log(sprintf('Local video %s deleted', $record), $this->logtag);
						$countD++;
					}
				}
				if ($countD > 0 || $countV > 0) {
					$signature = $this->flash->flash_message(esc_html__('Video(s) deleted successfully.', 'upvimeo-direct-uploads'), 'success');
				} else {
					$signature = $this->flash->flash_message(esc_html__('Unable to delete video(s)', 'upvimeo-direct-uploads'), 'error');
				}

				$url = $this->flash->get_current_url($signature);
				wp_safe_redirect($url);
				exit;
		}

		return;
	}
}
