<?php

namespace Formatrica\Submission\Pipeline\Stages;

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

use Formatrica\Submission\Integration_Queue;
use Formatrica\Submission\Integrations\Dispatchers\Generic_Webhook_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\Hubspot_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\Mailchimp_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\Salesforce_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\Slack_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\Webhook_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\WooCommerce_Dispatcher;
use Formatrica\Submission\Integrations\Dispatchers\WordPress_Post_Dispatcher;
use Formatrica\Submission\Pipeline\Submission_Context;
use Formatrica\Submission\Pipeline\Submission_Stage;

/**
 * Dispatch the general webhook and all enabled third-party integrations —
 * async via the queue where applicable, otherwise synchronously.
 */
final class Integration_Dispatch_Stage implements Submission_Stage
{
    public function __construct(private Integration_Queue $integration_queue)
    {
    }

    public function handle(Submission_Context $ctx): void
    {
        // Deferred until the payment confirms (webhook re-runs this stage).
        if ($ctx->early_payment_response !== null) {
            return;
        }

        $options = $ctx->options;
        $form = $ctx->form;
        $payload = $ctx->sanitised;
        $context = $ctx->context;
        $field_meta = $ctx->field_meta;

        // Dispatch general webhook
        if (!empty($options['webhooks']['enabled'])) {
            $dispatcher = new Webhook_Dispatcher();
            $dispatcher->dispatch($options['webhooks'], $form, $payload, $context, $field_meta);
        }

        // Dispatch third-party integrations
        $integrations = $options['integrations'] ?? [];

        if (empty($integrations) || !is_array($integrations)) {
            return;
        }

        foreach ($integrations as $integration_id => $settings) {
            if (!is_array($settings) || empty($settings['enabled'])) {
                continue;
            }

            $integration_context = array_merge($context, [
                'integration' => $integration_id,
            ]);

            // Check if this integration should be queued for async processing
            if ($this->integration_queue->should_queue($integration_id)) {
                $this->integration_queue->enqueue(
                    $integration_id,
                    $settings,
                    $form,
                    $payload,
                    $integration_context,
                    $field_meta
                );
                continue;
            }

            // Run synchronously (local integrations: WordPress Post, WooCommerce, etc.)
            $dispatcher = $this->get_integration_dispatcher($integration_id);

            if ($dispatcher) {
                $dispatcher->dispatch($settings, $form, $payload, $integration_context, $field_meta);
            } else {
                /**
                 * Fires when an integration ID is not handled by core dispatchers.
                 *
                 * @param string $integration_id
                 * @param array<string, mixed> $settings
                 * @param array<string, mixed> $form
                 * @param array<string, mixed> $payload
                 * @param array<string, mixed> $integration_context
                 * @param array<int, array<string, mixed>> $field_meta
                 */
                do_action(
                    'formatrica_integration_dispatch',
                    $integration_id,
                    $settings,
                    $form,
                    $payload,
                    $integration_context,
                    $field_meta
                );
            }
        }
    }

    private function get_integration_dispatcher(string $integration_id): ?object
    {
        switch ($integration_id) {
            case 'zapier':
            case 'make':
                return new Generic_Webhook_Dispatcher($integration_id);
            case 'slack':
                return new Slack_Dispatcher();
            case 'mailchimp':
                return new Mailchimp_Dispatcher();
            case 'salesforce':
                // Pro integration, stripped from Free packages. class_exists so a
                // grandfathered config degrades to the fallback action, not a fatal.
                return class_exists(Salesforce_Dispatcher::class) ? new Salesforce_Dispatcher() : null;
            case 'hubspot':
                return class_exists(Hubspot_Dispatcher::class) ? new Hubspot_Dispatcher() : null;
            case 'wordpress_post':
                return new WordPress_Post_Dispatcher();
            case 'woocommerce':
                return new WooCommerce_Dispatcher();
            default:
                return null;
        }
    }
}
