<?php

declare(strict_types=1);

use App\Models\Deal;
use App\Models\Project;
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;

/**
 * Smoke-тесты Deal Eloquent-модели: composite PK (id, received_at),
 * factory, связи. Под superuser (без RLS — отдельно в RlsSmokeTest).
 */
uses(DatabaseTransactions::class);

test('DealFactory создаёт сделку с дефолтным status=new', function () {
    $deal = Deal::factory()->create();

    expect($deal->id)->toBeInt();
    expect($deal->tenant_id)->toBeInt();
    expect($deal->project_id)->toBeInt();
    expect($deal->status)->toBe('new');
    expect($deal->is_test)->toBeFalse();
    expect($deal->received_at)->not->toBeNull();
});

test('Deal->tenant() и Deal->project() возвращают родителей', function () {
    $tenant = Tenant::factory()->create();
    $project = Project::factory()->create(['tenant_id' => $tenant->id]);
    $deal = Deal::factory()->create([
        'tenant_id' => $tenant->id,
        'project_id' => $project->id,
    ]);

    expect($deal->tenant->id)->toBe($tenant->id);
    expect($deal->project->id)->toBe($project->id);
});

test('Deal->manager() возвращает менеджера или null', function () {
    $tenant = Tenant::factory()->create();
    $manager = User::factory()->create(['tenant_id' => $tenant->id]);

    $assigned = Deal::factory()->create([
        'tenant_id' => $tenant->id,
        'manager_id' => $manager->id,
    ]);
    $unassigned = Deal::factory()->create(['tenant_id' => $tenant->id]);

    expect($assigned->manager->id)->toBe($manager->id);
    expect($unassigned->manager)->toBeNull();
});

test('Deal::update() формирует WHERE по composite PK (id, received_at)', function () {
    $deal = Deal::factory()->create();
    $originalId = $deal->id;
    $originalReceivedAt = $deal->received_at;

    // Проверяем, что update генерирует SQL с обоими полями в WHERE.
    DB::enableQueryLog();
    $deal->update(['comment' => 'updated via composite PK']);
    $logs = DB::getQueryLog();
    DB::disableQueryLog();

    $updateLog = collect($logs)->first(fn ($q) => str_starts_with($q['query'], 'update'));

    expect($updateLog)->not->toBeNull();
    expect($updateLog['query'])->toContain('"id" = ?');
    expect($updateLog['query'])->toContain('"received_at" = ?');
    expect($updateLog['bindings'])->toContain($originalId);

    $reloaded = Deal::query()->where('id', $originalId)->where('received_at', $originalReceivedAt)->first();
    expect($reloaded->comment)->toBe('updated via composite PK');
});

test('Deal cast: phones JSONB → array', function () {
    $deal = Deal::factory()->create([
        'phones' => ['79001234567', '79007654321'],
    ]);

    $reloaded = Deal::query()
        ->where('id', $deal->id)
        ->where('received_at', $deal->received_at)
        ->first();

    expect($reloaded->phones)->toBe(['79001234567', '79007654321']);
});

test('Deal cast: is_test BOOLEAN, escalated_count INT', function () {
    $deal = Deal::factory()->create([
        'is_test' => true,
        'escalated_count' => 3,
    ]);

    $reloaded = Deal::query()
        ->where('id', $deal->id)
        ->where('received_at', $deal->received_at)
        ->first();

    expect($reloaded->is_test)->toBeTrue();
    expect($reloaded->escalated_count)->toBe(3);
});
