<?php

declare(strict_types=1);

use App\Jobs\Supplier\FlushDeferredOnlineSyncJob;
use App\Jobs\SyncSupplierProjectJob;
use App\Models\Project;
use App\Models\Tenant;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;

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

/**
 * Task 4.2 — джоб досыла отложенной онлайн-очереди в 00:05 МСК.
 *
 * Для каждого проекта из supplier_deferred_sync диспатчит SyncSupplierProjectJob
 * (в 00:05 он вне окна → отработает немедленно) и чистит строку.
 */
function makeDeferredProject(): Project
{
    $tenant = Tenant::factory()->create();
    $project = Project::factory()->for($tenant)->create([
        'signal_type' => 'site', 'signal_identifier' => 'okna.ru', 'is_active' => true, 'daily_limit_target' => 10,
    ]);
    DB::table('supplier_deferred_sync')->insert([
        'project_id' => $project->id,
        'created_at' => now(),
    ]);

    return $project;
}

it('досылает отложенные онлайн-правки и чистит очередь', function (): void {
    Bus::fake([SyncSupplierProjectJob::class]);
    $project = makeDeferredProject();

    (new FlushDeferredOnlineSyncJob)->handle();

    expect(DB::table('supplier_deferred_sync')->count())->toBe(0);
    Bus::assertDispatched(
        SyncSupplierProjectJob::class,
        fn (SyncSupplierProjectJob $job) => $job->projectId === $project->id,
    );
});

it('пустая очередь — ничего не диспатчит, не падает', function (): void {
    Bus::fake([SyncSupplierProjectJob::class]);

    (new FlushDeferredOnlineSyncJob)->handle();

    Bus::assertNotDispatched(SyncSupplierProjectJob::class);
});

it('досылает несколько проектов и полностью очищает очередь', function (): void {
    Bus::fake([SyncSupplierProjectJob::class]);
    makeDeferredProject();
    makeDeferredProject();
    makeDeferredProject();

    (new FlushDeferredOnlineSyncJob)->handle();

    expect(DB::table('supplier_deferred_sync')->count())->toBe(0);
    Bus::assertDispatchedTimes(SyncSupplierProjectJob::class, 3);
});
