<?php

declare(strict_types=1);

namespace GatoGraphQL\GatoGraphQL\Log\Controllers\FileHandler;

use GatoGraphQL\GatoGraphQL\Log\Controllers\PageController;
use GatoGraphQL\GatoGraphQL\PluginApp;
use WP_List_Table;

/**
 * @phpcs:ignoreFile
 * 
 * FileListTable class.
 */
class FileListTable extends WP_List_Table
{
    /**
     * The user option key for saving the preferred number of files displayed per page.
     *
     * @const string
     */
    public const PER_PAGE_USER_OPTION_KEY = 'logging_file_list_per_page';

    /**
     * Instance of FileController.
     *
     * @var FileController
     */
    private $file_controller;

    /**
     * Instance of PageController.
     *
     * @var PageController
     */
    private $page_controller;

    /**
     * FileListTable class.
     *
     * @param FileController $file_controller Instance of FileController.
     * @param PageController $page_controller Instance of PageController.
     */
    public function __construct(FileController $file_controller, PageController $page_controller)
    {
        $this->file_controller = $file_controller;
        $this->page_controller = $page_controller;

        parent::__construct(
            array(
                'singular' => 'log-file',
                'plural'   => 'log-files',
                'ajax'     => false,
            )
        );
    }

    /**
     * Render message when there are no items.
     *
     * @return void
     */
    public function no_items(): void
    {
        esc_html_e('No log files found.', 'gatographql');
    }

    /**
     * Retrieves the list of bulk actions available for this table.
     *
     * @return array
     */
    protected function get_bulk_actions(): array
    {
        return array(
            'export' => esc_html__('Download', 'gatographql'),
            'delete' => esc_html__('Delete permanently', 'gatographql'),
        );
    }

    /**
     * Get the existing log sources for the filter dropdown.
     *
     * @return array
     */
    protected function get_sources_list(): array
    {
        $sources = $this->file_controller->get_file_sources();
        if (is_wp_error($sources)) {
            return array();
        }

        sort($sources);

        return $sources;
    }

    /**
     * Displays extra controls between bulk actions and pagination.
     *
     * @param string $which The location of the tablenav being rendered. 'top' or 'bottom'.
     *
     * @return void
     */
    protected function extra_tablenav($which): void
    {
        $all_sources = $this->get_sources_list();

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Recommended
        $current_source = File::sanitize_source(wp_unslash($_GET['source'] ?? ''));

        ?>
        <div class="alignleft actions">
            <?php if ('top' === $which) : ?>
                <label for="filter-by-source" class="screen-reader-text"><?php esc_html_e('Filter by log source', 'gatographql'); ?></label>
                <select name="source" id="filter-by-source">
                    <option<?php selected($current_source, ''); ?> value=""><?php esc_html_e('All sources', 'gatographql'); ?></option>
                    <?php foreach ($all_sources as $source) : ?>
                        <option<?php selected($current_source, $source); ?> value="<?php echo esc_attr($source); ?>">
                            <?php echo esc_html($source); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
                <?php
                submit_button(
                    __('Filter', 'gatographql'),
                    '',
                    'filter_action',
                    false,
                    array(
                        'id' => 'logs-filter-submit',
                    )
                );
                ?>
            <?php endif; ?>
        </div>
        <?php
    }

    /**
     * Set up the column header info.
     *
     * @return void
     */
    public function prepare_column_headers(): void
    {
        $this->_column_headers = array(
            $this->get_columns(),
            get_hidden_columns($this->screen),
            $this->get_sortable_columns(),
            $this->get_primary_column(),
        );
    }

    /**
     * Prepares the list of items for displaying.
     *
     * @return void
     */
    public function prepare_items(): void
    {
        $per_page = $this->get_items_per_page(
            $this->getPerPageUserOptionKey(),
            $this->get_per_page_default()
        );

        $defaults  = array(
            'per_page' => $per_page,
            'offset'   => ( $this->get_pagenum() - 1 ) * $per_page,
        );
        $file_args = wp_parse_args(
            $this->page_controller->get_query_params(array( 'order', 'orderby', 'source' )),
            $defaults
        );

        $total_items = $this->file_controller->get_files($file_args, true);
        if (is_wp_error($total_items)) {
            printf(
                '<div class="notice notice-warning"><p>%s</p></div>',
                esc_html($total_items->get_error_message())
            );

            return;
        }

        $total_pages = ceil($total_items / $per_page);
        $items       = $this->file_controller->get_files($file_args);

        $this->items = $items;

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

    /**
     * Gets a list of columns.
     *
     * @return array
     */
    public function get_columns(): array
    {
        $columns = array(
            'cb'       => '<input type="checkbox" />',
            'source'   => esc_html__('Source', 'gatographql'),
            'created'  => esc_html__('Date created', 'gatographql'),
            'modified' => esc_html__('Date modified', 'gatographql'),
            'size'     => esc_html__('File size', 'gatographql'),
        );

        return $columns;
    }

    /**
     * Gets a list of sortable columns.
     *
     * @return array
     */
    protected function get_sortable_columns(): array
    {
        $sortable = array(
            'source'   => array( 'source' ),
            'created'  => array( 'created' ),
            'modified' => array( 'modified', true ),
            'size'     => array( 'size' ),
        );

        return $sortable;
    }

    /**
     * Render the checkbox column.
     *
     * @param File $item The current log file being rendered.
     *
     * @return string
     */
    public function column_cb($item): string
    {
        ob_start();
        ?>
        <input
            id="cb-select-<?php echo esc_attr($item->get_file_id()); ?>"
            type="checkbox"
            name="file_id[]"
            value="<?php echo esc_attr($item->get_file_id()); ?>"
        />
        <label for="cb-select-<?php echo esc_attr($item->get_file_id()); ?>">
            <span class="screen-reader-text">
                <?php
                printf(
                    // translators: 1. a date, 2. a slug-style name for a file.
                    esc_html__('Select the %1$s log file for %2$s', 'gatographql'),
                    esc_html(gmdate(get_option('date_format'), $item->get_created_timestamp())),
                    esc_html($item->get_source())
                );
                ?>
            </span>
        </label>
        <?php
        return ob_get_clean();
    }

    /**
     * Render the source column.
     *
     * @param File $item The current log file being rendered.
     *
     * @return string
     */
    public function column_source($item): string
    {
        $log_file        = $item->get_file_id();
        $single_file_url = add_query_arg(
            array(
                'view'    => 'single_file',
                'file_id' => $log_file,
            ),
            $this->page_controller->get_logs_tab_url()
        );
        $rotation        = '';
        if (! is_null($item->get_rotation())) {
            $rotation = sprintf(
                ' &ndash; <span class="post-state">%d</span>',
                $item->get_rotation()
            );
        }

        return sprintf(
            '<a class="row-title" href="%1$s">%2$s</a>%3$s',
            esc_url($single_file_url),
            esc_html($item->get_source()),
            $rotation
        );
    }

    /**
     * Render the created column.
     *
     * @param File $item The current log file being rendered.
     *
     * @return string
     */
    public function column_created($item): string
    {
        $timestamp = $item->get_created_timestamp();

        return gmdate('Y-m-d', $timestamp);
    }

    /**
     * Render the modified column.
     *
     * @param File $item The current log file being rendered.
     *
     * @return string
     */
    public function column_modified($item): string
    {
        $timestamp = $item->get_modified_timestamp();

        return gmdate('Y-m-d H:i:s', $timestamp);
    }

    /**
     * Render the size column.
     *
     * @param File $item The current log file being rendered.
     *
     * @return string
     */
    public function column_size($item): string
    {
        $size = $item->get_file_size();

        return size_format($size);
    }

    /**
     * Helper to get the default value for the per_page arg.
     *
     * @return int
     */
    public function get_per_page_default(): int
    {
        return $this->file_controller::DEFAULTS_GET_FILES['per_page'];
    }

    /**
     * Get the user option key for saving the preferred number of files displayed per page.
     *
     * @return string
     */
    public function getPerPageUserOptionKey(): string
    {
        $pluginNamespace = PluginApp::getMainPlugin()->getPluginNamespace();
        return $pluginNamespace . '_' . self::PER_PAGE_USER_OPTION_KEY;
    }
}
