<?php
/**
 * Launches a TWINT SOAP charge for a Pay4All Form order.
 *
 * Mirrors TwintGateway::start_twint_payment_process for WC: build a TwintCore
 * (with the Form-scoped data provider + event handler), let TransactionService
 * fire StartOrder against the merchant's TWINT-Soap endpoint, and return the
 * payment URL TWINT replies with.
 *
 * The customer's browser is then redirected to that URL (TWINT pairing page);
 * TWINT confirms the payment server-side and calls back to FormWebhookHandler
 * which marks the p4all_order as paid.
 *
 * If StartOrder fails we keep the order in `pending` and surface a useful
 * error message so the customer (and the merchant in browser devtools) sees
 * what actually went wrong.
 */

namespace Twnt4All\Pay4All;

use Twnt4All\Support\Journal;

if ( ! defined( 'ABSPATH' ) ) { exit; }

final class FormPaymentLauncher
{
    /**
     * @param int $order_id   p4all_order post ID
     * @return array{success:bool,redirect_url:string,error?:string}
     */
    public static function launch( int $order_id ) : array
    {
        $shim = new FormOrderShim( $order_id );
        if ( ! $shim->is_loaded() ) {
            Journal::error( sprintf( 'FormPaymentLauncher: order %d not found (post not a p4all_order).', $order_id ) );
            return [ 'success' => false, 'redirect_url' => '', 'error' => 'order_not_found' ];
        }

        if ( strtoupper( $shim->get_currency() ) !== 'CHF' ) {
            return [ 'success' => false, 'redirect_url' => '', 'error' => 'unsupported_currency' ];
        }

        if ( ! defined( 'T4A_MERCHANT_UUID' ) || ! T4A_MERCHANT_UUID ) {
            return [
                'success'      => false,
                'redirect_url' => '',
                'error'        => 'TWINT init: aucun UID magasin configuré (Réglages > Pay4all TWINT > étape 3).',
            ];
        }

        // Make the shim discoverable by OrderDataRepository::save/delete_order_data
        // (which run inside the SOAP engine when it stores transaction_id etc.)
        FormOrderRegistry::register( $shim );

        // Stash the referer so the shim's get_checkout_payment_url() can send
        // the user back to the form on cancel/error/timeout.
        if ( ! empty( $_SERVER[ 'HTTP_REFERER' ] ) ) {
            update_post_meta( $order_id, '_p4all_form_referer',
                esc_url_raw( wp_unslash( (string) $_SERVER[ 'HTTP_REFERER' ] ) )
            );
        }

        try {
            $twint = FormTwintCore::create_for_transaction( $order_id, T4A_MERCHANT_UUID );

            if ( ! $twint ) {
                Journal::error( sprintf( 'FormPaymentLauncher: FormTwintCore returned null for order %d.', $order_id ) );
                return [
                    'success'      => false,
                    'redirect_url' => '',
                    'error'        => 'TWINT init: impossible de créer la session SOAP (certificat ou identifiants manquants).',
                ];
            }

            // Flag the order as "TWINT initiated" so any duplicate submit
            // surfaces the same status instead of double-charging.
            update_post_meta( $order_id, '_p4all_twint_initiated', time() );

            $url = $twint->transactionHandler->start_order();

            if ( ! $url ) {
                Journal::error( sprintf( 'FormPaymentLauncher: start_order returned empty for order %d.', $order_id ) );
                return [
                    'success'      => false,
                    'redirect_url' => '',
                    'error'        => 'TWINT init: start_order n\'a pas renvoyé d\'URL. Consultez les logs serveur.',
                ];
            }

            return [ 'success' => true, 'redirect_url' => (string) $url ];

        } catch ( \Throwable $e ) {
            Journal::error( sprintf(
                'FormPaymentLauncher engine_error: %s in %s:%d',
                $e->getMessage(),
                $e->getFile(),
                $e->getLine()
            ) );
            return [
                'success'      => false,
                'redirect_url' => '',
                'error'        => 'TWINT engine: ' . $e->getMessage(),
            ];
        }
    }
}
