<?php

declare(strict_types=1);

use App\Models\ActivityLog;
use App\Models\Deal;
use App\Models\Project;
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;

/**
 * Тесты GET /api/deals/{id} — детали сделки + recent activity events для
 * DealDetailDrawer.
 */
uses(DatabaseTransactions::class);

beforeEach(function () {
    $this->tenant = Tenant::factory()->create();
    $this->otherTenant = Tenant::factory()->create();

    DB::statement('SET app.current_tenant_id = '.$this->tenant->id);
    $this->project = Project::factory()->for($this->tenant)->create(['name' => 'Окна Москва']);
    $this->manager = User::factory()->for($this->tenant)->create([
        'first_name' => 'Иван',
        'last_name' => 'Петров',
        'email' => 'ivan@example.test',
    ]);
});

test('GET /api/deals/{id} 422 без tenant_id', function () {
    $deal = Deal::factory()->for($this->tenant)->for($this->project)->create();
    $this->getJson('/api/deals/'.$deal->id)->assertStatus(422);
});

test('GET /api/deals/{id} 404 для unknown tenant', function () {
    $deal = Deal::factory()->for($this->tenant)->for($this->project)->create();
    $this->getJson('/api/deals/'.$deal->id.'?tenant_id=999999')->assertStatus(404);
});

test('GET /api/deals/{id} 404 если сделка не существует', function () {
    $this->getJson('/api/deals/999999?tenant_id='.$this->tenant->id)->assertStatus(404);
});

test('GET /api/deals/{id} 404 если сделка чужого tenant\'а (defense-in-depth)', function () {
    DB::statement('SET app.current_tenant_id = '.$this->otherTenant->id);
    $foreignProject = Project::factory()->for($this->otherTenant)->create();
    $foreign = Deal::factory()->for($this->otherTenant)->for($foreignProject)->create();

    // Запрашиваем чужую сделку с нашим tenant_id — RLS+app-фильтр скрывают.
    $this->getJson('/api/deals/'.$foreign->id.'?tenant_id='.$this->tenant->id)
        ->assertStatus(404);
});

test('GET /api/deals/{id} возвращает сделку с relations', function () {
    $deal = Deal::factory()
        ->for($this->tenant)
        ->for($this->project)
        ->create([
            'phone' => '+7 (999) 100-00-00',
            'contact_name' => 'Анна С.',
            'status' => 'new',
            'manager_id' => $this->manager->id,
            'comment' => 'Заметка менеджера',
        ]);

    $r = $this->getJson('/api/deals/'.$deal->id.'?tenant_id='.$this->tenant->id);

    $r->assertStatus(200);
    expect($r->json('deal.id'))->toBe($deal->id);
    expect($r->json('deal.phone'))->toBe('+7 (999) 100-00-00');
    expect($r->json('deal.contact_name'))->toBe('Анна С.');
    expect($r->json('deal.comment'))->toBe('Заметка менеджера');
    expect($r->json('deal.status'))->toBe('new');
    expect($r->json('deal.project_name'))->toBe('Окна Москва');
    expect($r->json('deal.manager_name'))->toBe('Иван П.');
    expect($r->json('deal.manager_initials'))->toBe('ИП');
    expect($r->json('deal.received_at'))->toBeString();
});

test('GET /api/deals/{id} возвращает activity events отсортированные по created_at DESC', function () {
    $deal = Deal::factory()->for($this->tenant)->for($this->project)->create();

    DB::statement('SET app.current_tenant_id = '.$this->tenant->id);
    ActivityLog::create([
        'tenant_id' => $this->tenant->id,
        'user_id' => null,
        'deal_id' => $deal->id,
        'event' => ActivityLog::EVENT_DEAL_CREATED,
        'context' => ['source' => 'webhook'],
        'created_at' => now()->subMinutes(30),
    ]);
    ActivityLog::create([
        'tenant_id' => $this->tenant->id,
        'user_id' => $this->manager->id,
        'deal_id' => $deal->id,
        'event' => ActivityLog::EVENT_DEAL_STATUS_CHANGED,
        'context' => ['from' => 'new', 'to' => 'paid', 'source' => 'manual'],
        'created_at' => now()->subMinutes(5),
    ]);

    $r = $this->getJson('/api/deals/'.$deal->id.'?tenant_id='.$this->tenant->id);

    $r->assertStatus(200);
    $events = $r->json('events');
    expect($events)->toHaveCount(2);
    // ORDER BY created_at DESC — свежее (status_changed) сверху.
    expect($events[0]['event'])->toBe('deal.status_changed');
    expect($events[0]['context'])->toMatchArray(['from' => 'new', 'to' => 'paid']);
    expect($events[0]['actor']['name'])->toBe('Иван П.');
    expect($events[0]['actor']['initials'])->toBe('ИП');

    expect($events[1]['event'])->toBe('deal.created');
    expect($events[1]['actor'])->toBeNull(); // user_id=null → system
});

test('GET /api/deals/{id} НЕ возвращает чужие activity events (RLS+app-фильтр)', function () {
    $deal = Deal::factory()->for($this->tenant)->for($this->project)->create();

    // Пишем event на чужого tenant'а с тем же deal_id (gap if RLS+app-filter не сработает).
    DB::statement('SET app.current_tenant_id = '.$this->otherTenant->id);
    ActivityLog::create([
        'tenant_id' => $this->otherTenant->id,
        'user_id' => null,
        'deal_id' => $deal->id, // тот же id, но другой tenant
        'event' => ActivityLog::EVENT_DEAL_CREATED,
        'context' => ['source' => 'leak'],
    ]);

    DB::statement('SET app.current_tenant_id = '.$this->tenant->id);
    ActivityLog::create([
        'tenant_id' => $this->tenant->id,
        'user_id' => null,
        'deal_id' => $deal->id,
        'event' => ActivityLog::EVENT_DEAL_CREATED,
        'context' => ['source' => 'webhook'],
    ]);

    $r = $this->getJson('/api/deals/'.$deal->id.'?tenant_id='.$this->tenant->id);

    $events = $r->json('events');
    expect($events)->toHaveCount(1);
    expect($events[0]['context']['source'])->toBe('webhook');
});

test('GET /api/deals/{id} лимит 50 событий', function () {
    $deal = Deal::factory()->for($this->tenant)->for($this->project)->create();

    DB::statement('SET app.current_tenant_id = '.$this->tenant->id);
    foreach (range(1, 60) as $i) {
        ActivityLog::create([
            'tenant_id' => $this->tenant->id,
            'user_id' => null,
            'deal_id' => $deal->id,
            'event' => ActivityLog::EVENT_DEAL_STATUS_CHANGED,
            'context' => ['n' => $i],
            'created_at' => now()->subMinutes(60 - $i),
        ]);
    }

    $r = $this->getJson('/api/deals/'.$deal->id.'?tenant_id='.$this->tenant->id);

    expect($r->json('events'))->toHaveCount(50);
});
