<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Services\TwoFactorService;
use App\Services\UserSessionService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class TwoFactorChallengeController extends Controller
{
    public function __construct(
        protected TwoFactorService $twoFactor
    ) {}

    public function show(Request $request)
    {
        if (! $request->session()->has('login.id')) {
            return redirect()->route('login');
        }

        $user = \App\Models\User::find($request->session()->get('login.id'));
        if (! $user) {
            return redirect()->route('login')->withErrors(['email' => 'Session expired. Please sign in again.']);
        }

        if ($this->twoFactor->mustEnroll($user)) {
            return redirect()->route('two-factor.enroll');
        }

        if (! $this->twoFactor->isEnabled($user)) {
            return redirect()->route('login');
        }

        return view('auth.two-factor-challenge', [
            'method' => $this->twoFactor->method($user),
            'maskedEmail' => $this->maskEmail($user->email),
            'userName' => $user->name,
        ]);
    }

    protected function maskEmail(?string $email): string
    {
        if (! $email || ! str_contains($email, '@')) {
            return $email ?? '';
        }

        [$local, $domain] = explode('@', $email, 2);
        $hidden = strlen($local) <= 1
            ? str_repeat('•', 3)
            : substr($local, 0, 1) . str_repeat('•', max(2, strlen($local) - 1));

        return $hidden . '@' . $domain;
    }

    public function verify(Request $request, UserSessionService $sessions)
    {
        $request->validate(['code' => 'required|string|size:6']);

        $userId = $request->session()->get('login.id');
        $user = \App\Models\User::find($userId);
        if (! $user) {
            return redirect()->route('login')->withErrors(['code' => 'Session expired. Please sign in again.']);
        }

        if (! $this->twoFactor->verifyLoginCode($user, $request->input('code'))) {
            $this->twoFactor->recordFailedVerify($user);

            if ($this->twoFactor->isVerifyLockedOut($user)) {
                $request->session()->forget(['login.id', 'login.remember']);

                return redirect()->route('login')->withErrors([
                    'email' => 'Too many failed verification attempts. Please sign in again.',
                ]);
            }

            return back()->withErrors(['code' => 'Invalid or expired verification code.']);
        }

        $this->twoFactor->clearLoginCode($user);
        $this->twoFactor->clearFailedVerifies($user);
        Auth::login($user, (bool) $request->session()->get('login.remember', false));
        $request->session()->forget(['login.id', 'login.remember']);
        $request->session()->regenerate();
        $sessions->recordLogin($user, $request);

        if ($user->is_superadmin ?? false) {
            return redirect()->intended(route('superadmin.dashboard'));
        }

        return redirect()->intended(route('dashboard'));
    }

    public function resend(Request $request)
    {
        $userId = $request->session()->get('login.id');
        $user = \App\Models\User::find($userId);
        if (! $user) {
            return redirect()->route('login');
        }

        if ($this->twoFactor->method($user) !== TwoFactorService::METHOD_EMAIL) {
            return back()->with('error', 'Resend is only available for email verification.');
        }

        $this->twoFactor->sendLoginCode($user);

        return back()->with('success', 'A new verification code has been sent to your email.');
    }
}
