<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Services\AuditLog;
use App\Services\DeviceTokenService;
use App\Services\UserLanding;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

/**
 * Quick PIN login for shared/POS devices: a short PIN unlocks a session for
 * the staff member already bound to this browser (see {@see DeviceTokenService}),
 * without ever weakening the account's real credentials.
 *
 * Deliberately outside the `auth`/`guest` middleware groups (see routes/web.php)
 * — no session is required, and an existing session for a different staff
 * member is fine (shift changeover).
 */
class PinLoginController extends Controller
{
    public function __construct(private readonly DeviceTokenService $deviceTokens) {}

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'device_token' => ['required', 'string'],
            'pin' => ['required', 'digits_between:4,6'],
        ]);

        $user = $this->deviceTokens->resolve($validated['device_token']);

        // Every failure below returns the identical message, so a wrong PIN
        // and an untrusted/expired device are indistinguishable from the
        // outside — nothing here should let an attacker learn which factor
        // was wrong.
        if ($user === null || $user->pin_hash === null || ! Hash::check($validated['pin'], $user->pin_hash)) {
            return response()->json([
                'code' => 'device_untrusted',
                'message' => 'Wrong PIN, or this device is no longer trusted.',
            ], 422);
        }

        if ($user->isLocked() || ! $user->isActive()) {
            return response()->json([
                'code' => 'account_unavailable',
                'message' => 'This account is not available. Contact an administrator.',
            ], 422);
        }

        // PIN is a convenience, never a downgrade path: any account that has
        // opted into a real second factor must keep using it.
        if ($user->two_factor_confirmed_at !== null || $user->two_factor_email_enabled) {
            return response()->json([
                'code' => 'stronger_auth_required',
                'message' => 'This account requires signing in with your password.',
            ], 422);
        }

        Auth::login($user);
        $request->session()->regenerate();

        AuditLog::record('user.pin_login', $user, ['ip' => $request->ip()]);

        return response()->json([
            'redirect' => UserLanding::urlFor($user),
        ]);
    }
}
