<?php
namespace Formipay;
use Formipay\Traits\SingletonTrait;
if ( ! defined( 'ABSPATH' ) ) exit;

class Order {

    use SingletonTrait;

    private $form_id;

    private $form_data;

    private $order_data;

    private $order_details;

    private $chosen_currency; // reserved (not used yet)

    private $currency; // 3-letter currency code from request (e.g., IDR, USD)

	/**
	 * Initializes the plugin by setting filters and administration functions.
	 */
    
    protected function __construct() {
        
        add_action( 'init',                                     [$this, 'create_db'] );
        add_action( 'wp_ajax_formipay_submission',              [$this, 'retrieve_form_data'] );
        add_action( 'wp_ajax_nopriv_formipay_submission',       [$this, 'retrieve_form_data'] );

        add_action( 'admin_menu',                               [$this, 'add_menu'] );
        add_action( 'admin_enqueue_scripts',                    [$this, 'enqueue'] );

        add_action( 'wp_ajax_formipay_get_all_forms',           [$this, 'formipay_get_all_forms'] );
        add_action( 'wp_ajax_formipay_orders_get_choices',      [$this, 'formipay_orders_get_choices'] );

        add_action( 'wp_ajax_formipay-tabledata-orders',        [$this, 'formipay_tabledata_orders'] );
        add_action( 'wp_ajax_formipay-delete-order',            [$this, 'formipay_delete_order'] );
        add_action( 'wp_ajax_formipay-bulk-delete-order',       [$this, 'formipay_bulk_delete_order'] );
        add_action( 'wp_ajax_formipay_load_order_data',         [$this, 'formipay_load_order_data'] );
        add_action( 'wp_ajax_formipay_change_order_status',     [$this, 'formipay_change_order_status'] );
        add_action( 'wp_ajax_formipay_check_editable_field',    [$this, 'formipay_check_editable_field'] );
        add_action( 'wp_ajax_formipay_update_editable_field_data', [$this, 'formipay_update_editable_field_data'] );
        add_action( 'wp_ajax_formipay_update_digital_access',   [$this, 'formipay_update_digital_access'] );

        add_filter( 'formipay/order/thankyou-screen-content',   [$this, 'process_response_message'], 999, 5 );
        add_filter( 'formipay/order/get',                       [$this, 'get_order_by_id'], 10, 2 );

    }

    public function create_db() {

        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();

        $create[] = "CREATE TABLE `{$wpdb->base_prefix}formipay_orders` (
            `id` bigint(20) NOT NULL AUTO_INCREMENT,
            `created_date` datetime DEFAULT CURRENT_TIMESTAMP,
            `updated_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            `form_id` int,
            `user_id` int,
            `customer_id` int,
            `items` text,
            `total` float(10, 2) DEFAULT 0,
            `status` varchar(20) DEFAULT 'on-hold',
            `form_data` text,
            `payment_gateway` text,
            `meta_data` text, 
            PRIMARY KEY (`id`)
        ) $charset_collate;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        dbDelta($create);

    }

    public function retrieve_form_data() {
        // Verify nonce
        if ( empty($_POST['nonce']) || ! wp_verify_nonce( sanitize_text_field(wp_unslash($_POST['nonce'])), 'formipay_order_submit' ) ) {
            wp_send_json_error([
                'message' => 'Nonce verification failed'
            ]);
        }
    
        // Sanitize and unslash inputs explicitly
        $form_id = isset($_REQUEST['form_id']) ? intval(wp_unslash($_REQUEST['form_id'])) : 0;
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $raw_data = isset($_REQUEST['data']) ? wp_unslash($_REQUEST['data']) : [];
        $form_data = is_array($raw_data) ? formipay_sanitize_array($raw_data) : sanitize_text_field($raw_data);
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $order_meta_data = isset($_REQUEST['meta_data']) ? wp_unslash($_REQUEST['meta_data']) : [];
        $purpose = isset($_REQUEST['purpose']) ? sanitize_text_field(wp_unslash($_REQUEST['purpose'])) : '';
        $this->currency = isset($_REQUEST['currency']) ? sanitize_text_field( wp_unslash($_REQUEST['currency']) ) : (string) formipay_default_currency('code');
    
        $this->form_id = $form_id;
    
        // Let everyone modify this data (sanitize inside filters if needed)
        $order_data = apply_filters('formipay/order/process-data', $form_data, $form_id);
        $this->order_data = $order_data;
    
        $order_details = $this->process_order_details();
        $this->order_details = $order_details;
    
        $total = $this->process_order_total();
    
        if ($purpose === 'calculate') {
            $order_data['total'] = $total;
            $order_data['items'] = $order_details;
            $order_data['form_data'] = formipay_get_post_meta($form_id);
            wp_send_json($order_data);
        }
    
        $status = ($total == 0) ? 'completed' : 'on-hold';
    
        $submit_args = [
            'form_id'         => $form_id,
            'items'           => $order_details,
            'total'           => $total,
            'status'          => $status,
            'form_data'       => $order_data,
            'payment_gateway' => isset($order_data['payment_gateway']) ? sanitize_text_field($order_data['payment_gateway']) : '',
            'meta_data'       => $order_meta_data,
        ];
    
        $submit = $this->submit($submit_args);
    
        $order_date = formipay_date('Y-m-d H:i:s');
    
        $form_settings = formipay_get_post_meta($form_id, 'formipay_settings');
        $global_settings = get_option('formipay_settings');
        $thankyou_link = (!empty($global_settings['thankyou_link'])) ? $global_settings['thankyou_link'] : 'thankyou';
    
        if ($submit !== false) {
            
            $order_data = formipay_get_order($submit);
            $this->order_data = apply_filters('formipay/order/result', $order_data);
    
            do_action('formipay/order/new', $this->order_data);
            do_action('formipay/order/on-hold', $this->order_data);
            do_action('formipay/notification/order', $this->order_data);
    
            $submit_action_type = formipay_get_post_meta($form_id, 'submit_action_type');
    
            $success_message = formipay_get_post_meta($form_id, 'success_response_content');
            $success_message = $this->process_response_content($success_message, 'thankyou');
    
            $unique_id = isset($order_meta_data['session_id']) ? sanitize_text_field($order_meta_data['session_id']) : '';
            $thankyou_url = site_url('/' . $thankyou_link . '/' . base64_encode($form_id . ':::' . $order_data['id'] . ':::' . $unique_id));
            setcookie('fp_access', wp_json_encode([$order_data['id'] => $unique_id]), time() + 86400, '/', '', is_ssl(), true);
    
            if (
                !empty($this->order_data['redirect_url']) &&
                $submit_action_type !== 'whatsapp'
            ) {
                $redirect_url = esc_url_raw($this->order_data['redirect_url']);
            } else {
                switch ($submit_action_type) {
                    case 'redirect':
                        $redirect_url = esc_url_raw(formipay_get_post_meta($form_id, 'redirect_url'));
                        break;
                    case 'whatsapp':
                        $admin_number = sanitize_text_field(formipay_get_post_meta($form_id, 'whatsapp_admin'));
                        $whatsapp_message_format = formipay_get_post_meta($form_id, 'whatsapp_message');
                        $redirect_url = 'https://wa.me/' . $admin_number . '?text=' . rawurlencode($this->process_response_content($whatsapp_message_format, $submit_action_type));
                        break;
                    default:
                        $redirect_url = esc_url_raw($thankyou_url);
                        break;
                }
            }
    
            wp_send_json_success([
                'message'       => wp_kses_post($success_message),
                'response_type' => formipay_get_post_meta($form_id, 'response_type'),
                'action_type'   => $submit_action_type,
                'url'           => $redirect_url,
            ]);
        }
    
        $message = formipay_get_post_meta($form_id, 'failed_response_content');
        $message = str_replace('{{error_message}}', $submit->error_message(), $message);
        wp_send_json_error(['message' => wp_kses_post($message)]);
    }    

    public function process_order_shortcodes($submit_action_type) {

        $buyer_name = '';
        if(!empty(formipay_get_post_meta($this->form_id, 'buyer_name'))){
            $buyer_name_field = formipay_get_post_meta($this->form_id, 'buyer_name');
            $buyer_name = $this->order_data['form_data'][$buyer_name_field];
        }

        $shortcodes = [
            'buyer_name'        => $buyer_name,
            'product_name'      => html_entity_decode(get_the_title($this->form_id)),
            'order_id'          => $this->order_data['id'],
            'order_date'        => $this->order_data['created_date'],
            'order_total'       => formipay_price_format($this->order_data['total'], $this->form_id),
            'order_status'      => $this->order_data['status'],
            'order_details'     => $this->render_order_details($submit_action_type),
            'form_submission'   => $this->render_form_submit($submit_action_type)
        ];

        $shortcodes = apply_filters( 'formipay/order/shortcodes', $shortcodes, $this->form_id, $this->order_data, $submit_action_type );

        return $shortcodes;

    }

    public function process_order_details() {

        $currency_codes = [];
        $allowed_currencies = formipay_get_post_meta($this->form_id, 'allowed_currencies');
        if(!empty($allowed_currencies)){
            $parse_currencies = json_decode($allowed_currencies, true);
            foreach($parse_currencies as $currency_data){
                $parse_currency = explode(':::', $currency_data);
                $currency_codes[] = $parse_currency[0];
            }
        }
        
        $details = [];

        // Ensure currency code is present; fallback to form default currency code
        if (empty($this->currency)) {
            $default_currency_full = formipay_get_post_meta($this->form_id, 'default_currencies'); // e.g., "IDR:::Indonesian rupiah:::Rp"
            $parts = explode(':::', (string) $default_currency_full);
            $this->currency = $parts[0] ?? 'IDR';
        }

        // Attached static products (qty = 1 each in this case)
        $products = formipay_get_post_meta($this->form_id, 'static_products');
        if (!empty($products)) {
            $products = array_filter(array_map('absint', explode(',', (string) $products)));
            foreach ($products as $product_id) {
                $regular_key = 'setting_product_price_regular_' . $this->currency;
                $sale_key    = 'setting_product_price_sale_' . $this->currency;
                $regular_price = formipay_get_post_meta($product_id, $regular_key);
                $sale_price    = formipay_get_post_meta($product_id, $sale_key);
                $price = ($sale_price !== '' && $sale_price !== null) ? (float) $sale_price : (float) $regular_price;

                $details[] = [
                    'item'     => html_entity_decode(get_the_title($product_id)),
                    'amount'   => $price,
                    'qty'      => 1,
                    'subtotal' => $price,
                    'context'  => 'product',
                ];
            }
        }

        // Static items (fees/bonuses), currency-aware amounts
        $raw_items = formipay_get_post_meta($this->form_id, 'static_items');
        if (!empty($raw_items)) {
            $items = json_decode((string) $raw_items, true) ?: [];
            foreach ($items as $it) {
                $label = $it['label'] ?? 'Item';
                $qty   = (int) ($it['quantity'] ?? 1);
                $key   = 'amount_' . $this->currency;
                $amt   = (float) ($it[$key] ?? 0);
                $details[] = [
                    'item'     => $label,
                    'amount'   => $amt,
                    'qty'      => $qty,
                    'subtotal' => $amt * $qty,
                    'context'  => 'item',
                ];
            }
        }

        $details = apply_filters('formipay/order/order-details', $details, $this->form_id, $this->order_data );

        return $details;

    }

    public function process_order_total() {

        $detail_total = 0.00;

        if(!empty($this->order_details)){
            foreach ($this->order_details as $detail) {
                $detail_total += $detail['subtotal'];
            }
        }

        $order_total = apply_filters('formipay/order/set-total', $detail_total, $this->form_id, $this->order_data);

        if($order_total <= 0){
            $order_total = 0;
        }

        return $order_total;

    }

    public function process_response_content($content, $submit_action_type){

        $shortcodes = $this->process_order_shortcodes($submit_action_type);
        // $target = [];
        // $replace_to_be = [];
        $replacements = [];
        if(!empty($shortcodes)){
            foreach($shortcodes as $key => $value){
                // $target[] = '{{'.$key.'}}';
                // $replace_to_be[] = $value;
                $replacements['{{'.$key.'}}'] = $value;
            }
        }

        // $content = str_replace($target, $replace_to_be, $content);
        $content = strtr($content, $replacements);

        if($submit_action_type == 'whatsapp'){
            $content = str_replace(
                [
                    PHP_EOL, "\n", ' '
                ],
                [
                    '%0A', '%0A', '%20'
                ],
                $content
            );
        }

        return $content;

    }

    public function render_order_details($submit_action_type) {

        if($submit_action_type == 'thankyou'){

            ob_start();
            if(!empty($this->order_details)){
            ?>
            <table id="order-details">
                <tbody>
                    <?php
                    foreach($this->order_details as $detail){
                        $qty = '';
                        if(isset($detail['qty'])){
                            $qty = ' <i class="bi bi-x"></i> '.$detail['qty'];
                        }
                        ?>
                            <tr>
                                <th><?php echo esc_html($detail['item'] . $qty); ?></th>
                                <td><?php echo esc_html(formipay_price_format($detail['subtotal'], $this->form_id)); ?></td>
                            </tr>
                        <?php
                    }
                    ?>
                    <tr>
                        <th><?php echo esc_html__( 'Total', 'formipay' ); ?></th>
                        <td><b><?php echo esc_html(formipay_price_format($this->order_data['total'], $this->form_id)); ?></b></td>
                    </tr>
                </tbody>
            </table>
            <?php
            }
            $content = ob_get_contents();
            ob_get_clean();

        }elseif($submit_action_type == 'whatsapp'){

            $target_length = 24;
            $message_format = formipay_get_post_meta($this->form_id, 'whatsapp_message');
            $order_details_message = '';
            if(!empty($this->order_details)){
                foreach($this->order_details as $detail){
                    $qty = '';
                    if(isset($detail['qty']) && !empty($detail['qty'])){
                        $qty = $detail['qty'].'×';
                    }
                    $subtotal = formipay_price_format($detail['subtotal'], $this->form_id);
                    $qty_length = strlen($qty);
                    $subtotal_length = strlen($subtotal);
                    if(floatval($detail['subtotal']) < 0){
                        $subtotal_length = $subtotal_length + 1;
                    }
                    $dot_length = $target_length - ($qty_length + $subtotal_length);
                    $dots = str_repeat('.', intval($dot_length));
                    $order_details_message .= "%0A".$detail['item'];
                    $order_details_message .= "%0A".$qty.$dots.$subtotal;
                }
                $total = formipay_price_format($this->order_data['total'], $this->form_id);
                $total_length = strlen($total);
                $dot_length = $target_length - ($total_length + 6);
                $dots = str_repeat('.', intval($dot_length));
                $divider = str_repeat('_', intval($target_length));
                $order_details_message .= "%0A".$divider."%0A%0A".'Total'.$dots.$total;
            }
            $order_details_message .= '';

            $content = '%60%60%60'.$order_details_message.'%60%60%60';

        }else{

            $content = apply_filters( 'formipay/order/order-details/shortcode-render', '', $this->form_id, $this->order_details, $submit_action_type );

        }

        return $content;
    }

    public function render_form_submit($submit_action_type) {
        ob_start();
        if(!empty($this->order_data)){

            $field_config = formipay_get_post_meta($this->order_data['form_id'], 'formipay_settings');

            $skip_row = array(
                'form_id', 'payment', 'id', 'status', 'total', 'created_date', 'redirect_url', 'items', 'form_data', 'meta_data'
            );
            $rows = [];
            foreach($this->order_data['form_data'] as $field_name => $field_value){

                $field_value = $field_value['value'];
                // $field_label = $field_config['fields'][$field_name.'_config']['label'];
                if(in_array($field_name, $skip_row)){
                    continue;
                }
                switch ($field_name) {

                    case 'form_id':
                        $field_label = __( 'Form ID', 'formipay' );
                        break;
                    case 'qty':
                        $field_label = __( 'Quantity', 'formipay' );
                        break;
                    case 'coupon_code':
                        $field_label = __( 'Coupon Code', 'formipay' );
                        break;
                    case 'payment':
                        $field_label = __( 'Payment', 'formipay' );
                        break;
                    case 'payment_gateway':
                        $field_label = __( 'Payment Gateway', 'formipay' );
                        $field_value = ucwords(str_replace('_', ' ', $field_value));
                        break;
                    case 'id':
                        $field_label = __( 'Order ID', 'formipay' );
                        break;
                    case 'total':
                        $field_label = __( 'Grand Total', 'formipay' );
                        $field_value = formipay_price_format($field_value, $this->form_id);
                        break;
                    case 'status':
                        $field_label = __( 'Order Status', 'formipay' );
                        break;
                    case 'created_date':
                        $field_label = __( 'Order Date', 'formipay' );
                        break;
                    
                    default:
                        $field_label = $field_config['fields'][$field_name.'_config']['label'];
                        if(is_array($field_value)){
                            $field_value = $field_value['value'];
                        }
                        if(filter_var($field_value, FILTER_VALIDATE_EMAIL)){
                            $field_value = $field_value;
                        }elseif(strpos($field_value, ',') !== false){
                            $values = explode(',', $field_value);
                            $field_value = '';
                            foreach($values as $value){
                                $field_value .= '<span class="checkbox-span">'.$value.'</span> ';
                            }
                        }else{
                            $field_value = ucwords(str_replace(['-','_'], ' ', $field_value));
                        }
                        break;
                }
                $rows[] = [
                    'label' => $field_label,
                    'value' => $field_value
                ];
            }

            if($submit_action_type == 'thankyou') {
                ?>
                <table id="order-submission-details">
                    <tbody>
                        <tr>
                            <th><?php echo esc_html__('Product', 'formipay'); ?></th>
                            <td><?php echo esc_html(get_the_title($this->form_id)); ?></td>
                        </tr>
                        <?php
                        foreach($rows as $row) {
                            ?>
                            <tr>
                                <th><?php echo esc_html($row['label']); ?></th>
                                <td><?php echo esc_html($row['value']); ?></td>
                            </tr>
                            <?php
                        }
                        ?>
                    </tbody>
                </table>
                <?php
                ob_get_clean();
                $content = ob_get_contents();
            }elseif($submit_action_type == 'whatsapp') {
                $content = '';
                foreach($rows as $row){
                    $content .= "%0A".rawurlencode($row['label'].': *'.$row['value'].'*');
                }
            }
        }

        return $content;
    }

    public function submit($args) {

        $args = wp_parse_args( $args, [
            'form_id'           => 0,
            'items'             => [],
            'total'             => 0,
            'status'            => 'on-hold',
            'form_data'         => [],
            'payment_gateway'   => '',
            'meta_data'         => []
        ] );

        global $wpdb;
        $table = $wpdb->prefix . 'formipay_orders';

        $insert_data = [
            'created_date'      => formipay_date('Y-m-d H:i:s'),
            'form_id'           => intval($args['form_id']),
            'items'             => maybe_serialize($args['items']),
            'total'             => floatval($args['total']),
            'status'            => sanitize_text_field( $args['status'] ),
            'form_data'         => maybe_serialize($args['form_data']),
            'payment_gateway'   => sanitize_text_field($args['payment_gateway']),
            'meta_data'         => maybe_serialize($args['meta_data'])
        ];

        if($args['form_id'] > 0){
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
            $wpdb->insert($table, $insert_data);

            return $wpdb->insert_id;
        }
        
        return false;

    }

    public function get($order_id = 0) {

        global $wpdb;
        $table = $wpdb->prefix .'formipay_orders';
        if($order_id == 0){
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $get = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM %i", $table
                )
            );
        }else{
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $get = $wpdb->get_row(
                $wpdb->prepare(
                    "SELECT * FROM %i WHERE `id` = %d", $table, $order_id
                )
            );
        }
        
        return $get;

    }

    public function get_order_by_id($data, $order_id){
        global $wpdb;
        $table = $wpdb->prefix .'formipay_orders';
        if($order_id == 0){
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $data = $wpdb->get_results(
                $wpdb->prepare("SELECT * FROM %i", $table),
                ARRAY_A
            );
        }else{
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $data = $wpdb->get_row(
                $wpdb->prepare("SELECT * FROM %i WHERE `id` = %d", $table, $order_id),
            ARRAY_A);
        }
        
        return $data;
    }

    public function get_by_form_id($form_id, $search='', $limit=false, $offset=false) {

        global $wpdb;
        $table = $wpdb->prefix .'formipay_orders';
        if(false == $limit && false == $offset){
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $get = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM %i WHERE `form_id` = %d", $table, $form_id
                )
            );
        }else{
            if('' == $search){
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $get = $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM %i WHERE `form_id` = %d ORDER BY `id` DESC LIMIT %d, %d", 
                        $table, $form_id, $offset, $limit
                    )
                );
            }else{
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $get = $wpdb->get_results(
                    $wpdb->prepare("SELECT * FROM %i WHERE `form_id` = %d AND `form_data` LIKE %s ORDER BY `id` DESC LIMIT %d, %d", 
                    $table, $form_id, '%'.$search.'%',$offset, $limit)
                );
            }
        }
    
        return $get;

    }

    public function add_menu() {

        add_submenu_page( 
            'formipay', 
            __( 'Orders', 'formipay' ), 
            __( 'Orders', 'formipay' ), 
            'manage_options', 
            'formipay-orders', 
            [$this, 'orders_page'] 
        );

    }

    public function orders_page() {

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $order_id = isset($_GET['order_id']) ? intval($_GET['order_id']) : 0;
        if(empty($order_id)){
            include FORMIPAY_PATH . 'admin/page-orders.php';
        }else{
            $order = formipay_get_order( $order_id );
            include FORMIPAY_PATH . 'admin/page-order-details.php';
        }

    }

    public function enqueue() {

        global $current_screen;

        if($current_screen->id == 'formipay_page_formipay-orders') {

            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $order_id = isset($_GET['order_id']) ? intval($_GET['order_id']) : 0;
            if(empty($order_id)){
                wp_enqueue_style( 'page-orders', FORMIPAY_URL . 'admin/assets/css/admin-orders.css', [], FORMIPAY_VERSION, 'all' );
                wp_enqueue_script( 'page-orders', FORMIPAY_URL . 'admin/assets/js/admin-orders.js', ['jquery', 'gridjs'], FORMIPAY_VERSION, true );

                wp_localize_script( 'page-orders', 'formipay_orders_page', [
                    'ajax_url' => admin_url('admin-ajax.php'),
                    'site_url' => site_url(),
                    'columns' => [
                        'id' => esc_html__( 'ID', 'formipay' ),
                        'form' => esc_html__( 'Form', 'formipay' ),
                        'total' => esc_html__( 'Total', 'formipay' ),
                        'date' => esc_html__( 'Date', 'formipay' ),
                        'payment_gateway' => esc_html__( 'Payment Gateway', 'formipay' ),
                        'status' => esc_html__( 'Status', 'formipay' ),
                    ],
                    'filter_form' => [
                        'products' => [
                            'placeholder' => esc_html__( 'Filter by Product', 'formipay' ),
                            'noresult_text' => esc_html__( 'No results found', 'formipay' )
                        ],
                        'currencies' => [
                            'placeholder' => esc_html__( 'Filter by Currency', 'formipay' ),
                            'noresult_text' => esc_html__( 'No results found', 'formipay' )
                        ]
                    ],
                    'nonce' => wp_create_nonce( 'formipay-order-details' )
                ] );
            }else{

                wp_enqueue_style( 'bootstrap-icon', FORMIPAY_URL . 'vendor/Bootstrap/bootstrap-icons.css', [], '1.11.1', 'all');
                wp_enqueue_style( 'bootstrap', FORMIPAY_URL . 'vendor/Bootstrap/bootstrap.min.css', [], '5.3.2' );
                wp_enqueue_style( 'page-orders', FORMIPAY_URL . 'admin/assets/css/admin-order-details.css', [], FORMIPAY_VERSION, 'all' );
                wp_enqueue_script( 'handlebars', FORMIPAY_URL . 'vendor/HandleBars/handlebars.min.js', [], '4.7.7', true);
                wp_enqueue_script( 'bootstrap', FORMIPAY_URL . 'vendor/Bootstrap/bootstrap.bundle.min.js', ['jquery'], '5.3.2', true );
                wp_enqueue_script( 'page-orders', FORMIPAY_URL . 'admin/assets/js/admin-order-details.js', ['jquery'], FORMIPAY_VERSION, true );

                wp_localize_script( 'page-orders', 'formipay_order_details_page', [
                    'ajax_url' => admin_url('admin-ajax.php'),
                    'site_url' => site_url(),
                    'order_id' => $order_id,
                    'order_detail' => [
                        'change_order_status_confirmation' => esc_html__( 'Are you sure to change status?', 'formipay' ),
                        'change_order_status_button_confirm' => esc_html__( 'Change', 'formipay' ),
                        'change_order_status_button_cancel' => esc_html__( 'Cancel', 'formipay' ),
                        'edit_button_loading_text' => esc_html__( 'Preparing...', 'formipay' ),
                        'update_button_loading_text' => esc_html__( 'Updating...', 'formipay' ),
                        'pass_method' => [
                            'magic_link' => esc_html__( 'Magic Link', 'formipay' ),
                            'static_password' => esc_html__( 'Static Password', 'formipay' )
                        ]
                    ],
                    'modal' => [
                        'delete' => [
                            'question' => esc_html__( 'Do you want to delete the order?', 'formipay' ),
                            'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
                            'confirmButton' => esc_html__( 'Delete Permanently', 'formipay' )
                        ],
                        'bulk_delete' => [
                            'question' => esc_html__( 'Do you want to delete the selected the order(s)?', 'formipay' ),
                            'cancelButton' => esc_html__( 'Cancel', 'formipay' ),
                            'confirmButton' => esc_html__( 'Confirm', 'formipay' )
                        ],
                    ],
                    'nonce' => wp_create_nonce( 'formipay-order-details' )
                ] );
            }

        }

    }

    public function formipay_get_all_forms() {

        $all_forms = get_posts([
            'post_type' => 'formipay-form',
            'posts_per_page' => -1
        ]);

        $forms = [];
        if(!empty($all_forms)){
            foreach($all_forms as $form){
                $forms[$form->ID] = get_the_title($form->ID);
            }
        }

        wp_send_json( $forms );

    }

    public function get_all_field_name($formid) {

        $meta = get_post_meta($formid, 'formipay_settings', true);
        $headers = $meta['fields'];

        $table_header = [];
        if(!empty($headers)){
            foreach($headers as $config => $header){
                $header_id = $header['field_id'];
                $table_header[$header_id] = $header['label'];
            }
        }
        return $table_header;

    }

    public function formipay_orders_get_choices() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $type = isset($_REQUEST['type']) ? sanitize_text_field( wp_unslash($_REQUEST['type']) ) : '';
        $search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';

        $results = [];
        if($type == 'form'){
            $args = [
                'post_type' => 'formipay-form',
                'posts_per_page' => -1,
            ];
            if('' !== $search) {
                $args['s'] = $search;
            }
            $get = get_posts($args);
    
            if(!empty($get)){
                foreach($get as $post){
                    $results[] = [
                        'value' => $post->ID,
                        'label' => $post->post_title
                    ];
                }
            }
        }elseif($type == 'currency'){
            $countries = formipay_currency_array();
            foreach($countries as $country){
                $country_name = strtolower($country['name']);
                $country_search = strtolower($search);
                if(strpos($country_name, $country_search) !== false || $country_search == strtolower($country['code'])){
                    $results[] = [
                        'value' => $country['code'],
                        // phpcs:ignore PluginCheck.CodeAnalysis.ImageFunctions.NonEnqueuedImage
                        'label' => '<img src="'.formipay_get_flag_by_currency($country['code']).'" height="18" style="margin-bottom: -3px;"> '.$country['name']
                    ];
                }
            }
        }

        wp_send_json($results);

    }

    public function update($order_id, $args) {
    
        global $wpdb;
        $table_name = $wpdb->prefix . 'formipay_orders';
        
        // Get current data safely
        $recent_data = $this->get($order_id);
        if (!$recent_data) {
            return new WP_Error('invalid_order', __('Order not found', 'formipay'));
        }
    
        // Parse args with type safety
        $args = wp_parse_args($args, [
            'form_id'           => (int)$recent_data->form_id,
            'items'             => maybe_unserialize($recent_data->items) ?: [],
            'total'             => (float)$recent_data->total,
            'status'            => sanitize_text_field($recent_data->status),
            'form_data'         => maybe_unserialize($recent_data->form_data) ?: [],
            'payment_gateway'   => sanitize_text_field($recent_data->payment_gateway),
            'meta_data'         => maybe_unserialize($recent_data->meta_data) ?: []
        ]);
    
        // Prepare update log
        $update_time = current_time('mysql');
        $user_id = get_current_user_id();
        $changes = [];
        $status_changed = false;
    
        // Compare values properly (unserialized)
        $compare_fields = [
            'items' => ['before' => maybe_unserialize($recent_data->items), 'after' => $args['items']],
            'total' => ['before' => (float)$recent_data->total, 'after' => (float)$args['total']],
            'status' => ['before' => $recent_data->status, 'after' => $args['status']],
            'form_data' => ['before' => maybe_unserialize($recent_data->form_data), 'after' => $args['form_data']],
            'payment_gateway' => ['before' => $recent_data->payment_gateway, 'after' => $args['payment_gateway']]
        ];
    
        foreach ($compare_fields as $field => $values) {
            if ($values['before'] !== $values['after']) {
                $changes[$field] = [
                    'before' => $this->sanitize_log_value($values['before']),
                    'after' => $this->sanitize_log_value($values['after'])
                ];
                
                if ($field === 'status') {
                    $status_changed = true;
                }
            }
        }
    
        // Update meta_data with log
        if (!empty($changes)) {
            $args['meta_data']['update_log'][] = [
                'timestamp' => $update_time,
                'user_id' => $user_id,
                'changes' => $changes
            ];
        }
    
        // Prepare database update
        $new_args = [
            'form_id'           => (int)$args['form_id'],
            'items'             => maybe_serialize($args['items']),
            'total'             => (float)$args['total'],
            'status'            => sanitize_text_field($args['status']),
            'form_data'         => maybe_serialize($args['form_data']),
            'payment_gateway'   => sanitize_text_field($args['payment_gateway']),
            'meta_data'         => maybe_serialize($args['meta_data'])
        ];
    
        $formats = [
            '%d',   // form_id
            '%s',   // items
            '%f',   // total
            '%s',   // status
            '%s',   // form_data
            '%s',   // payment_gateway
            '%s'    // meta_data
        ];
    
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $updated = $wpdb->update(
            $table_name,
            $new_args,
            ['id' => (int)$order_id],
            $formats,
            ['%d']
        );
    
        // Trigger actions if status changed
        if ($status_changed && $updated) {
            $order_data = $this->get($order_id);
            do_action("formipay/order/{$args['status']}", $order_data);
            do_action('formipay/notification/order', $order_data);
        }
    
        return $updated;
    }

    public function delete($order_id) {

        global $wpdb;

		return $wpdb->delete(
			$wpdb->prefix . 'formipay_orders',
			['id' => $order_id],
			['%d'],
		);

    }
    
    private function sanitize_log_value($value) {
        if (is_array($value)) {
            return array_map([$this, 'sanitize_log_value'], $value);
        }
        return sanitize_text_field(wp_unslash($value));
    }
    

    public function formipay_tabledata_orders() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        global $wpdb;
        $table = $wpdb->prefix . 'formipay_orders';

        // Count order statuses efficiently
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $status_counts = $wpdb->get_results("SELECT `status`, COUNT(*) as cnt FROM {$table} GROUP BY `status`", ARRAY_A);

        $order_status = [
            'all' => 0,
            'completed' => 0,
            'on-hold' => 0,
            'payment-confirm' => 0
        ];

        if (!empty($status_counts)) {
            foreach ($status_counts as $row) {
                $order_status['all'] += (int) $row['cnt'];
                if (isset($order_status[$row['status']])) {
                    $order_status[$row['status']] = (int) $row['cnt'];
                }
            }
        }
    
        $where = [];
        $params = [];

        // ID filter
        if (!empty(intval($_REQUEST['order_id']))) {
            $where[] = "`id` = %d";
            $params[] = intval($_REQUEST['order_id']);
        } else {
            $where[] = "`id` > %d";
            $params[] = 0;
        }

        // Status filter
        if (isset($_REQUEST['order_status']) && 'all' !== $_REQUEST['order_status']) {
            $where[] = "`status` = %s";
            $params[] = sanitize_text_field(wp_unslash($_REQUEST['order_status']));
        }

        // Product filter
        if (isset($_REQUEST['product']) && 0 < intval($_REQUEST['product'])) {
            $where[] = "`form_id` = %d";
            $params[] = intval($_REQUEST['product']);
        }

        // Combine WHERE clause
        $where_sql = implode(' AND ', $where);
    
        $sql = "SELECT * FROM {$table} WHERE $where_sql ORDER BY `id` DESC";
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $get_all_orders = $wpdb->get_results($wpdb->prepare($sql, ...$params));

        // For paginated query:
        $limit = intval($_REQUEST['limit'] ?? 10);
        $offset = intval($_REQUEST['offset'] ?? 0);
        $sql_paginated = $sql . " LIMIT %d OFFSET %d";
        $params_paginated = array_merge($params, [$limit, $offset]);
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $get_filtered_orders = $wpdb->get_results($wpdb->prepare($sql_paginated, ...$params_paginated));
    
        $orders = [];
        
        // Process filtered orders
        if (!empty($get_filtered_orders)) {
            foreach ($get_filtered_orders as $key => $order) { 
                $currency = explode(':::', formipay_get_post_meta($order->form_id, 'product_currency'));
                $code = !empty($currency[0]) ? $currency[0] : '';   
                // Prepare order data
                $orders[] = [
                    'ID' => $order->id,
                    'form' => get_the_title($order->form_id),
                    'date' => $order->created_date,
                    'payment_gateway' => ucwords(str_replace('_', ' ', $order->payment_gateway)),
                    'status' => ucwords(str_replace('-', ' ', $order->status)),
                    'total' => [
                        'flag' => formipay_get_flag_by_currency($code),
                        'name' => $code,
                        'value' => formipay_price_format($order->total, $order->form_id),
                    ]
                ];
            }
        }
    
        // Prepare response data
        $response = [
            'results' => $orders,
            'total' => count($get_all_orders),
            'posts_report' =>  $order_status
        ];
    
        wp_send_json($response);
    }

    public function formipay_delete_order() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;

        $delete = $this->delete($order_id);

        if(is_wp_error( $delete )){
            wp_send_json_error( [
                'title' => esc_html__( 'Failed', 'formipay' ),
                'message' => esc_html__( 'Failed to delete ortder. Please try again.', 'formipay' ),
                'icon' => 'error'
            ] );
        }

        wp_send_json_success( [
            'title' => esc_html__( 'Deleted', 'formipay' ),
            'message' => esc_html__( 'Order is deleted permanently.', 'formipay' ),
            'icon' => 'success'
        ] );

    }

    public function formipay_bulk_delete_order() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        if( empty($_REQUEST['ids']) ){
            wp_send_json_error( [
                'title' => esc_html__( 'Failed', 'formipay' ),
                'message' => esc_html__( 'There is no coupon selected. Please try again.', 'formipay' ),
                'icon' => 'error'
            ] );
        }

        $ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : [];

        $success = 0;
        $failed = 0;
        $report = __( 'Done.', 'formipay' );
        if(!empty($ids)){
            foreach($ids as $id){
                $delete = $this->delete($id);
                if(is_wp_error( $delete )){
                    $failed++;
                }else{
                    $success++;
                }
            }
        }

        if($success > 0){
            $report .= sprintf( __( ' Deleted %d coupon(s).', 'formipay' ), $success);
        }
        if($failed > 0){
            $report .= sprintf( __( ' Failed %d coupon(s).', 'formipay' ), $failed);
        }

        wp_send_json_success( [
            'title' => esc_html__( 'Done!', 'formipay' ),
            'message' => $report,
            'icon' => 'info'
        ] );

    }

    public function formipay_load_order_data() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $order_id = isset($_REQUEST['order']) ? intval($_REQUEST['order']) : 0;

        wp_send_json(formipay_get_order($order_id));

    }

    public function formipay_change_order_status() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }
        
        $order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
        $status = isset($_REQUEST['status']) ? sanitize_text_field( wp_unslash($_REQUEST['status']) ) : '';
    
        if ($order_id > 0 && $status !== '') {
    
            $update = $this->update($order_id, ['status' => $status]);
    
            if (is_wp_error($update)) {
                wp_send_json_error([
                    'message' => $update->get_error_message(),
                    'code'    => $update->get_error_code(),
                ]);
            }
    
            wp_send_json_success([
                'message' => sprintf(
                    esc_html__('Change status order of #%d is success', 'formipay'),
                    $order_id
                ),
            ]);
        }
    
        wp_send_json_error([
            'message' => sprintf(
                esc_html__('Change status order of #%d is failed', 'formipay'),
                $order_id
            ),
        ]);
    }    

    public function formipay_check_editable_field() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $editable_field = [];

        $order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
        $get_order_data = formipay_get_order($order_id);

        $form_id = $get_order_data['form_id'];

        $field_types = formipay_field_type_collection();
        $form_field = formipay_get_post_meta($form_id, 'formipay_settings');
        $form_field = $form_field['fields'];

        unset($field_types['divider']);
        unset($field_types['page_break']);
        unset($field_types['country_list']);
        
        foreach($form_field as $key => $field){
            if(array_key_exists($field['field_type'], $field_types)){
                $skip = false;
                if(in_array($field['field_type'], ['select', 'checkbox', 'radio'])){
                    $options = $field['field_options'];
                    if(!empty($options)){
                        foreach($options as $option){
                            if('' !== $option['amount']){
                                if(isset($get_order_data['status']) && $get_order_data['status'] == 'completed'){
                                    $skip = true;
                                }
                            }
                        }
                    }
                }
                if(false == $skip){
                    $editable_field[$key] = $field;
                }
            }
        }

        wp_send_json($editable_field);

    }

    public function formipay_update_editable_field_data() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $raw_data = isset($_REQUEST['new_values']) ? wp_unslash( $_REQUEST['new_values'] ) : [];
        $data = is_array($raw_data) ? formipay_sanitize_array($raw_data) : sanitize_text_field($raw_data);

        $new_values = [];
        if(!empty($data)){
            foreach($data as $_data){
                $name = $_data['name'];
                $new_values[$name] = $_data['value'];
            }
        }

        $get_order_data = formipay_get_order($order_id);
        if(!empty($get_order_data)){
            $current_form_data = $get_order_data['form_data'];
    
            $new_form_data = [];
            foreach($current_form_data as $current_data){
                $field_name = $current_data['name'];
                $field_value = $current_data['value'];
                if(isset($new_values[$field_name])) {
                    $field_value = $new_values[$field_name];
                }
                $new_form_data[$field_name] = $field_value;
            }
    
            $update_form_data = $this->update($order_id, ['form_data' => $new_form_data]);
    
            if (is_wp_error($update_form_data)) {
                wp_send_json_error([
                    'message' => $update_form_data->get_error_message(),
                    'code'    => $update_form_data->get_error_code(),
                ]);
            }
    
            wp_send_json_success( [
                'message' => esc_html__( 'Succesfully change transaction data', 'formipay' )
            ] );
        }
    
        wp_send_json_error( [
            'message' => esc_html__( 'Error. Data is not available or not able to be changed. Try again.', 'formipay' )
        ] );

    }

    public function formipay_update_digital_access() {

        check_ajax_referer( 'formipay-order-details', '_wpnonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
        $method = isset($_REQUEST['method']) ? sanitize_text_field( wp_unslash($_REQUEST['method']) ) : '';
        $password = isset($_REQUEST['password']) ? sanitize_text_field( wp_unslash($_REQUEST['password']) ) : '';

        $get_order_data = $this->get($order_id);
        $meta_data = maybe_unserialize($get_order_data->meta_data);
        $meta_data['access_method'] = $method;
        if($method == 'static_password'){
            $meta_data['access_password'] = $password;
        }
        $update_meta_data = $this->update($order_id, ['meta_data' => $meta_data]);

        if(is_wp_error($update_meta_data)){
            wp_send_json_error([
                'message' => $update_meta_data->get_error_message(),
                'code'    => $update_meta_data->get_error_code(),
            ]);
        }

        wp_send_json_success( [
            'message' => esc_html__( 'Succesfully set access data', 'formipay' )
        ] );

    }

}