<?php

// phpcs:disable WordPress.WP.I18n.TextDomainMismatch -- Bridge to pay4all-for-twint :
// this WooCommerce integration re-emits the TWINT gateway strings the free
// plugin already ships and translates. Reusing its text domain avoids
// duplicating dozens of msgids × 4 locales in pay4all-pro's .po files.

namespace Twnt4All\Wallet;

use Twnt4All\Checkout\OrderDataRepository;
use Twnt4All\Support\Journal;
use Twnt4All\Support\WpBridge;
use Twnt4All\Mixin\OrderAwareTrait;

if ( !defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

abstract class WalletPaymentHandler
{
    use OrderAwareTrait;

    const TYPE_PAYMENT       = 'payment';
    const TYPE_REGISTRATION  = 'registration';
    const TYPE_ALIAS_PAYMENT = 'alias_payment';

    const STATUS_PENDING    = 'pending';
    const STATUS_AUTHORIZED = 'authorized';
    const STATUS_CAPTURED   = 'captured';
    const STATUS_FAILED     = 'failed';
    const STATUS_CANCELLED  = 'cancelled';

    const CONTEXT_CHECKOUT = 'checkout';
    const CONTEXT_ADMIN    = 'admin';

    /** @var \WC_Order */
    protected $order;

    /** @var string */
    protected $transaction_id;

    /** @var string */
    protected $refno;

    /** @var string */
    protected $deferred = false;

    /** @var string */
    private $redirect_key;

    protected $gateway;

    protected $is_add_pm;

    protected $context;

    public function __construct( $order, $gateway = null, $is_add_pm = false, $context = self::CONTEXT_CHECKOUT )
    {
        $this->gateway   = $gateway;
        $this->is_add_pm = $is_add_pm;
        $this->context   = $context;
        $this->order     = $order;
        $this->refno     = $this->get_or_create_reference_number();

        if ( get_option( 't4a_twint_settings_payment_type' ) == 'deferred' ) {
            $this->deferred = true;
        }
    }

    /**
     * Rewrites the gateway return URL if the Polylang plugin is active.
     */
    public static function add_polylang_fix()
    {
        include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
        if ( is_plugin_active( 'polylang/polylang.php' ) ) {
            if ( function_exists( 'pll_current_language' ) ) {
                add_filter( 'woocommerce_api_request_url', function ( $api_request_url, $request, $ssl ) {
                    if ( is_null( $ssl ) ) {
                        $scheme = wp_parse_url( home_url(), PHP_URL_SCHEME );
                    } elseif ( $ssl ) {
                        $scheme = 'https';
                    } else {
                        $scheme = 'http';
                    }

                    $current_lang = pll_current_language( 'slug' );

                    $pll_options = get_option( 'polylang' );
                    if ( !empty( $pll_options[ 'hide_default' ] ) && $pll_options[ 'default_lang' ] === $current_lang ) {
                        return $api_request_url;
                    }

                    if ( strstr( get_option( 'permalink_structure' ), '/index.php/' ) ) {
                        $api_request_url = trailingslashit( home_url( '/' . $current_lang . '/index.php/wc-api/' . $request, $scheme ) );
                    } elseif ( get_option( 'permalink_structure' ) ) {
                        $api_request_url = trailingslashit( home_url( '/' . $current_lang . '/wc-api/' . $request, $scheme ) );
                    } else {
                        $api_request_url = add_query_arg( 'wc-api', $request, trailingslashit( home_url( '', $scheme ) ) );
                    }

                    return $api_request_url;
                }, 10, 3 );

            }
        }
    }

    /**
     * Returns the order total multiplied by 100 and without decimals.
     *
     * @return mixed
     * @internal param $order
     */
    protected function get_formatted_total()
    {
        return wc_format_decimal( $this->order->get_total(), 2 );
    }

    /**
     * Generates a new unique reference number from the order number.
     * @return string
     * @internal param $order
     */
    protected function get_or_create_reference_number()
    {
        $reference = OrderDataRepository::get_order_data( $this->order, 'reference' );

        if ( empty( $reference ) ) {

            if ( !empty( $this->shop_prefix ) ) {
                $reference = preg_replace( "/[^A-Za-z0-9]/", "", $this->shop_prefix ) . '_';
            }

            $reference .= $this->order->get_order_number();

            // Additional customer data.
            $add_billing_firstname = get_option( 't4a_twint_reference_include_billing_firstname' );
            if ( $add_billing_firstname && $add_billing_firstname == 'yes' ) {
                $bfn = $this->order->get_billing_first_name();
                if ( !empty( $bfn ) ) {
                    $reference .= '_' . $bfn;
                }
            }

            $add_billing_lastname = get_option( 't4a_twint_reference_include_billing_lastname' );
            if ( $add_billing_lastname && $add_billing_lastname == 'yes' ) {
                $bln = $this->order->get_billing_last_name();
                if ( !empty( $bln ) ) {
                    $reference .= '_' . $bln;
                }
            }

            $add_billing_company = get_option( 't4a_twint_reference_include_billing_company' );
            if ( $add_billing_company && $add_billing_company == 'yes' ) {
                $bc = $this->order->get_billing_company();
                if ( !empty( $bc ) ) {
                    $reference .= '_' . $bc;
                }
            }

            $add_shipping_firstname = get_option( 't4a_twint_reference_include_shipping_firstname' );
            if ( $add_shipping_firstname && $add_shipping_firstname == 'yes' ) {
                $sfn = $this->order->get_shipping_first_name();
                if ( !empty( $sfn ) ) {
                    $reference .= '_' . $sfn;
                }
            }

            $add_shipping_lastname = get_option( 't4a_twint_reference_include_shipping_lastname' );
            if ( $add_shipping_lastname && $add_shipping_lastname == 'yes' ) {
                $sln = $this->order->get_shipping_last_name();
                if ( !empty( $sln ) ) {
                    $reference .= '_' . $sln;
                }
            }

            $add_shipping_company = get_option( 't4a_twint_reference_include_shipping_company' );
            if ( $add_shipping_company && $add_shipping_company == 'yes' ) {
                $sc = $this->order->get_shipping_company();
                if ( !empty( $sc ) ) {
                    $reference .= '_' . $sc;
                }
            }

            $reference = iconv( 'UTF-8', 'ASCII//TRANSLIT', $reference );
            $reference = preg_replace( '/[^\s\w-]/u', '', $reference );
            $reference = mb_substr( $reference, 0, 35, 'utf-8' );
            $reference .= '_' . uniqid();

            OrderDataRepository::save_order_data( $this->order->get_id(), [ 'reference' => $reference ] );
        }

        return $reference;
    }

    protected function get_transaction_id()
    {
        if ( $this->transaction_id ) {
            return $this->transaction_id;
        }

        return OrderDataRepository::get_order_data( $this->order, 'transaction_id' );
    }


    protected function get_webhook_url()
    {
        return add_query_arg(
            [
                'order_id'     => $this->order->get_id(),
                'order_number' => $this->order->get_order_number()
            ], \WC()->api_request_url( T4A_PREFIX . '_transaction_webhook' ) );
    }

    protected function get_redirect_url()
    {
        return add_query_arg(
            [
                'order_id'     => $this->order->get_id(),
                'order_number' => $this->order->get_order_number(),
                's'            => $this->get_redirect_key(),
            ], \WC()->api_request_url( T4A_PREFIX . '_transaction_redirect' ) );
    }

    protected function get_cancel_url()
    {
        return add_query_arg(
            [
                'order_id'     => $this->order->get_id(),
                'order_number' => $this->order->get_order_number(),
                's'            => $this->get_redirect_key(),
            ], \WC()->api_request_url( T4A_PREFIX . '_transaction_cancel' ) );
    }

    protected function get_redirect_key()
    {
        if ( !$this->redirect_key ) {

            $data = [
                'order_id'           => $this->order->get_id(),
                'amount'             => $this->order->get_total(),
                'currency'           => $this->order->get_currency(),
                'billing_first_name' => $this->order->get_billing_first_name(),
                'billing_last_name'  => $this->order->get_billing_last_name(),
                'billing_postcode'   => $this->order->get_billing_postcode(),
                'integration'        => 'twnt',
            ];

            $data_str           = http_build_query( $data, '', ';' );
            $this->redirect_key = WpBridge::create_hash_key( $data_str, 1 );
        }

        return $this->redirect_key;
    }

    public static function get_transaction_type_text( $id )
    {
        switch ( $id ) {
            case static::TYPE_REGISTRATION:
                return __( 'Registration', 'pay4all-for-twint' );
            case static::TYPE_ALIAS_PAYMENT:
                return __( 'Alias payment', 'pay4all-for-twint' );
            case static::TYPE_PAYMENT:
            default:
                return __( 'Payment', 'pay4all-for-twint' );
        }
    }

    public static function get_transaction_status_text( $id )
    {
        switch ( $id ) {
            case static::STATUS_PENDING:
                return __( 'Pending', 'pay4all-for-twint' );
            case static::STATUS_CAPTURED:
                return __( 'Captured', 'pay4all-for-twint' );
            case static::STATUS_FAILED:
                return __( 'Failed', 'pay4all-for-twint' );
            case static::STATUS_CANCELLED:
                return __( 'Cancelled', 'pay4all-for-twint' );
            case static::STATUS_AUTHORIZED:
                return __( 'Authorized', 'pay4all-for-twint' );
            default:
                return '';
        }
    }
}
