<?php

declare(strict_types=1);

use App\Models\OutboundWebhookSubscription;
use App\Models\Tenant;
use App\Models\User;
use App\Support\WebhookUrlGuard;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Http;

uses(DatabaseTransactions::class);

beforeEach(function () {
    $this->tenant = Tenant::factory()->create();
    $this->user = User::factory()->for($this->tenant)->create();
    $this->actingAs($this->user);
});

// --- unit: WebhookUrlGuard (IP-литералы, без DNS) ---

test('WebhookUrlGuard блокирует приватные/зарезервированные/loopback IP', function (string $url) {
    expect(WebhookUrlGuard::blockReason($url))->not->toBeNull();
})->with([
    'https://127.0.0.1/hook',          // loopback
    'https://10.0.0.1/hook',           // private A
    'https://172.16.0.1/hook',         // private B
    'https://192.168.1.1/hook',        // private C
    'https://169.254.169.254/hook',    // link-local / cloud metadata
    'https://[::1]/hook',              // IPv6 loopback
]);

test('WebhookUrlGuard пропускает публичный IP', function () {
    expect(WebhookUrlGuard::blockReason('https://93.184.216.34/hook'))->toBeNull();
});

test('WebhookUrlGuard отклоняет битый URL', function () {
    expect(WebhookUrlGuard::blockReason('not-a-url'))->not->toBeNull();
});

// --- endpoint: webhooks/test не должен бить во внутреннюю сеть ---

test('POST webhooks/test блокирует приватный IP target_url (SSRF) и не шлёт запрос', function () {
    Http::fake();
    OutboundWebhookSubscription::factory()->create([
        'tenant_id' => $this->tenant->id,
        'user_id' => $this->user->id,
        'target_url' => 'https://169.254.169.254/hook',
    ]);

    $this->postJson('/api/webhooks/test')->assertStatus(422);
    Http::assertNothingSent();
});

test('POST webhooks/test пропускает публичный target_url', function () {
    Http::fake(['*' => Http::response(['ok' => true], 200)]);
    OutboundWebhookSubscription::factory()->create([
        'tenant_id' => $this->tenant->id,
        'user_id' => $this->user->id,
        'target_url' => 'https://93.184.216.34/hook',
    ]);

    $this->postJson('/api/webhooks/test')
        ->assertOk()
        ->assertJsonPath('ok', true);
    Http::assertSentCount(1);
});
