<?php

declare(strict_types=1);

namespace App\Services\Auth;

use App\Enums\AuthEventType;
use App\Models\AuthEvent;
use App\Models\User;
use App\Support\Http\RequestSignature;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;

/**
 * Records authentication and account-security history.
 *
 * Failed attempts are recorded as well as successful ones, because the pattern
 * of failures is what the suspicious-login checks read. A domain portfolio is a
 * high-value target, so an account takeover needs to leave a trail.
 */
final class AuthEventRecorder
{
    public function __construct(
        private readonly RequestSignature $signature,
    ) {}

    /** @param  array<string, mixed>  $metadata */
    public function record(
        AuthEventType $event,
        ?User $user = null,
        ?string $emailAttempted = null,
        array $metadata = [],
        ?Request $request = null,
    ): AuthEvent {
        $request ??= request();

        return AuthEvent::create([
            'user_id' => $user?->getKey(),
            // Kept even on success so the trail shows what was typed, which
            // matters when an attacker is probing similar addresses.
            'email_attempted' => $emailAttempted ?? $user?->email,
            'event' => $event,
            'ip_address' => Context::get('ip_address') ?? $request?->ip(),
            'user_agent' => Str::limit((string) ($request?->userAgent() ?? ''), 500, ''),
            'device_fingerprint' => $this->signature->fingerprint($request),
            'country_code' => $this->signature->countryCode($request),
            'metadata' => $metadata === [] ? null : $metadata,
        ]);
    }
}
