<?php

declare(strict_types=1);

use App\Jobs\Billing\BalanceFrozenReminderJob;
use App\Jobs\Billing\BalancePreflightSweepJob;
use App\Jobs\SyncSupplierProjectJob;
use App\Mail\BalanceFrozenReminderMail;
use App\Models\PricingTier;
use App\Models\Project;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Billing\BillingTopupService;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
use Tests\Concerns\SharesSupplierPdo;

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

// Косяк 01 (24.06.2026): при нескольких версиях тарифа (старая дорогая + новая дешёвая,
// обе is_active — это нормальное версионирование цены по effective_from) расчёт баланса
// и снятия блока ДОЛЖЕН брать ДЕЙСТВУЮЩУЮ версию по дате — как списание и витрина через
// PricingTierRepository::activeAt — а не «по-простому» PricingTier::where(is_active)->get(),
// которое садится на старую дорогую версию (садится на запись с меньшим id).

beforeEach(function () {
    Queue::fake();
    DB::statement("SELECT set_config('app.current_tenant_id', '0', true)");

    // СТАРАЯ дорогая версия — создаём ПЕРВОЙ (ниже id → наивный sortBy('tier_no') садится на неё).
    PricingTier::query()->create([
        'tier_no' => 1,
        'leads_in_tier' => 100,
        'price_per_lead_kopecks' => 50000, // 500₽/лид — устаревшая версия
        'is_active' => true,
        'effective_from' => '2020-01-01',
    ]);
    // НОВАЯ действующая версия — свежий effective_from.
    PricingTier::query()->create([
        'tier_no' => 1,
        'leads_in_tier' => 100,
        'price_per_lead_kopecks' => 5000, // 50₽/лид — действующая версия
        'is_active' => true,
        'effective_from' => now(),
    ]);
});

it('topup unblocks project using the CURRENT cheap tariff, not the stale expensive one', function () {
    $tenant = Tenant::factory()->withRequisites()->create(['balance_rub' => '0.00']);
    $project = Project::factory()->for($tenant)->create([
        'is_active' => true,
        'daily_limit_target' => 30,
        'preflight_blocked_at' => now(),
    ]);

    // 2000₽: по действующей 50₽/лид = 40 лидов >= 30 → блок снять.
    // (по устаревшей 500₽/лид = 4 лида < 30 → остался бы заблокирован — это и есть баг.)
    app(BillingTopupService::class)->topup($tenant->id, '2000.00', null);

    expect($project->fresh()->preflight_blocked_at)->toBeNull();
    Queue::assertPushed(SyncSupplierProjectJob::class);
});

it('creates project (no 409) when limit is affordable at the CURRENT tariff', function () {
    // 2000₽: действующая 50₽ = 40 лидов >= 30 → создать (по устаревшей 500₽ = 4 < 30 → 409 = БАГ).
    $tenant = Tenant::factory()->withRequisites()->create(['balance_rub' => '2000.00']);
    $user = User::factory()->create(['tenant_id' => $tenant->id]);

    $this->actingAs($user)->postJson('/api/projects', [
        'name' => 'По действующей цене',
        'signal_type' => 'site',
        'signal_identifier' => 'current-tariff.ru',
        'daily_limit_target' => 30,
        'regions' => [],
        'delivery_days_mask' => 127,
    ])->assertStatus(201);

    expect(Project::where('signal_identifier', 'current-tariff.ru')->exists())->toBeTrue();
});

it('applies bulk limit increase affordable at the CURRENT tariff', function () {
    // 2000₽: действующая 50₽ = 40 лидов. Два проекта по 15 → сумма 30 ≤ 40 → применить.
    // (по устаревшей 500₽ = 4 < 30 → оба снялись бы = БАГ.)
    $tenant = Tenant::factory()->withRequisites()->create(['balance_rub' => '2000.00']);
    $user = User::factory()->create(['tenant_id' => $tenant->id]);
    $p1 = Project::factory()->for($tenant)->create(['is_active' => true, 'daily_limit_target' => 5, 'delivered_today' => 0]);
    $p2 = Project::factory()->for($tenant)->create(['is_active' => true, 'daily_limit_target' => 5, 'delivered_today' => 0]);

    $this->actingAs($user)->postJson('/api/projects/bulk', [
        'action' => 'update_limit',
        'ids' => [$p1->id, $p2->id],
        'replace' => 15,
    ])->assertOk()->assertJsonPath('updated', 2);

    expect($p1->fresh()->daily_limit_target)->toBe(15);
    expect($p2->fresh()->daily_limit_target)->toBe(15);
});

it('does NOT freeze tenant affordable at the CURRENT tariff during the sweep', function () {
    // 2000₽: действующая 50₽ = 40 лидов >= 30 → НЕ замораживать.
    // (по устаревшей 500₽ = 4 < 30 → заморозил бы = БАГ.)
    $tenant = Tenant::factory()->create(['balance_rub' => '2000.00', 'frozen_by_balance_at' => null]);
    Project::factory()->for($tenant)->create(['is_active' => true, 'daily_limit_target' => 30]);

    (new BalancePreflightSweepJob)->handle();

    expect($tenant->fresh()->frozen_by_balance_at)->toBeNull();
});

it('reminder email shows capacity at the CURRENT tariff, not the stale one', function () {
    Mail::fake();
    // Замороженный клиент в окне reminder (25ч). 2000₽, лимит 100 → нужно 100.
    // действующая 50₽ = 40 лидов вместимость; устаревшая 500₽ = 4 (это попало бы в письмо = БАГ).
    $tenant = Tenant::factory()->create([
        'balance_rub' => '2000.00',
        'frozen_by_balance_at' => now()->subHours(25),
    ]);
    Project::factory()->for($tenant)->create(['is_active' => true, 'daily_limit_target' => 100]);

    (new BalanceFrozenReminderJob)->handle();

    Mail::assertQueued(BalanceFrozenReminderMail::class, fn ($mail) => $mail->result->capacityLeads === 40);
});
