<?php

namespace App\Services\Integrations;

use App\Models\IntegrationWebhookEvent;
use Illuminate\Support\Str;

class IntegrationWebhookRecorder
{
    /**
     * @param  array<string, mixed>  $context
     */
    public function recordReceived(string $provider, ?string $eventId, ?string $eventType, array $context = []): IntegrationWebhookEvent
    {
        return IntegrationWebhookEvent::create([
            'provider' => $provider,
            'event_id' => $eventId,
            'event_type' => $eventType,
            'status' => IntegrationWebhookEvent::STATUS_RECEIVED,
            'received_at' => now(),
            'context' => $context,
        ]);
    }

    /**
     * @param  array<string, mixed>  $context
     */
    public function markProcessed(IntegrationWebhookEvent $event, array $context = []): IntegrationWebhookEvent
    {
        $event->forceFill([
            'status' => IntegrationWebhookEvent::STATUS_PROCESSED,
            'processed_at' => now(),
            'context' => $this->mergeContext($event, $context),
        ])->save();

        return $event;
    }

    /**
     * @param  array<string, mixed>  $context
     */
    public function markIgnored(IntegrationWebhookEvent $event, array $context = []): IntegrationWebhookEvent
    {
        $event->forceFill([
            'status' => IntegrationWebhookEvent::STATUS_IGNORED,
            'processed_at' => now(),
            'context' => $this->mergeContext($event, $context),
        ])->save();

        return $event;
    }

    /**
     * @param  array<string, mixed>  $context
     */
    public function markFailed(IntegrationWebhookEvent $event, string $message, array $context = []): IntegrationWebhookEvent
    {
        $event->forceFill([
            'status' => IntegrationWebhookEvent::STATUS_FAILED,
            'failed_at' => now(),
            'error_message' => Str::limit($message, 500, ''),
            'context' => $this->mergeContext($event, $context),
        ])->save();

        return $event;
    }

    /**
     * @param  array<string, mixed>  $context
     * @return array<string, mixed>
     */
    private function mergeContext(IntegrationWebhookEvent $event, array $context): array
    {
        $existing = $event->context ?? [];

        if (! is_array($existing)) {
            $existing = [];
        }

        return array_merge($existing, $context);
    }
}
