<?php

declare(strict_types=1);

use App\Jobs\Supplier\DeleteSupplierProjectJob;
use App\Models\Project;
use App\Models\SupplierProject;
use App\Models\Tenant;
use App\Services\Supplier\SupplierPortalClient;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;

uses(DatabaseTransactions::class, SharesSupplierPdo::class);

/**
 * Task 2.4 — отложенное удаление донора, пока летит хвост слепка.
 *
 * Если у supplier_project нет других потребителей, но за активную/завтрашнюю дату
 * есть снимок маршрутизации с его источником — хвостовой лид ещё может прийти, и
 * LeadRouter ищет snapshot по источнику донора. Удалив донора, мы оборвём матч.
 * Поэтому удаление откладывается до следующего CleanupInactiveSupplierProjectsJob.
 */
function insertTailSnapshot(
    Tenant $tenant,
    string $signalType,
    ?string $signalIdentifier,
    ?array $smsSenders = null,
    ?string $smsKeyword = null,
    ?string $date = null,
): void {
    DB::table('project_routing_snapshots')->insert([
        'snapshot_date' => $date ?? Carbon::tomorrow('Europe/Moscow')->toDateString(),
        'project_id' => random_int(900000, 999999),
        'tenant_id' => $tenant->id,
        'daily_limit' => 10,
        'delivery_days_mask' => 127,
        'regions' => '{}',
        'signal_type' => $signalType,
        'signal_identifier' => $signalIdentifier,
        'sms_senders' => $smsSenders === null ? null : json_encode($smsSenders),
        'sms_keyword' => $smsKeyword,
        'expected_volume' => 10,
        'delivered_count' => 0,
        'created_at' => now(),
    ]);
}

it('не удаляет supplier_project, пока есть снимок с его источником за активную дату', function (): void {
    $tenant = Tenant::factory()->create();
    $sp = SupplierProject::query()->create([
        'platform' => 'B1', 'signal_type' => 'call', 'unique_key' => '79991110000',
        'supplier_external_id' => '555', 'current_limit' => 1,
    ]);
    // Снимок-хвост по тому же источнику (call/79991110000), потребителей pivot — нет.
    insertTailSnapshot($tenant, 'call', '79991110000');

    $mock = Mockery::mock(SupplierPortalClient::class);
    $mock->shouldNotReceive('deleteProject');
    app()->instance(SupplierPortalClient::class, $mock);

    (new DeleteSupplierProjectJob([$sp->id]))->handle(app(SupplierPortalClient::class));

    // Донор НЕ удалён — удаление отложено, пока летит хвост.
    expect(SupplierProject::find($sp->id))->not->toBeNull();
});

it('откладывает удаление sms-донора, пока снимок несёт его sender в хвосте', function (): void {
    $tenant = Tenant::factory()->create();
    $sp = SupplierProject::query()->create([
        'platform' => 'B3', 'signal_type' => 'sms', 'unique_key' => 'Caranga',
        'supplier_external_id' => '777', 'current_limit' => 1,
    ]);
    insertTailSnapshot($tenant, 'sms', null, smsSenders: ['Caranga']);

    $mock = Mockery::mock(SupplierPortalClient::class);
    $mock->shouldNotReceive('deleteProject');
    app()->instance(SupplierPortalClient::class, $mock);

    (new DeleteSupplierProjectJob([$sp->id]))->handle(app(SupplierPortalClient::class));

    expect(SupplierProject::find($sp->id))->not->toBeNull();
});

it('удаляет донора, когда хвоста слепка нет (регрессия базового удаления)', function (): void {
    $tenant = Tenant::factory()->create();
    $sp = SupplierProject::query()->create([
        'platform' => 'B1', 'signal_type' => 'call', 'unique_key' => '79992220000',
        'supplier_external_id' => '600', 'current_limit' => 1,
    ]);
    // Снимок есть, но по ДРУГОМУ источнику — хвоста для этого донора нет.
    insertTailSnapshot($tenant, 'call', '70000000000');

    $mock = Mockery::mock(SupplierPortalClient::class);
    $mock->shouldReceive('deleteProject')->once()->with(600);
    app()->instance(SupplierPortalClient::class, $mock);

    (new DeleteSupplierProjectJob([$sp->id]))->handle(app(SupplierPortalClient::class));

    expect(SupplierProject::find($sp->id))->toBeNull();
});
