<?php

declare(strict_types=1);

use App\Models\Tenant;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Hash;

uses(DatabaseTransactions::class);

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

test('POST /api/auth/login возвращает user + requires_2fa=false для обычного user', function () {
    $user = User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'login-test@example.ru',
        'password_hash' => Hash::make('secret-pass-123'),
        'totp_enabled' => false,
        'is_active' => true,
    ]);

    $response = $this->postJson('/api/auth/login', [
        'email' => 'login-test@example.ru',
        'password' => 'secret-pass-123',
    ]);

    $response->assertOk();
    $response->assertJsonPath('user.id', $user->id);
    $response->assertJsonPath('user.email', 'login-test@example.ru');
    $response->assertJsonPath('requires_2fa', false);
    expect($response->json('user'))->not->toHaveKey('password_hash');
});

test('POST /api/auth/login c totp_enabled=true возвращает requires_2fa=true', function () {
    User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'totp-user@example.ru',
        'password_hash' => Hash::make('secret-pass-123'),
        'totp_enabled' => true,
    ]);

    $response = $this->postJson('/api/auth/login', [
        'email' => 'totp-user@example.ru',
        'password' => 'secret-pass-123',
    ]);

    $response->assertOk();
    $response->assertJsonPath('requires_2fa', true);
});

test('POST /api/auth/login возвращает 422 при неверном пароле', function () {
    User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'wrong-pass@example.ru',
        'password_hash' => Hash::make('right-pass-123'),
    ]);

    $response = $this->postJson('/api/auth/login', [
        'email' => 'wrong-pass@example.ru',
        'password' => 'wrong-pass-456',
    ]);

    $response->assertStatus(422);
    $response->assertJsonPath('errors.email.0', 'Неверный email или пароль.');
});

test('POST /api/auth/login возвращает 422 для несуществующего email', function () {
    $response = $this->postJson('/api/auth/login', [
        'email' => 'nonexistent@example.ru',
        'password' => 'any-password',
    ]);

    $response->assertStatus(422);
});

test('POST /api/auth/login возвращает 422 для заблокированного аккаунта (is_active=false)', function () {
    User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'blocked@example.ru',
        'password_hash' => Hash::make('right-pass-123'),
        'is_active' => false,
    ]);

    $response = $this->postJson('/api/auth/login', [
        'email' => 'blocked@example.ru',
        'password' => 'right-pass-123',
    ]);

    $response->assertStatus(422);
    $response->assertJsonPath('errors.email.0', 'Аккаунт заблокирован.');
});

test('POST /api/auth/login валидирует email format и password min:8', function () {
    $response = $this->postJson('/api/auth/login', [
        'email' => 'not-an-email',
        'password' => 'short',
    ]);

    $response->assertStatus(422);
    $response->assertJsonValidationErrors(['email', 'password']);
});

test('POST /api/auth/login обновляет last_login_at у user', function () {
    $user = User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'lastlogin@example.ru',
        'password_hash' => Hash::make('secret-pass-123'),
        'last_login_at' => null,
    ]);

    $this->postJson('/api/auth/login', [
        'email' => 'lastlogin@example.ru',
        'password' => 'secret-pass-123',
    ])->assertOk();

    expect($user->fresh()->last_login_at)->not->toBeNull();
});

test('GET /api/auth/me возвращает 401 без авторизации', function () {
    $this->getJson('/api/auth/me')->assertStatus(401);
});

test('GET /api/auth/me возвращает user после login', function () {
    $user = User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'me-test@example.ru',
        'password_hash' => Hash::make('secret-pass-123'),
    ]);

    $this->postJson('/api/auth/login', [
        'email' => 'me-test@example.ru',
        'password' => 'secret-pass-123',
    ])->assertOk();

    $this->getJson('/api/auth/me')
        ->assertOk()
        ->assertJsonPath('user.id', $user->id)
        ->assertJsonPath('user.email', 'me-test@example.ru');
});

test('POST /api/auth/logout успешно завершает сессию (200 + flash-message)', function () {
    User::factory()->create([
        'tenant_id' => $this->tenant->id,
        'email' => 'logout-test@example.ru',
        'password_hash' => Hash::make('secret-pass-123'),
    ]);

    $this->postJson('/api/auth/login', [
        'email' => 'logout-test@example.ru',
        'password' => 'secret-pass-123',
    ])->assertOk();

    // logout возвращает 200 с message. Полное invalidate-session тестирование
    // проблемно в Pest-runtime (cookie-jar держит session между запросами теста);
    // это тестируется через Pest browser-mode — отдельный коммит.
    $this->postJson('/api/auth/logout')
        ->assertOk()
        ->assertJsonPath('message', 'Вы вышли из системы.');
});
