<?php

namespace App\Http\Controllers\Backoffice;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\User;
use App\Services\TotpService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class TwoFactorController extends Controller
{
    public function showSetup(TotpService $totp)
    {
        $user = Auth::guard('web')->user();
        if (!$user) {
            return redirect()->route('backoffice.login');
        }

        if (!$user->twofa_secret) {
            $user->twofa_secret = $totp->generateSecret();
            $user->save();
        }

        $issuer = setting('site_name', 'PayGaranti');
        $account = $user->username ?: $user->email ?: ('user-' . $user->id);
        $otpAuthUrl = $totp->getOtpAuthUri($issuer, $account, $user->twofa_secret);

        return view('backoffice.auth.twofa', [
            'user' => $user,
            'issuer' => $issuer,
            'account' => $account,
            'otpAuthUrl' => $otpAuthUrl,
        ]);
    }

    public function showEnroll(Request $request, TotpService $totp)
    {
        $userId = $request->session()->get('backoffice_2fa_enroll_user');
        if (!$userId) {
            return redirect()->route('backoffice.login');
        }

        $user = User::find($userId);
        if (!$user) {
            $request->session()->forget(['backoffice_2fa_enroll_user', 'backoffice_2fa_remember']);
            return redirect()->route('backoffice.login');
        }

        if (!$user->twofa_secret) {
            $user->twofa_secret = $totp->generateSecret();
            $user->save();
        }

        $issuer = setting('site_name', 'PayGaranti');
        $account = $user->username ?: $user->email ?: ('user-' . $user->id);
        $otpAuthUrl = $totp->getOtpAuthUri($issuer, $account, $user->twofa_secret);

        return view('backoffice.auth.twofa-enroll', [
            'user' => $user,
            'issuer' => $issuer,
            'account' => $account,
            'otpAuthUrl' => $otpAuthUrl,
        ]);
    }

    public function enable(Request $request, TotpService $totp)
    {
        $user = Auth::guard('web')->user();
        if (!$user) {
            return redirect()->route('backoffice.login');
        }

        $data = $request->validate([
            'code' => 'required|string',
        ]);

        if (!$user->twofa_secret || !$totp->verifyCode($user->twofa_secret, $data['code'])) {
            return back()->withErrors(['code' => 'Invalid code.'])->withInput();
        }

        $user->update([
            'twofa_enabled' => true,
            'twofa_confirmed_at' => now(),
        ]);

        ActivityLog::log(
            'twofa_enable',
            'auth',
            'Backoffice user enabled 2FA: ' . $user->username
        );

        return back()->with('status', 'Two factor enabled.');
    }

    public function verifyEnroll(Request $request, TotpService $totp)
    {
        $data = $request->validate([
            'code' => 'required|string',
        ]);

        $userId = $request->session()->get('backoffice_2fa_enroll_user');
        $remember = (bool) $request->session()->get('backoffice_2fa_remember', false);

        $user = User::find($userId);
        if (!$user || !$user->twofa_secret) {
            $request->session()->forget(['backoffice_2fa_enroll_user', 'backoffice_2fa_remember']);
            return redirect()->route('backoffice.login');
        }

        if (!$totp->verifyCode($user->twofa_secret, $data['code'])) {
            return back()->withErrors(['code' => 'Invalid code.'])->withInput();
        }

        $user->update([
            'twofa_enabled' => true,
            'twofa_confirmed_at' => now(),
        ]);

        ActivityLog::log(
            'twofa_enable',
            'auth',
            'Backoffice user enabled 2FA: ' . $user->username
        );

        Auth::guard('web')->login($user, $remember);
        $request->session()->forget(['backoffice_2fa_enroll_user', 'backoffice_2fa_remember']);
        $request->session()->regenerate();

        $user->update(['last_login_at' => now()]);

        ActivityLog::log(
            'login',
            'auth',
            'Backoffice user login (2FA): ' . $user->username
        );

        return redirect()->route('backoffice.dashboard', ['fresh' => time()]);
    }

    public function disable(Request $request, TotpService $totp)
    {
        $user = Auth::guard('web')->user();
        if (!$user) {
            return redirect()->route('backoffice.login');
        }

        $data = $request->validate([
            'code' => 'required|string',
        ]);

        if (!$user->twofa_secret || !$totp->verifyCode($user->twofa_secret, $data['code'])) {
            return back()->withErrors(['code' => 'Invalid code.'])->withInput();
        }

        $user->update([
            'twofa_enabled' => false,
            'twofa_secret' => null,
            'twofa_confirmed_at' => null,
        ]);

        ActivityLog::log(
            'twofa_disable',
            'auth',
            'Backoffice user disabled 2FA: ' . $user->username
        );

        return back()->with('status', 'Two factor disabled.');
    }

    public function showChallenge(Request $request)
    {
        if (Auth::guard('web')->check()) {
            return redirect()->route('backoffice.dashboard', ['fresh' => time()]);
        }

        if (!$request->session()->has('backoffice_2fa_user')) {
            return redirect()->route('backoffice.login');
        }

        return view('backoffice.auth.twofa-challenge');
    }

    public function verifyChallenge(Request $request, TotpService $totp)
    {
        $data = $request->validate([
            'code' => 'required|string',
        ]);

        $userId = $request->session()->get('backoffice_2fa_user');
        $remember = (bool) $request->session()->get('backoffice_2fa_remember', false);

        $user = User::find($userId);
        if (!$user || !$user->twofa_enabled || !$user->twofa_secret) {
            $request->session()->forget(['backoffice_2fa_user', 'backoffice_2fa_remember']);
            return redirect()->route('backoffice.login');
        }

        if (!$totp->verifyCode($user->twofa_secret, $data['code'])) {
            return back()->withErrors(['code' => 'Invalid code.'])->withInput();
        }

        Auth::guard('web')->login($user, $remember);
        $request->session()->forget(['backoffice_2fa_user', 'backoffice_2fa_remember']);
        $request->session()->regenerate();

        $user->update(['last_login_at' => now()]);

        ActivityLog::log(
            'login',
            'auth',
            'Backoffice user login (2FA): ' . $user->username
        );

        return redirect()->route('backoffice.dashboard', ['fresh' => time()]);
    }
}
