<?php
/**
 * Background polling for a Form TWINT order — mirror of
 * TwintGateway::monitor_order_background_task but routed through the
 * Form-scoped TwintCore so OrderDataRepository's meta + reference reads land
 * on the p4all_order shim instead of the shop order lookup.
 *
 * Hooked on:
 *   p4all_form_monitor_order_immediate  → fired in the same request after start_order
 *   p4all_form_monitor_order            → fired on shutdown for long-poll fallback
 *
 * The TWINT engine itself does the polling; we only need to wire the action
 * to the engine entry point. The engine writes status updates back into the
 * order meta, and on confirmed payment FormWebhookHandler / the engine flips
 * the p4all_order to `paid`.
 */

namespace Twnt4All\Pay4All;

use Twnt4All\Support\Journal;

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

final class FormBackgroundMonitor
{
    public static function register() : void
    {
        // The original p4all_form_monitor_order[_immediate] actions are
        // intercepted by FormMonitorJob / FormImmediateMonitorJob which spawn
        // a non-blocking HTTP loopback. The actual SOAP polling happens on
        // the wp_async_* counterpart — that's what we hook here.
        add_action( 'wp_async_p4all_form_monitor_order',           [ self::class, 'run' ], 10, 3 );
        add_action( 'wp_async_p4all_form_monitor_order_immediate', [ self::class, 'run' ], 10, 3 );
    }

    /**
     * @param int    $order_id
     * @param string $order_uuid
     * @param int    $time
     */
    public static function run( $order_id, $order_uuid, $time = 0 ) : void
    {
        $order_id = (int) $order_id;
        if ( $order_id <= 0 ) { return; }

        // Defensive: only act on actual Form orders. Belt-and-braces in case
        // a misregistered hook would route a WC order here.
        if ( ! FormOrderShim::is_form_order_id( $order_id ) ) {
            return;
        }

        if ( ! defined( 'T4A_MERCHANT_UUID' ) || ! T4A_MERCHANT_UUID ) {
            Journal::error( 'FormBackgroundMonitor: T4A_MERCHANT_UUID missing' );
            return;
        }

        try {
            $twint = FormTwintCore::create_for_transaction( $order_id, T4A_MERCHANT_UUID );
            if ( ! $twint ) {
                Journal::error( sprintf( 'FormBackgroundMonitor: FormTwintCore null for order %d', $order_id ) );
                return;
            }

            // Cross-check the saved UUID against the one passed in — same
            // guard as TwintGateway::monitor_order_background_task.
            $saved_uuid = $twint->dataProvider->get_order_uuid( false );
            if ( $order_uuid !== '' && $saved_uuid !== '' && $saved_uuid !== $order_uuid ) {
                Journal::error( sprintf(
                    'FormBackgroundMonitor: order UUID mismatch (expected %s, got %s) for order %d',
                    $saved_uuid, $order_uuid, $order_id
                ) );
                return;
            }

            $twint->transactionHandler->background_task( (int) $time );

        } catch ( \Throwable $e ) {
            Journal::error( sprintf(
                'FormBackgroundMonitor exception: %s in %s:%d',
                $e->getMessage(), $e->getFile(), $e->getLine()
            ) );
        }
    }
}
