<?php

declare(strict_types=1);

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

use App\Http\Controllers\Controller;
use App\Models\TwoFactorRecoveryCode;
use App\Services\Auth\TwoFactorService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class TwoFactorController extends Controller
{
    public function __construct(private readonly TwoFactorService $svc)
    {
    }

    public function enable(Request $request): JsonResponse
    {
        $user = $request->user();
        if (! $user) {
            throw new AccessDeniedHttpException('UNAUTH');
        }

        $payload = $this->svc->generateSecret($user);

        return response()->json([
            'data' => [
                'secret' => $payload['secret'],
                'provisioning_uri' => $payload['provisioningUri'],
                'qr_svg' => $payload['qrSvg'],
            ],
        ]);
    }

    public function verify(Request $request): JsonResponse
    {
        $user = $request->user();
        if (! $user) {
            throw new AccessDeniedHttpException('UNAUTH');
        }
        $data = $request->validate([
            'code' => ['required', 'string', 'size:6'],
        ]);

        $ok = $this->svc->verify($user, $data['code']);

        return response()->json([
            'data' => [
                'verified' => $ok,
                'enabled' => (bool) $user->two_factor_enabled,
            ],
        ], $ok ? 200 : 422);
    }

    public function recoveryCodes(Request $request): JsonResponse
    {
        $user = $request->user();
        if (! $user) {
            throw new AccessDeniedHttpException('UNAUTH');
        }
        if (! $user->two_factor_enabled) {
            throw new AccessDeniedHttpException('2FA_NOT_ENABLED');
        }

        // wipe old + generate 10 new
        TwoFactorRecoveryCode::where('user_id', $user->id)->delete();

        $codes = [];
        for ($i = 0; $i < 10; $i++) {
            $code = strtoupper(Str::random(5).'-'.Str::random(5));
            $codes[] = $code;
            TwoFactorRecoveryCode::create([
                'user_id' => $user->id,
                'code_hash' => Hash::make($code),
            ]);
        }

        return response()->json(['data' => ['recovery_codes' => $codes]]);
    }
}
