<?php

namespace Tests\Feature\Jobs;

use App\Jobs\SendGuestPushNotificationBatch;
use App\Models\Event;
use App\Models\GuestNotification;
use App\Models\PushSubscription;
use App\Models\Tenant;
use App\Services\Push\WebPushDispatcher;
use App\Services\PushSubscriptionService;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Minishlink\WebPush\MessageSentReport;
use Tests\TestCase;

class SendGuestPushNotificationBatchTest extends TestCase
{
    use RefreshDatabase;

    public function test_job_marks_subscription_as_delivered(): void
    {
        config()->set('push.enabled', true);

        $tenant = Tenant::factory()->create();
        $event = Event::factory()->for($tenant)->create(['status' => 'published']);
        $notification = GuestNotification::factory()->create([
            'tenant_id' => $tenant->id,
            'event_id' => $event->id,
        ]);

        $subscription = PushSubscription::factory()
            ->for($tenant)
            ->for($event)
            ->create();

        $report = new MessageSentReport(
            new Request('POST', 'https://push.example.com'),
            new Response(201),
            true,
            'OK'
        );

        $dispatcher = new class($report) extends WebPushDispatcher
        {
            public function __construct(private MessageSentReport $report) {}

            public function send(PushSubscription $subscription, array $payload): ?MessageSentReport
            {
                return $this->report;
            }
        };

        $job = new SendGuestPushNotificationBatch($notification->id, [$subscription->id]);
        $job->handle($dispatcher, app(PushSubscriptionService::class));

        $this->assertNotNull($subscription->fresh()->last_notified_at);
        $this->assertSame('active', $subscription->fresh()->status);
    }

    public function test_job_revokes_expired_subscription(): void
    {
        config()->set('push.enabled', true);

        $tenant = Tenant::factory()->create();
        $event = Event::factory()->for($tenant)->create(['status' => 'published']);
        $notification = GuestNotification::factory()->create([
            'tenant_id' => $tenant->id,
            'event_id' => $event->id,
        ]);

        $subscription = PushSubscription::factory()
            ->for($tenant)
            ->for($event)
            ->create();

        $report = new MessageSentReport(
            new Request('POST', 'https://push.example.com'),
            new Response(410),
            false,
            'Gone'
        );

        $dispatcher = new class($report) extends WebPushDispatcher
        {
            public function __construct(private MessageSentReport $report) {}

            public function send(PushSubscription $subscription, array $payload): ?MessageSentReport
            {
                return $this->report;
            }
        };

        $job = new SendGuestPushNotificationBatch($notification->id, [$subscription->id]);
        $job->handle($dispatcher, app(PushSubscriptionService::class));

        $this->assertSame('revoked', $subscription->fresh()->status);
    }
}
