<?php

use App\Models\AuditLog;
use Illuminate\Http\Request;
use App\Services\AuditLogger;
use App\Http\Middleware\RecordAdminApiAudit;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('audit logger persists row with snapshots', function (): void {
    $row = AuditLogger::record(
        AuditLogger::OPERATOR_ADMIN,
        42,
        'settings',
        'update',
        'lottery_setting',
        'deposit_min',
        ['value_json' => 100],
        ['value_json' => 200],
        '203.0.113.10',
        'PHPUnit',
    );

    expect($row)->toBeInstanceOf(AuditLog::class)
        ->operator_type->toBe(AuditLogger::OPERATOR_ADMIN)
        ->operator_id->toBe(42)
        ->module_code->toBe('settings')
        ->action_code->toBe('update')
        ->target_type->toBe('lottery_setting')
        ->target_id->toBe('deposit_min')
        ->before_json->toBe(['value_json' => 100])
        ->after_json->toBe(['value_json' => 200])
        ->ip->toBe('203.0.113.10')
        ->user_agent->toBe('PHPUnit');

    expect(AuditLog::query()->count())->toBe(1);
});

test('audit logger truncates user agent to 255', function (): void {
    $ua = str_repeat('a', 300);

    $row = AuditLogger::record(AuditLogger::OPERATOR_SYSTEM, 0, 'job', 'run', ip: null, userAgent: $ua);

    expect(strlen((string) $row->user_agent))->toBe(255);
});

test('audit logger record from request fills ip', function (): void {
    $request = Request::create('/fake', 'POST', server: [
        'REMOTE_ADDR' => '198.51.100.2',
        'HTTP_USER_AGENT' => 'TestAgent',
    ]);

    $row = AuditLogger::recordFromRequest(
        $request,
        AuditLogger::OPERATOR_PLAYER,
        7,
        'wallet',
        'transfer',
        null,
        null,
        ['x' => 1],
        ['x' => 2],
    );

    expect($row)
        ->ip->toContain('198.51.100.2')
        ->user_agent->toBe('TestAgent');

    expect($request->attributes->get(RecordAdminApiAudit::ATTRIBUTE_AUDIT_RECORDED))->toBeTrue();
});

test('record for system uses operator zero', function (): void {
    AuditLogger::recordForSystem('reconcile', 'start', targetId: '2026-01');

    /** @var AuditLog|null $row */
    $row = AuditLog::query()->latest('id')->first();

    expect($row)->not->toBeNull()
        ->operator_type->toBe(AuditLogger::OPERATOR_SYSTEM)
        ->operator_id->toBe(0);
});
