<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\TwoFactorRequest;
use App\Services\TwoFactorService;
use App\Services\AuthenticationService;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Support\Facades\Auth;

class TwoFactorController extends Controller
{
    protected TwoFactorService $twoFactorService;
    protected AuthenticationService $authService;

    public function __construct(TwoFactorService $twoFactorService, AuthenticationService $authService)
    {
        $this->twoFactorService = $twoFactorService;
        $this->authService = $authService;
    }

    /**
     * Show the 2FA verification form.
     */
    public function showForm(): View
    {
        if (!session('auth.user_id')) {
            return redirect()->route('login');
        }

        $user = User::find(session('auth.user_id'));

        if (!$user || !$user->two_factor_enabled) {
            return redirect()->route('login');
        }

        return view('auth.two-factor');
    }

    /**
     * Verify the 2FA code.
     */
    public function verify(TwoFactorRequest $request): RedirectResponse
    {
        $userId = session('auth.user_id');

        if (!$userId) {
            return redirect()->route('login')
                ->withErrors(['code' => 'Session expired. Please login again.']);
        }

        $user = User::find($userId);

        if (!$user) {
            return redirect()->route('login')
                ->withErrors(['code' => 'User not found. Please login again.']);
        }

        // Verify the code
        if (!$this->twoFactorService->verify($user, $request->getCode())) {
            return back()->withErrors(['code' => 'Invalid authentication code.']);
        }

        // 2FA verified, complete login
        Auth::login($user, session('auth.remember', false));
        $this->authService->completeAuthentication($user, $request);

        // Clear session data
        session()->forget(['auth.user_id', 'auth.remember']);

        return redirect()->intended($user->getDashboardUrl())
            ->with('status', 'Login successful!');
    }

    /**
     * Cancel 2FA verification and redirect to login.
     */
    public function cancel(): RedirectResponse
    {
        session()->forget(['auth.user_id', 'auth.remember']);
        return redirect()->route('login');
    }

    /**
     * Show 2FA setup form for authenticated user.
     */
    public function showSetupForm(Request $request): View
    {
        $user = $request->user();

        if ($user->two_factor_enabled) {
            return view('auth.two-factor-manage', [
                'enabled' => true,
                'remainingCodes' => $this->twoFactorService->remainingRecoveryCodes($user),
            ]);
        }

        $secret = $this->twoFactorService->generateSecret();
        $qrCodeUrl = $this->twoFactorService->getQrCodeUrl($user, $secret);

        // Store secret temporarily
        session(['two_factor_secret' => $secret]);

        return view('auth.two-factor-setup', compact('qrCodeUrl', 'secret'));
    }

    /**
     * Enable 2FA for the user.
     */
    public function enable(TwoFactorRequest $request): RedirectResponse
    {
        $user = $request->user();
        $secret = session('two_factor_secret');

        if (!$secret) {
            return redirect()->route('two-factor.setup')
                ->withErrors(['code' => 'Setup session expired. Please try again.']);
        }

        // Verify the code before enabling
        if (!$this->twoFactorService->verifyCode($secret, $request->getCode())) {
            return back()->withErrors(['code' => 'Invalid authentication code. Please try again.']);
        }

        // Enable 2FA
        $recoveryCodes = $this->twoFactorService->enable($user, $secret);

        // Clear session
        session()->forget('two_factor_secret');

        return redirect()->route('two-factor.setup')
            ->with('status', 'Two-factor authentication enabled!')
            ->with('recoveryCodes', $recoveryCodes);
    }

    /**
     * Disable 2FA for the user.
     */
    public function disable(Request $request): RedirectResponse
    {
        $request->validate([
            'password' => ['required', 'string', 'current_password'],
        ]);

        $this->twoFactorService->disable($request->user());

        return redirect()->route('two-factor.setup')
            ->with('status', 'Two-factor authentication has been disabled.');
    }

    /**
     * Regenerate recovery codes.
     */
    public function regenerateCodes(Request $request): RedirectResponse
    {
        $request->validate([
            'password' => ['required', 'string', 'current_password'],
        ]);

        $user = $request->user();

        if (!$user->two_factor_enabled) {
            return redirect()->route('two-factor.setup');
        }

        $recoveryCodes = $this->twoFactorService->regenerateRecoveryCodes($user);

        return redirect()->route('two-factor.setup')
            ->with('status', 'New recovery codes generated!')
            ->with('recoveryCodes', $recoveryCodes);
    }
}
