<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\AuditService;
use App\Services\LoginAttemptService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;

class AuthenticatedSessionController extends Controller
{
    public function __construct(private readonly LoginAttemptService $attempts) {}

    public function create(): View
    {
        return view('auth.login');
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'login' => ['required', 'string', 'max:255'],
            'password' => ['required', 'string', 'max:1024'],
        ]);

        $login = trim($data['login']);
        $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
        if ($field === 'email') {
            $login = Str::lower($login);
        }

        $throttleKey = 'login:'.hash('sha256', Str::lower($login).'|'.($request->ip() ?? 'unknown'));
        if (RateLimiter::tooManyAttempts($throttleKey, 5)) {
            $this->attempts->record($request, 'throttled', $login);
            throw ValidationException::withMessages([
                'login' => 'Too many login attempts. Try again shortly.',
            ]);
        }

        $candidate = User::query()->where($field, $login)->first();
        if (! Auth::attempt([$field => $login, 'password' => $data['password'], 'status' => 'active'], $request->boolean('remember'))) {
            RateLimiter::hit($throttleKey, 60);
            $status = $candidate && $candidate->status !== 'active' ? 'inactive_account' : 'failed_credentials';
            $this->attempts->record($request, $status, $login, $candidate);

            throw ValidationException::withMessages([
                'login' => 'The provided credentials do not match an active account.',
            ]);
        }

        RateLimiter::clear($throttleKey);
        $user = $request->user();

        if ($user->two_factor_confirmed_at) {
            $request->session()->put([
                'security.two_factor_user_id' => $user->getKey(),
                'security.two_factor_remember' => $request->boolean('remember'),
            ]);
            $this->attempts->record($request, 'two_factor_required', $login, $user);
            Auth::logout();
            $request->session()->regenerate();

            return redirect()->route('two-factor.challenge');
        }

        $request->session()->regenerate();
        $this->attempts->record($request, 'success', $login, $user);
        AuditService::record('auth.login', $user);

        return redirect()->intended(route('dashboard'));
    }

    public function destroy(Request $request): RedirectResponse
    {
        AuditService::record('auth.logout', $request->user());
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('login');
    }
}
