<?php

namespace App\Livewire\Auth;

use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Validate;
use Livewire\Component;
use PragmaRX\Google2FA\Exceptions\Google2FAException;
use PragmaRX\Google2FAQRCode\Google2FA;

#[Layout('layouts.auth')]
class TwoFactorSetup extends Component
{
    public string $secret = '';

    #[Validate('required|string')]
    public string $code = '';

    public function mount()
    {
        if (Auth::user()->hasTotp()) {
            return $this->redirect(route('settings'), navigate: true);
        }

        $this->secret = (new Google2FA)->generateSecretKey();
    }

    public function confirm()
    {
        $this->validate();

        try {
            $matches = (new Google2FA)->verifyKey($this->secret, preg_replace('/\s+/', '', $this->code) ?? '');
        } catch (Google2FAException $e) {
            $matches = false;
        }

        if (! $matches) {
            throw ValidationException::withMessages(['code' => __('auth.code_mismatch')]);
        }

        Auth::user()->forceFill([
            'two_factor_secret' => $this->secret,
            'two_factor_confirmed_at' => now(),
        ])->save();

        // First factor enrolled and no codes yet → generate the single recovery set and
        // ask Settings to pop the modal (the app layout hosts wire-elements/modal).
        if (! Auth::user()->hasRecoveryCodes()) {
            Auth::user()->replaceRecoveryCodes();
            session()->flash('open_recovery_modal', true);
            // put (not flash): must survive the redirect AND the later openModal Livewire
            // request; the modal pulls it on mount to reveal the freshly generated codes once.
            session()->put('2fa.codes_fresh', now()->timestamp);
            // One-time download grant (a timestamp) — the download route requires + consumes
            // it within a short window, so the fresh set can be downloaded once and a later
            // direct hit 403s.
            session()->put('2fa.download_grant', now()->timestamp);
        }

        return $this->redirect(route('settings'), navigate: true);
    }

    public function qrCode(): string
    {
        return (new Google2FA)->getQRCodeInline('Clusev', Auth::user()->email, $this->secret);
    }

    public function render()
    {
        return view('livewire.auth.two-factor-setup')->title(__('auth.title_setup'));
    }
}
