<?php

declare(strict_types=1);

namespace PhpWA\Integration;

use InvalidArgumentException;
use PhpWA\Exception\ProtocolException;
use PhpWA\Runtime\Deadline;
use PhpWA\Runtime\OutboxHandlerInterface;
use PhpWA\Storage\OutboxEvent;

/**
 * Framework-neutral bridge suitable for an EasyChat service callback.
 * The callback receives the stable event ID first so it can enforce a UNIQUE
 * idempotency constraint before applying the event.
 */
final class CallableOutboxHandler implements OutboxHandlerInterface
{
    /** @var callable */ private $callback;
    public function __construct(callable $callback) { $this->callback = $callback; }

    public function handle(string $accountId, OutboxEvent $event, Deadline $deadline): void
    {
        try { $payload = json_decode($event->payload(), true, 128, JSON_THROW_ON_ERROR); }
        catch (\Throwable $error) { throw new ProtocolException('Committed outbox JSON became malformed.', 0, $error); }
        if (!is_array($payload)) { throw new ProtocolException('Committed outbox payload must be a JSON object or array.'); }
        $result = ($this->callback)(
            $event->id(), $accountId, $event->type(), $payload,
            $event->occurredAt(), $event->attempts(), $deadline
        );
        if ($result !== null && $result !== true) {
            throw new InvalidArgumentException('Outbox callback must return true or null after a durable commit.');
        }
    }
}
