<?php
/**
 * A class to deliver info to a webhook.
 *
 * @since 3.0.0
 */

declare( strict_types=1 );
namespace FeData\FastEvents\Hooks\Actions;

defined( 'ABSPATH' ) || exit;

use FeData\FastEvents\Hooks\Webhooks\AbstractWebhook;
use FeData\FastEvents\Hooks\Webhooks\Topic\EventTopic;
use FeData\FastEvents\Hooks\Webhooks\Topic\InvoiceTopic;
use FeData\FastEvents\Hooks\Webhooks\Topic\OrderTopic;
use FeData\FastEvents\Hooks\Webhooks\Topic\ScanTopic;
use FeData\FastEvents\Hooks\Webhooks\Topic\TicketTopic;
use FeData\FastEvents\Logging\LoggerFactory;

/**
 * A class to deliver info to a webhook.
 */
final class WebhookAction {

	/**
	 * WebhookAction constructor.
	 *
	 * @since 3.0.0
	 *
	 * @param LoggerFactory $logger Logger.
	 */
	public function __construct( private readonly LoggerFactory $logger ) {
	}


	/**
	 * Action to deliver info to a webhook.
	 *
	 * @since 1.0
	 *
	 * @param int   $webhook_id      Webhook identifier.
	 * @param mixed $arg             Identifier. Can be an event_id, order_id, or a qrcode with a level structure.
	 * @param array $retry_scheme    Array of intervals for retrying.
	 * @param int   $retry_position  Position in the retry_scheme.
	 */
	public function webhook( int $webhook_id, mixed $arg, array $retry_scheme, int $retry_position ): void {
		global $wpdb;
		global $fevt_container;

		// Check if the webhook still exists.
		$webhook = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_event_webhooks WHERE id = %d", $webhook_id ) );
		if ( empty( $webhook ) ) {
			// Webhook not found. Most likely it was removed, hence we log it and return.
			$this->logger->error(
				'Webhook #' . $webhook_id . ' not found, may have been removed. Pending action is deleted',
				array(
					'type' => 'Webhook',
				)
			);
			$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}fe_event_webhooks SET pending=GREATEST(0, pending-1) WHERE id = %d", $webhook->id ) );
			return;
		}

		// Pick the right handler.
		list( $main_topic, $sub_topic ) = explode( '.', $webhook->topic, 2 );
		$hook                           = null;
		switch ( $main_topic ) {
			case 'event':
				$hook = $fevt_container->get( EventTopic::class );
				break;
			case 'order':
				$hook = $fevt_container->get( OrderTopic::class );
				break;
			case 'scan':
				$hook = $fevt_container->get( ScanTopic::class );
				break;
			case 'tickets':
				$hook = $fevt_container->get( TicketTopic::class );
				break;
			case 'invoice':
				$hook = $fevt_container->get( InvoiceTopic::class );
				break;
		}
		if ( ! is_null( $hook ) ) {
			$hook->set_retry_position( $retry_position );
			$hook->set_retry_scheme( $retry_scheme );
			$hook->set_arg( $arg );
			$hook->dispatch( $sub_topic, $webhook, $arg );
		}
	}
}
