<?php

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

class PrimerPaymentsPage extends WP_List_Table {

    public function __construct() {
        parent::__construct(array(
                'singular' => 'payment',
                'plural'   => 'payments',
                'ajax'     => false
        ));
    }

    function handle_main_primer_payments_admin_menu() {
        do_action('primer_payments_menu_start');
        $payments            = get_piraeusbank_transactions();
        $processed_order_ids = array();

        wp_enqueue_script('jquery');

        $search_query = isset($_GET['order_search']) ? sanitize_text_field($_GET['order_search']) : '';

        $orders_data = array();
        foreach ($payments as $payment) {
            $order_id = $payment['order_id'];
            if (in_array($order_id, $processed_order_ids)) {
                continue;
            }
            $order = wc_get_order($order_id);
            if ($order) {
                $receipt_id      = $order->get_meta('order_id_from_receipt');
                $tickets_display = $order->get_transaction_id();
                $refund_total    = array();
                $refunds         = $order->get_refunds();

                if (!empty($search_query)) {
                    $order_number = $order->get_order_number();
                    if ((string)$order_id !== $search_query && $order_number !== $search_query) {
                        continue;
                    }
                }

                $peiraeus_refunds = $order->get_meta('_piraeus_refunds', true);
                if (!empty($peiraeus_refunds) && is_array($peiraeus_refunds)) {
                    $refund_messages = array();
                    foreach ($peiraeus_refunds as $refund) {
                        if (!is_array($refund) || !isset($refund['amount'])) {
                            continue;
                        }
                        $refund_messages[] = sprintf(__('Refunded amount: %1$s <br>Date: %2$s<br>Transaction ID: %3$s <br>Trace ID: %4$s', 'primer'),
                                wc_price($refund['amount'], array('currency' => $order->get_currency())),
                                date('Y-m-d H:i:s', strtotime($refund['date'])), $refund['transaction_id'] ?? 'N/A', $refund['trace_id'] ?? 'N/A');
                    }
                    $peiraeus_refunds_message = !empty($refund_messages) ? implode('<br><br>', $refund_messages) : 'No refunds found.';
                } else {
                    $peiraeus_refunds_message = '';
                }

                if (!empty($refunds)) {
                    foreach ($refunds as $refund) {
                        if (is_a($refund, 'WC_Order_Refund')) {
                            $refund_total[] = $refund->get_amount();
                        }
                    }
                }

                $has_refunds  = !empty($order->get_refunds());
                $pre_message  = $has_refunds ? (array_sum($refund_total) == $order->get_total() ? 'Refunded' : 'Partially Refunded') : 'Paid';
                $refund_color = $pre_message == 'Refunded' ? 'red' : ($pre_message == 'Partially Refunded' ? 'orange' : 'green');

                $refund_nonce       = wp_create_nonce('primer_refund_nonce');
                $order_total_paid   = $order->get_total() - $order->get_total_refunded();
                $eligible_statuses  = apply_filters('woocommerce_valid_order_statuses_for_refund', array('processing', 'completed', 'on-hold', 'pending', 'failed', 'cancelled', 'refunded', 'trash', 'custom'));
                $show_refund_button = ($order_total_paid > 0.001) && in_array($order->get_status(), $eligible_statuses);

                if ($show_refund_button) {
                    $order_id_esc     = esc_attr($order->get_id());
                    $refund_nonce_esc = esc_attr($refund_nonce);
                    $button_text      = esc_html(__('Make Refund', 'primer'));
                    $total_paid_esc   = esc_attr(wc_format_decimal($order_total_paid, 2));
                    $refund_button    = "<button type='button' class='button button-primary' data-max-refund='{$total_paid_esc}' onclick=\"makeRefund({$order_id_esc}, this, '{$refund_nonce_esc}')\"> {$button_text} </button>";
                } else {
                    $refund_button = '';
                }

                $orders_data[]         = array(
                        'order_id'       => $order->get_id(),
                        'order_number'   => $order->get_order_number(),
                        'customer_name'  => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()),
                        'receipt'        => $receipt_id,
                        'date'           => $payment['timestamp'],
                        'status'         => $order->get_status(),
                        'total'          => $order->get_formatted_order_total(),
                        'refunds'        => $peiraeus_refunds_message,
                        'trans_ticket'   => $tickets_display,
                        'merch_ref'      => $payment['merch_ref'],
                        'refund_message' => $pre_message,
                        'refund_color'   => $refund_color,
                        'refund'         => $refund_button
                );
                $processed_order_ids[] = $order_id;
            }
        }

        $orders_data = $this->apply_filters($orders_data);

        $total_items         = count($orders_data);
        $screen              = get_current_screen();
        $per_page_option     = $screen ? ($screen->get_option('per_page') ?: 'per_page') : 'per_page';
        $per_page            = absint(get_user_option($per_page_option) ?: 20);
        $current_page        = $this->get_pagenum();
        $offset              = max(0, ($current_page - 1) * $per_page);
        $current_page_orders = array_slice($orders_data, $offset, $per_page);

        $this->set_pagination_args(array(
                'total_items' => $total_items,
                'per_page'    => $per_page,
                'total_pages' => ceil($total_items / $per_page)
        ));
        $orders_data = $current_page_orders;

        ?>
        <div class="wrap">
            <h1 class="page-payments-head"><?php _e('Payments', 'primer'); ?></h1>

            <form method="get" style="display: inline-block; float: right;">
                <?php
                $allowed_params = array('page', 'status', 'date_from', 'date_to');
                foreach ($_GET as $key => $value) {
                    if (in_array($key, $allowed_params)) {
                        printf('<input type="hidden" name="%s" value="%s" />', esc_attr($key), esc_attr($value));
                    }
                }
                ?>
                <p class="search-box" style="float: right; margin: 0;">
                    <label class="screen-reader-text" for="order-search-input"><?php _e('Search by Order ID:', 'primer'); ?></label>
                    <input type="search" id="order-search-input" name="order_search" value="<?php echo esc_attr($search_query); ?>" placeholder="<?php esc_attr_e('', 'primer'); ?>">
                    <?php submit_button(__('Search', 'primer'), 'button', 'order_search_submit', false); ?>
                </p>
            </form>

            </br></br></br>

            <?php $this->render_filters(); ?>

            <?php if ($total_items > 20) { ?>
                <div style="margin-bottom: 10px; float: right; "><?php echo $this->pagination('top'); ?></div>
            <?php } ?>

            <?php if (!empty($orders_data)) : ?>
                <table class="wp-list-table widefat fixed striped table-view-list ">
                    <thead>
                    <tr>
                        <th><?php _e('Order', 'primer'); ?></th>
                        <th><?php _e('Transaction ID', 'primer'); ?></th>
                        <th><?php _e('Merchant Ref', 'primer'); ?></th>
                        <th><?php _e('Receipts', 'primer'); ?></th>
                        <th><?php _e('Payment Date', 'primer'); ?></th>
                        <th><?php _e('Order Status', 'primer'); ?></th>
                        <th><?php _e('Total', 'primer'); ?></th>
                        <th><?php _e('Refunds', 'primer'); ?></th>
                        <th><?php _e('Refund', 'primer'); ?></th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php foreach ($orders_data as $order) : ?>
                        <tr>
                            <td>
                                <a style="font-weight: 700;" href="<?php echo admin_url('post.php?post=' . $order['order_id'] . '&action=edit'); ?>">
                                    #<?php echo esc_html($order['order_number']); ?>
                                </a>
                                <?php echo '<p style="color:' . $order['refund_color'] . '; margin: 0;font-weight: 500">' . __($order['refund_message'], 'primer') . '</p>'; ?>
                                <p><?php echo esc_html($order['customer_name']); ?></p>
                            </td>
                            <td>
                                <?php
                                if (is_array($order['trans_ticket'])) {
                                    echo implode('<br>', array_map('esc_html', $order['trans_ticket']));
                                } else {
                                    echo esc_html($order['trans_ticket']);
                                }
                                ?>
                            </td>
                            <td><?php echo esc_html($order['merch_ref']); ?></td>
                            <td>
                                <?php if (!empty($order['receipt'])):
                                    $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '/?receipt=view');
                                    if (!empty($trasmission_failure)) {
                                        $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '-failed/?receipt=view');
                                    }
                                    ?>
                                    <a href="<?php echo esc_url($receipt_url); ?>" target="_blank" class="payments-links">
                                        <?php echo _e('Issued', 'primer'); ?>
                                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" viewBox="0 0 16 16" fill="#bababa" style="margin-top: 2px;">
                                            <path fill-rule="evenodd" clip-rule="evenodd" d="M2 0H14V16H12L10 14L8 16L6 14L4 16H2V0ZM5 4H11V6H5V4ZM11 8H5V10H11V8Z"/>
                                        </svg>
                                    </a>
                                <?php else: ?>
                                    <span class="payment-weight-400"> <?php _e('Not Issued', 'primer') ?></span>
                                <?php endif; ?>
                            </td>
                            <td><?php echo esc_html($order['date']); ?></td>
                            <td><?php echo esc_html(wc_get_order_status_name($order['status'])); ?></td>
                            <td class="payment-weight-500"><?php echo $order['total']; ?></td>
                            <td style="font-size: 12px; padding: 8px 0;"><?php echo $order['refunds']; ?></td>
                            <td style="vertical-align: middle; text-align: center;"><?php echo $order['refund']; ?></td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>

                <?php if ($total_items > 20) { ?>
                    <div style="margin-top: 10px; float: right; "><?php echo $this->pagination('button'); ?></div>
                <?php } ?>

            <?php else : ?>
                <table class="wp-list-table widefat fixed striped table-view-list ">
                    <thead>
                    <tr>
                        <th><?php _e('Order', 'primer'); ?></th>
                        <th><?php _e('Transaction ID', 'primer'); ?></th>
                        <th><?php _e('Merchant Ref', 'primer'); ?></th>
                        <th><?php _e('Receipts', 'primer'); ?></th>
                        <th><?php _e('Payment Date', 'primer'); ?></th>
                        <th><?php _e('Order Status', 'primer'); ?></th>
                        <th><?php _e('Total', 'primer'); ?></th>
                        <th><?php _e('Refunds', 'primer'); ?></th>
                        <th><?php _e('Refund', 'primer'); ?></th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td colspan="9" style="text-align: center; padding: 20px;">
                            <?php _e('No payments transactions found.', 'primer'); ?>
                        </td>
                    </tr>
                    </tbody>
                </table>

            <?php endif; ?>
        </div>

        <script type="text/javascript">
            let currentOrderId;
            let currentNonce;
            let currentMaxRefund;
            let currentButton;

            function makeRefund(orderId, button, nonceValue) {
                if (!orderId || !button || !nonceValue) {
                    console.error('Invalid parameters for makeRefund: orderId, button, or nonceValue is missing.');
                    return;
                }
                currentOrderId      = orderId;
                currentNonce        = nonceValue;
                currentButton       = button;
                const maxRefundText = button.getAttribute('data-max-refund');
                currentMaxRefund    = parseFloat(maxRefundText);
                jQuery('#modal-order-number').text(`#${orderId}`);
                jQuery('#modal-max-refund').text(maxRefundText);
                jQuery('#refund-amount-input').val(maxRefundText);
                jQuery('#refund-error-message').hide().text('');
                jQuery('#refund-modal-overlay').fadeIn(300);
            }

            function processRefundAjax(refundAmount) {
                jQuery('#refund-modal-overlay').fadeOut(100);
                const originalButton    = {
                    html    : currentButton.innerHTML,
                    disabled: currentButton.disabled
                };
                currentButton.disabled  = true;
                currentButton.innerHTML = '<span class="spinner is-active" style="float: none; margin: 0 5px 0 0;"></span> ' + 'Processing...';
                jQuery.ajax({
                    url        : ajaxurl,
                    type       : 'POST',
                    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
                    data       : {
                        action       : 'primer_make_full_refund',
                        order_id     : currentOrderId,
                        nonce        : currentNonce,
                        refund_amount: refundAmount.toFixed(2)
                    },
                    dataType   : 'json',
                    success    : function (response) {
                        const notice = document.createElement('div');
                        if (response.success) {
                            notice.className = 'notice notice-success is-dismissible';
                            notice.innerHTML = `<p>${response.data.message}</p>`;
                            document.querySelector('.wrap h1').after(notice);
                            setTimeout(() => window.location.reload(), 2000);
                        } else {
                            const errorMessage = response.data?.message || 'Error processing refund.';
                            notice.className   = 'notice notice-error is-dismissible';
                            notice.innerHTML   = `<p>${errorMessage}</p>`;
                            document.querySelector('.wrap h1').after(notice);
                        }
                    },
                    error      : function (xhr, status, error) {
                        console.error('AJAX Error:', xhr.responseText);
                        const notice     = document.createElement('div');
                        notice.className = 'notice notice-error is-dismissible';
                        notice.innerHTML = `<p>System Error: ${status} ${error}. Check console.</p>`;
                        document.querySelector('.wrap h1').after(notice);
                    },
                    complete   : function () {
                        if (!document.querySelector('.notice-success')) {
                            currentButton.disabled  = originalButton.disabled;
                            currentButton.innerHTML = originalButton.html;
                        }
                    }
                });
            }

            document.addEventListener('DOMContentLoaded', function () {
                const pagedInput = document.querySelector('input[name="paged"]');
                if (pagedInput) {
                    pagedInput.addEventListener('keydown', function (e) {
                        if (e.key === 'Enter') {
                            e.preventDefault();
                            const newPage = parseInt(this.value, 10);
                            if (isNaN(newPage) || newPage < 1) {
                                return;
                            }
                            const form = this.closest('form');
                            if (form) {
                                form.submit();
                            } else {
                                const url = new URL(window.location.href);
                                url.searchParams.set('paged', newPage);
                                window.location.href = url.toString();
                            }
                        }
                    });
                }
                const dateFromInput = document.getElementById('date_from');
                const dateToInput   = document.getElementById('date_to');
                const today         = new Date();

                function formatDate(date) {
                    const year  = date.getFullYear();
                    const month = String(date.getMonth() + 1).padStart(2, '0');
                    const day   = String(date.getDate()).padStart(2, '0');
                    return `${year}-${month}-${day}`;
                }

                const maxDate = formatDate(today);
                const minDate = '2020-01-01';
                if (dateFromInput) {
                    dateFromInput.min = minDate;
                    dateFromInput.max = maxDate;
                }
                if (dateToInput) {
                    dateToInput.min = minDate;
                    dateToInput.max = maxDate;
                }
                const modalOverlay = jQuery('#refund-modal-overlay');
                const refundInput  = jQuery('#refund-amount-input');
                const errorMsg     = jQuery('#refund-error-message');
                jQuery('.cancel-refund').on('click', function () {
                    modalOverlay.fadeOut(100);
                });
                jQuery('.confirm-refund').on('click', function () {
                    const amount = parseFloat(refundInput.val());
                    errorMsg.hide().text('');

                    if (isNaN(amount) || amount <= 0) {
                        errorMsg.text('<?php _e('Please enter a valid positive number for the refund amount.', 'primer'); ?>').fadeIn(200);
                        return;
                    }
                    if (amount > currentMaxRefund) {
                        const errorMessage = '<?php _e('The requested refund amount (%s €), exceeds the maximum allowed refund amount (%s €). Please adjust the value.', 'primer'); ?>';
                        const translatedError = errorMessage.replace('%s', amount.toFixed(2)).replace('%s', currentMaxRefund.toFixed(2));
                        errorMsg.text(translatedError).fadeIn(200);
                        return;
                    }
                    processRefundAjax(amount);
                });
            });
        </script>
        <?php

        echo $this->render_refund_modal();
    }

    protected function render_filters() {
        $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : '';
        $date_to   = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : '';
        $receipt   = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : '';
        $refund    = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : '';
        $status    = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : '';

        $order_statuses = wc_get_order_statuses();

        ?>
        <form method="get">
            <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>"/>
            <div class="alignleft actions filters-payments" style="margin-bottom: 10px;">
                <label for="date_from" class="payment-filers-labels-no-margin"><?php _e('Date From:', 'primer'); ?></label>
                <input type="date" name="date_from" id="date_from" value="<?php echo esc_attr($date_from); ?>"/>

                <label for="date_to" class="payment-filers-labels"><?php _e('Date To:', 'primer'); ?></label>
                <input type="date" name="date_to" id="date_to" value="<?php echo esc_attr($date_to); ?>"/>

                <label for="receipt_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
                <select name="receipt_filter" id="receipt_filter">
                    <option value=""><?php _e('All receipts statuses', 'primer'); ?></option>
                    <option value="issued" <?php selected($receipt, 'issued'); ?>><?php _e('Issued', 'primer'); ?></option>
                    <option value="not_issued" <?php selected($receipt, 'not_issued'); ?>><?php _e('Not Issued', 'primer'); ?></option>
                </select>

                <label for="refund_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
                <select name="refund_filter" id="refund_filter">
                    <option value=""><?php _e('All payments status', 'primer'); ?></option>
                    <option value="paid" <?php selected($refund, 'paid'); ?>><?php _e('Paid', 'primer'); ?></option>
                    <option value="partially_refunded" <?php selected($refund, 'partially_refunded'); ?>><?php _e('Partially Refunded', 'primer'); ?></option>
                    <option value="refunded" <?php selected($refund, 'refunded'); ?>><?php _e('Refunded', 'primer'); ?></option>
                </select>

                <label for="status_filter" class="payment-filers-labels"><?php _e('', 'primer') ?></label>
                <select name="status_filter" id="status_filter">
                    <option value=""><?php _e('All order statuses', 'primer') ?></option>
                    <?php
                    foreach ($order_statuses as $key_with_prefix => $label) :$key = str_replace('wc-', '', $key_with_prefix); ?>
                        <option value="<?php echo esc_attr($key); ?>" <?php selected($status, $key); ?>><?php echo esc_html($label); ?></option>
                    <?php endforeach; ?>
                </select>

                <div class="payments-button-filters">
                    <?php submit_button(__('Filter', 'primer'), 'button', 'filter_action', false); ?>
                </div>
            </div>
        </form>
        <?php
    }

    protected function apply_filters($orders_data) {
        $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : null;
        $date_to   = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : null;
        $receipt   = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : null;
        $refund    = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : null;
        $status    = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : null;

        if (empty($date_from) && empty($date_to) && empty($receipt) && empty($refund) && empty($status)) {
            return $orders_data;
        }

        $filtered_data = array_filter($orders_data, function($order) use ($date_from, $date_to, $receipt, $refund, $status) {
            $pass_date = $pass_receipt = $pass_refund = $pass_status = true;

            $order_date_timestamp = strtotime($order['date']);

            if ($date_from) {
                $from_timestamp = strtotime($date_from);
                if ($order_date_timestamp < $from_timestamp) {
                    $pass_date = false;
                }
            }

            if ($pass_date && $date_to) {
                $to_timestamp = strtotime($date_to) + (24 * 60 * 60);
                if ($order_date_timestamp >= $to_timestamp) {
                    $pass_date = false;
                }
            }

            if ($receipt) {
                $is_issued = !empty($order['receipt']);
                switch ($receipt) {
                    case 'issued':
                        $pass_receipt = $is_issued;
                        break;
                    case 'not_issued':
                        $pass_receipt = !$is_issued;
                        break;
                }
            }

            if ($refund) {
                $order_refund_message = strtolower(str_replace(' ', '_', $order['refund_message']));
                switch ($refund) {
                    case 'paid':
                        $pass_refund = ($order_refund_message === 'paid');
                        break;
                    case 'partially_refunded':
                        $pass_refund = ($order_refund_message === 'partially_refunded');
                        break;
                    case 'refunded':
                        $pass_refund = ($order_refund_message === 'refunded');
                        break;
                }
            }

            if ($status) {
                $order_status_slug = str_replace('wc-', '', $order['status']);
                $pass_status       = $order_status_slug === $status;
            }

            return $pass_date && $pass_receipt && $pass_refund && $pass_status;
        });

        return $filtered_data;
    }

    public function render_refund_modal() {
        $currency_symbol = get_woocommerce_currency_symbol();
        ob_start();
        ?>
        <div id="refund-modal-overlay">
            <div id="refund-modal">
                <h3><?php _e('Process Refund', 'primer'); ?></h3>
                <p><?php _e('Order:', 'primer'); ?> <strong id="modal-order-number">N/A</strong></p>
                <p><?php _e('Max Refund:', 'primer'); ?> <strong id="modal-max-refund">N/A</strong></p>
                <hr>
                <p class="payments-enter-amount"><?php _e('Enter Amount:', 'primer'); ?></p>
                <div class="refund-amount-input-div">
                    <span style="font-size: 1.2em;"><?php echo esc_html($currency_symbol); ?></span>
                    <input type="number" id="refund-amount-input" step="0.01" min="0.01">
                </div>
                <p id="refund-error-message"></p>
                <div class="refund-actions">
                    <button type="button" class="button button-secondary cancel-refund"><?php _e('Cancel', 'primer'); ?></button>
                    <button type="button" class="button button-primary confirm-refund"><?php _e('Confirm Refund', 'primer'); ?></button>
                </div>
            </div>
        </div>
        <?php
        return ob_get_clean();
    }

}

new PrimerPaymentsPage();

function get_piraeusbank_transactions() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'piraeusbank_transactions';

    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
        return array();
    }

    $query = "SELECT * FROM $table_name ORDER BY timestamp DESC";

    return $wpdb->get_results($query, ARRAY_A);
}
