<?php
/**
 * @package WordPress
 * @subpackage Traveler
 * @since 1.0
 *
 * Class STGatewayZarinpal
 *
 * Zarinpal Payment Gateway for Traveler Theme
 * Supports Zarinpal REST API v4
 */
if (!class_exists('STGatewayZarinpal')) {
    class STGatewayZarinpal extends STAbstactPaymentGateway
    {
        static private $_ints;

        private $_gateway_id = 'st_zarinpal';

        function __construct()
        {
            add_filter('st_payment_gateway_st_zarinpal_name', array($this, 'get_name'));
        }

        static function instance()
        {
            if (!self::$_ints) {
                self::$_ints = new self();
            }
            return self::$_ints;
        }

        static function add_payment($payment)
        {
            $payment['st_zarinpal'] = self::instance();
            return $payment;
        }

        function html()
        {
            echo st()->load_template('gateways/zarinpal');
        }

        /**
         * Pre-checkout validation
         */
        function _pre_checkout_validate()
        {
            $merchant_id = st()->get_option('zarinpal_merchant_id', '');
            if (empty($merchant_id)) {
                STTemplate::set_message(__('مرچنت آیدی زرین‌پال تنظیم نشده است.', 'traveler'), 'danger');
                return false;
            }
            return true;
        }

        /**
         * Process checkout - create payment request and redirect to Zarinpal
         */
        function do_checkout($order_id)
        {
            $merchant_id = st()->get_option('zarinpal_merchant_id', '');
            $sandbox = st()->get_option('zarinpal_enable_sandbox', 'off');
            $description = st()->get_option('zarinpal_description', __('پرداخت رزرو', 'traveler'));

            if (empty($merchant_id)) {
                return array(
                    'status' => false,
                    'message' => __('مرچنت آیدی زرین‌پال تنظیم نشده است.', 'traveler')
                );
            }

            $total = get_post_meta($order_id, 'total_price', true);
            $total = floatval($total);

            if ($total <= 0) {
                return array(
                    'status' => false,
                    'message' => __('مبلغ پرداخت نامعتبر است.', 'traveler')
                );
            }

            // Convert to Toman (Zarinpal expects amount in Toman/RIAL)
            $currency = TravelHelper::get_current_currency('name');
            $amount = $this->convert_amount($total, $currency);

            $callback_url = $this->get_return_url($order_id);

            $api_url = ($sandbox == 'on') 
                ? 'https://sandbox.zarinpal.com/pg/v4/payment/request.json'
                : 'https://api.zarinpal.com/pg/v4/payment/request.json';

            $params = array(
                'merchant_id' => sanitize_text_field($merchant_id),
                'amount' => intval($amount),
                'callback_url' => esc_url_raw($callback_url),
                'description' => sanitize_text_field($description),
            );

            $args = array(
                'body' => json_encode($params),
                'headers' => array(
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json'
                ),
                'timeout' => 30,
                'sslverify' => false
            );

            $response = wp_remote_post($api_url, $args);

            if (is_wp_error($response)) {
                return array(
                    'status' => false,
                    'message' => $response->get_error_message()
                );
            }

            $body = wp_remote_retrieve_body($response);
            $result = json_decode($body, true);

            if (empty($result) || !isset($result['data'])) {
                return array(
                    'status' => false,
                    'message' => __('پاسخ نامعتبر از زرین‌پال.', 'traveler')
                );
            }

            $data = $result['data'];

            if (isset($data['code']) && $data['code'] == 100) {
                $authority = sanitize_text_field($data['authority']);
                
                // Save authority to order meta for verification
                update_post_meta($order_id, 'zarinpal_authority', $authority);
                update_post_meta($order_id, 'zarinpal_amount', $amount);

                $start_pay_url = ($sandbox == 'on')
                    ? 'https://sandbox.zarinpal.com/pg/StartPay/' . $authority
                    : 'https://www.zarinpal.com/pg/StartPay/' . $authority;

                return array(
                    'status' => true,
                    'redirect' => $start_pay_url
                );
            } else {
                $error_message = isset($result['errors']['message']) ? $result['errors']['message'] : __('درخواست پرداخت ناموفق بود.', 'traveler');
                if (is_array($error_message)) {
                    $error_message = implode(', ', $error_message);
                }
                return array(
                    'status' => false,
                    'message' => $error_message
                );
            }
        }

        /**
         * Verify payment after callback from Zarinpal
         */
        function check_complete_purchase($order_id)
        {
            $authority = isset($_GET['Authority']) ? sanitize_text_field($_GET['Authority']) : '';
            $status = isset($_GET['Status']) ? sanitize_text_field($_GET['Status']) : '';

            if (empty($authority)) {
                return array(
                    'status' => false,
                    'message' => __('کد Authority یافت نشد.', 'traveler')
                );
            }

            if ($status !== 'OK') {
                return array(
                    'status' => false,
                    'message' => st()->get_option('zarinpal_failure_message', __('پرداخت لغو یا ناموفق بود.', 'traveler'))
                );
            }

            $saved_authority = get_post_meta($order_id, 'zarinpal_authority', true);
            if ($saved_authority !== $authority) {
                return array(
                    'status' => false,
                    'message' => __('عدم تطابق Authority.', 'traveler')
                );
            }

            $merchant_id = st()->get_option('zarinpal_merchant_id', '');
            $sandbox = st()->get_option('zarinpal_enable_sandbox', 'off');
            $amount = get_post_meta($order_id, 'zarinpal_amount', true);

            $api_url = ($sandbox == 'on')
                ? 'https://sandbox.zarinpal.com/pg/v4/payment/verify.json'
                : 'https://api.zarinpal.com/pg/v4/payment/verify.json';

            $params = array(
                'merchant_id' => sanitize_text_field($merchant_id),
                'authority' => $authority,
                'amount' => intval($amount)
            );

            $args = array(
                'body' => json_encode($params),
                'headers' => array(
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json'
                ),
                'timeout' => 30,
                'sslverify' => false
            );

            $response = wp_remote_post($api_url, $args);

            if (is_wp_error($response)) {
                return array(
                    'status' => false,
                    'message' => $response->get_error_message()
                );
            }

            $body = wp_remote_retrieve_body($response);
            $result = json_decode($body, true);

            if (empty($result) || !isset($result['data'])) {
                return array(
                    'status' => false,
                    'message' => __('پاسخ تایید نامعتبر است.', 'traveler')
                );
            }

            $data = $result['data'];

            // Successful verification codes: 100 (paid) or 101 (already verified)
            if (isset($data['code']) && ($data['code'] == 100 || $data['code'] == 101)) {
                $ref_id = isset($data['ref_id']) ? sanitize_text_field($data['ref_id']) : '';
                $card_pan = isset($data['card_pan']) ? sanitize_text_field($data['card_pan']) : '';
                
                update_post_meta($order_id, 'zarinpal_ref_id', $ref_id);
                update_post_meta($order_id, 'zarinpal_card_pan', $card_pan);
                update_post_meta($order_id, 'zarinpal_payment_status', 'completed');

                return array(
                    'status' => true
                );
            } else {
                $error_message = isset($result['errors']['message']) ? $result['errors']['message'] : __('تاییدیه پرداخت ناموفق بود.', 'traveler');
                if (is_array($error_message)) {
                    $error_message = implode(', ', $error_message);
                }
                return array(
                    'status' => false,
                    'message' => $error_message
                );
            }
        }

        /**
         * Convert amount to currency accepted by Zarinpal
         * Zarinpal accepts amount in Toman (IRT) or Rial
         */
        private function convert_amount($amount, $currency)
        {
            $currency = strtoupper($currency);
            
            // If currency is already IRT or TOMAN, return as-is
            if (in_array($currency, array('IRT', 'TOMAN'))) {
                return $amount;
            }
            
            // If currency is IRR (Rial), divide by 10
            if ($currency == 'IRR') {
                return $amount / 10;
            }
            
            // For other currencies, you may need to implement a conversion rate
            // Default: assume amount is in Toman
            return $amount;
        }

        /**
         * Package checkout support
         */
        function package_do_checkout($order_id)
        {
            return $this->do_checkout($order_id);
        }

        function package_completed_checkout($order_id)
        {
            return $this->check_complete_purchase($order_id);
        }

        function get_name()
        {
            $name = st()->get_option('zarinpal_name', '');
            return !empty($name) ? $name : __('زرین‌پال', 'traveler');
        }

        function get_option_fields()
        {
            return array(
                array(
                    'id' => 'zarinpal_name',
                    'label' => __('نام درگاه', 'traveler'),
                    'desc' => __('نامی که در صفحه پرداخت نمایش داده می‌شود', 'traveler'),
                    'type' => 'text',
                    'section' => 'option_pmgateway',
                    'std' => __('زرین‌پال', 'traveler'),
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_logo',
                    'label' => __('لوگو', 'traveler'),
                    'desc' => __('آپلود تصویر لوگوی درگاه', 'traveler'),
                    'type' => 'upload',
                    'section' => 'option_pmgateway',
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_merchant_id',
                    'label' => __('مرچنت آیدی', 'traveler'),
                    'desc' => __('مرچنت آیدی زرین‌پال خود را وارد کنید (فرمت UUID)', 'traveler'),
                    'type' => 'text',
                    'section' => 'option_pmgateway',
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_enable_sandbox',
                    'label' => __('حالت تست (سندباکس)', 'traveler'),
                    'desc' => __('فعال کردن حالت تست برای بررسی', 'traveler'),
                    'type' => 'on-off',
                    'section' => 'option_pmgateway',
                    'std' => 'off',
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_description',
                    'label' => __('توضیحات پرداخت', 'traveler'),
                    'desc' => __('توضیحاتی که در صفحه پرداخت زرین‌پال نمایش داده می‌شود', 'traveler'),
                    'type' => 'text',
                    'section' => 'option_pmgateway',
                    'std' => __('پرداخت رزرو', 'traveler'),
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_success_message',
                    'label' => __('پیام موفقیت', 'traveler'),
                    'desc' => __('پیامی که بعد از پرداخت موفق نمایش داده می‌شود', 'traveler'),
                    'type' => 'text',
                    'section' => 'option_pmgateway',
                    'std' => __('پرداخت شما با موفقیت انجام شد.', 'traveler'),
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
                array(
                    'id' => 'zarinpal_failure_message',
                    'label' => __('پیام خطا', 'traveler'),
                    'desc' => __('پیامی که بعد از پرداخت ناموفق یا لغو شده نمایش داده می‌شود', 'traveler'),
                    'type' => 'text',
                    'section' => 'option_pmgateway',
                    'std' => __('پرداخت لغو یا ناموفق بود. لطفاً دوباره تلاش کنید.', 'traveler'),
                    'condition' => 'pm_gway_' . $this->_gateway_id . '_enable:is(on)'
                ),
            );
        }

        function get_default_status()
        {
            return false;
        }

        function get_logo()
        {
            $logo = st()->get_option('zarinpal_logo', '');
            if (!empty($logo)) {
                return $logo;
            }
            return ST_TRAVELER_URI . '/img/gateway/nm-logo.png';
        }

        function is_check_complete_required()
        {
            return true;
        }

        function getGatewayId()
        {
            return $this->_gateway_id;
        }

        /**
         * Check payment method for all items or specific is enable
         */
        function is_available($item_id = false)
        {
            $result = false;
            if (st()->get_option('pm_gway_st_zarinpal_enable') == 'on') {
                $result = true;
            }
            if ($item_id) {
                $meta = get_post_meta($item_id, 'is_meta_payment_gateway_st_zarinpal', true);
                if ($meta == 'off') {
                    $result = false;
                } else {
                    $result = true;
                }
            }
            return $result;
        }
    }

    add_filter('st_payment_gateways', array('STGatewayZarinpal', 'add_payment'));
}
