<?php

namespace Storeplugin\PDFInvoice\Framework\ListTables;

defined('ABSPATH') || exit;

use Storeplugin\PDFInvoice\Config;
use Storeplugin\PDFInvoice\Asset;

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

class ListTable extends \WP_List_Table {
    private $config;
    private $dataSource;

    /**
     * Constructor.
     *
     * @param array             $config
     * @param DataSourceInterface $dataSource
     */
    public function __construct( $config, $dataSource ) {
        $this->config = $config;
        $this->dataSource = $dataSource;

        parent::__construct( [
            'singular' => $config['singular'],
            'plural'   => $config['plural'],
            'ajax'     => false,
        ] );
    }

    /**
     * Get table classes.
     *
     * @return array
     */
    public function get_table_classes() {
        if ( ! empty( $this->config['table_classes'] ) ) {
            return $this->config['table_classes'];
        }

        return [
            'widefat',
            'striped',
            'table-view-list',
            'nxtf-list-table',
        ];
    }

    /**
     * Get columns.
     *
     * @return array
     */
    public function get_columns() {
        $columns = [];

        // Add drag handle column if draggable is enabled
        if ( ! empty( $this->config['draggable_enabled'] ) ) {
            $handle_column = $this->config['draggable_config']['handle_column'] ?? 'drag_handle';
            if ( ! isset( $this->config['columns'][ $handle_column ] ) ) {
                $columns['drag_handle'] = '';
            }
        }

        // Add checkbox column if bulk actions exist
        if ( ! empty( $this->config['bulk_actions'] ) ) {
            $columns['cb'] = '<input type="checkbox" />';
        }

        // Add user-defined columns
        $columns = array_merge( $columns, $this->config['columns'] );

        return $columns;
    }

    /**
     * Get sortable columns.
     *
     * @return array
     */
    protected function get_sortable_columns() {
        return $this->config['sortable_columns'] ?? [];
    }

    /**
     * Get bulk actions.
     *
     * @return array
     */
    protected function get_bulk_actions() {
        return $this->config['bulk_actions'] ?? [];
    }

    /**
     * Generates and displays row action links.
     *
     * @param object $item        The current item.
     * @param string $column_name The name of the column to display.
     *
     * @return string
     */
    protected function column_default( $item, $columnName ) {
        // Check for custom renderer
        if ( isset( $this->config['column_renderers'][ $columnName ] ) ) {
            return call_user_func( $this->config['column_renderers'][ $columnName ], $item );
        }

        // Convert item to array if it's an object
        $itemArray = (array) $item;

        if ( ! isset( $itemArray[ $columnName ] ) ) {
            return '';
        }

        $value = $itemArray[ $columnName ];

        // Escape default output to prevent XSS; use a column renderer for HTML.
        if ( is_scalar( $value ) ) {
            return esc_html( (string) $value );
        }

        if ( is_object( $value ) && method_exists( $value, '__toString' ) ) {
            return esc_html( (string) $value );
        }

        if ( is_array( $value ) || is_object( $value ) ) {
            return esc_html( wp_json_encode( $value ) );
        }

        return '';
    }

    /**
     * Display the checkbox for a row.
     *
     * @param object $item The current item.
     *
     * @return string
     */
    protected function column_cb( $item ) {
        $itemArray = (array) $item;
        $id = $itemArray['id'] ?? $itemArray['ID'] ?? '';
        return sprintf( '<input type="checkbox" name="bulk-delete[]" value="%s" />', esc_attr( $id ) );
    }

    /**
     * Display the drag handle for a row.
     *
     * @param object $item The current item.
     *
     * @return string
     */
    protected function column_drag_handle( $item ) {
        return '<span class="nxtf-drag-handle dashicons dashicons-menu" style="cursor: move; color: #a0aec0;"></span>';
    }

    /**
     * Handle row actions.
     *
     * @param object $item
     * @param string $column_name
     * @param string $primary
     *
     * @return string
     */
    protected function handle_row_actions( $item, $columnName, $primary ) {
        if ( $columnName !== $primary ) {
            return '';
        }

        if ( empty( $this->config['row_actions_callback'] ) ) {
            return '';
        }

        $actions = call_user_func( $this->config['row_actions_callback'], $item );

        return $this->row_actions( $actions );
    }

    /**
     * Prepare items.
     */
    public function prepare_items() {
        $columns = $this->get_columns();
        $hidden = $this->config['hidden_columns'] ?? [];
        $sortable = $this->get_sortable_columns();
        $primary = $this->config['primary_column'] ?? array_key_first( $this->config['columns'] );

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

        // Handle bulk actions
        $this->process_bulk_action();

        // Get screen option for per_page
        $screen = get_current_screen();
        $screenOption = $screen->get_option( 'per_page', 'option' );
        $perPage = $this->config['per_page'] ?? 20;

        if ( $screenOption ) {
            $perPage = get_user_meta( get_current_user_id(), $screenOption, true );
            if ( empty( $perPage ) || $perPage < 1 ) {
                $perPage = $this->config['per_page'] ?? 20;
            }
        }

        $currentPage = $this->get_pagenum();

        $orderby = isset( $_REQUEST['orderby'] ) ? sanitize_key( wp_unslash( $_REQUEST['orderby'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $requestedOrder = isset( $_REQUEST['order'] ) ? sanitize_key( wp_unslash( $_REQUEST['order'] ) ) : 'asc'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $order = in_array( $requestedOrder, [ 'asc', 'desc' ], true ) ? $requestedOrder : 'asc';
        $search = isset( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

        $this->items = $this->dataSource->getItems( $perPage, $currentPage, $orderby, $order, $search );
        $totalItems = $this->dataSource->getTotalItems( $search );

        $this->set_pagination_args( [
            'total_items' => $totalItems,
            'per_page'    => $perPage,
            'total_pages' => ceil( $totalItems / $perPage ),
        ] );
    }

    /**
     * Get views.
     *
     * @return array
     */
    protected function get_views() {
        return $this->dataSource->getViews();
    }

    /**
     * Process bulk actions submitted from the list table.
     */
    protected function process_bulk_action(): void {
        $action = $this->current_action();
        $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';
        $action2 = isset( $_REQUEST['action2'] ) ? sanitize_key( wp_unslash( $_REQUEST['action2'] ) ) : '';

        if ( ! $action && '' !== $action2 && '-1' !== $action2 ) {
            $action = $action2;
        }

        if ( ! $action ) {
            return;
        }

        if ( ! $nonce || ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
            return;
        }

        if ( ! isset( $_REQUEST['bulk-delete'] ) || ! is_array( $_REQUEST['bulk-delete'] ) || empty( $_REQUEST['bulk-delete'] ) ) {
            return;
        }

        $ids = array_map( 'intval', wp_unslash( $_REQUEST['bulk-delete'] ) );
        $ids = array_values( array_filter( $ids, function( $id ) {
            return $id > 0;
        } ) );

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

        // Handle bulk action callbacks
        if ( isset( $this->config['bulk_action_handlers'][ $action ] ) ) {
            call_user_func( $this->config['bulk_action_handlers'][ $action ], $ids );
            wp_safe_redirect( remove_query_arg( ['action', 'action2', '_wpnonce', '_wp_http_referer'] ) );
            exit;
        }

        // Default delete action
        if ( $action === 'delete' ) {
            $this->dataSource->deleteItems( $ids );
            wp_safe_redirect( remove_query_arg( ['action', 'action2', '_wpnonce', '_wp_http_referer'] ) );
            exit;
        }
    }

    /**
     * Display a message when no items are found.
     */
    public function no_items() {
        esc_html_e( 'No items found.', 'storeinvoice-print-pdf-invoices-and-packing-slips' );
    }

    /**
     * Display the table with draggable attributes if enabled.
     */
    public function display() {
        $singular = $this->_args['singular'];
        $draggableEnabled = ! empty( $this->config['draggable_enabled'] );
        $tableId = '';
        $draggableNonce = '';
        $draggableAction = '';

        $this->display_tablenav( 'top' );

        $this->screen->render_screen_reader_content( 'heading_list' );

        if ( $draggableEnabled ) {
            Asset::registerFrameworkAssets();
            $tableId = $this->config['menu_slug'] ?? '';
            $draggableNonce = wp_create_nonce( Config::nonce('draggable') );
            $draggableAction = Config::ajax('update_table_order');

            // Enqueue draggable scripts (styles are in framework.css)
            wp_enqueue_script( 'sortablejs' );
            wp_enqueue_script( Config::asset('draggable') );
        }

        $tableClasses = implode( ' ', $this->get_table_classes() );
        $wpListsValue = $singular ? 'list:' . $singular : '';
        ?>
        <table
            class="wp-list-table <?php echo esc_attr( $tableClasses ); ?>"
            <?php if ( $draggableEnabled ) : ?>
                data-draggable="true"
                data-table-id="<?php echo esc_attr( $tableId ); ?>"
                data-nonce="<?php echo esc_attr( $draggableNonce ); ?>"
                data-ajax-action="<?php echo esc_attr( $draggableAction ); ?>"
            <?php endif; ?>
        >
            <thead>
            <tr>
                <?php $this->print_column_headers(); ?>
            </tr>
            </thead>

            <tbody id="the-list"<?php if ( '' !== $wpListsValue ) : ?> data-wp-lists="<?php echo esc_attr( $wpListsValue ); ?>"<?php endif; ?>>
                <?php $this->display_rows_or_placeholder(); ?>
            </tbody>

            <tfoot>
            <tr>
                <?php $this->print_column_headers( false ); ?>
            </tr>
            </tfoot>

        </table>
        <?php
        $this->display_tablenav( 'bottom' );
    }

    /**
     * Generate the table rows with item IDs as data attributes.
     *
     * @param object|array $item
     */
    public function single_row( $item ) {
        $itemArray = (array) $item;
        $id = $itemArray['id'] ?? $itemArray['ID'] ?? '';

        echo '<tr data-item-id="' . esc_attr( $id ) . '">';
        $this->single_row_columns( $item );
        echo '</tr>';
    }
}
