<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1\Auth\Concerns;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

/**
 * Establishes authentication for a freshly verified user.
 *
 * Two client shapes share these routes. The web SPA is a stateful caller: it
 * arrives from an allowed origin, Sanctum attaches the session middleware, and
 * a cookie session is created -- no token is ever exposed to JavaScript. The
 * mobile app is stateless: it names its device and receives a bearer token.
 *
 * A caller that is neither is answered with a clear error rather than a 500.
 * That happens for real -- a script or an integration hitting the login route
 * from an origin that is not in the stateful list -- and the fix is something
 * the caller can act on.
 */
trait IssuesAuthentication
{
    /**
     * @return string|null The plain-text token for stateless clients, or null
     *                     when a cookie session was established instead.
     */
    protected function issueAuthentication(Request $request, User $user, bool $remember = false): ?string
    {
        if ($request->filled('device_name')) {
            $token = $user->createToken($request->string('device_name')->toString(), ['*']);

            $token->accessToken->forceFill(array_filter([
                'device_name' => $request->string('device_name')->toString(),
                'device_platform' => $request->input('device_platform'),
                'last_used_ip' => $request->ip(),
            ], fn ($value): bool => $value !== null))->save();

            return $token->plainTextToken;
        }

        if (! $request->hasSession()) {
            throw ValidationException::withMessages([
                'device_name' => [
                    'This request cannot establish a session. Call from a configured application origin, or supply a device_name to receive an API token.',
                ],
            ]);
        }

        Auth::guard('web')->login($user, $remember);

        // Rotate the session id whenever the authenticated identity changes,
        // which is what closes session fixation.
        $request->session()->regenerate();

        return null;
    }
}
