<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\Settings\SettingsService;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class AuthenticatedSessionController extends Controller
{
    public function __construct(private readonly SettingsService $settings) {}

    public function create(): View
    {
        return view('auth.login', [
            'emailLoginEnabled' => $this->settings->isEnabled('security.enable_email_login'),
            'googleLoginEnabled' => $this->settings->isEnabled('google.login_enabled'),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        abort_unless($this->settings->isEnabled('security.enable_email_login'), 403, 'Email login is disabled.');

        $validated = $request->validate([
            'identifier' => ['required', 'string', 'max:255'],
            'password' => ['required', 'string', 'max:255'],
            'remember' => ['nullable', 'boolean'],
        ]);

        $this->ensureIsNotRateLimited($request);

        $user = $this->findUser((string) $validated['identifier']);

        if (! $user || blank($user->password_set_at) || ! Hash::check((string) $validated['password'], $user->password)) {
            RateLimiter::hit($this->throttleKey($request), 60);

            throw ValidationException::withMessages([
                'identifier' => 'These credentials do not match our records.',
            ]);
        }

        RateLimiter::clear($this->throttleKey($request));

        Auth::guard('web')->login($user, (bool) ($validated['remember'] ?? false));
        $request->session()->regenerate();

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

        return redirect()->intended($this->nextUrlFor($user));
    }

    private function findUser(string $identifier): ?User
    {
        $identifier = Str::lower(trim($identifier));

        return User::query()
            ->where('email', $identifier)
            ->orWhere('username', $identifier)
            ->first();
    }

    private function ensureIsNotRateLimited(Request $request): void
    {
        $maxAttempts = max(1, (int) $this->settings->get('security.maximum_login_attempts', 5));

        if (! RateLimiter::tooManyAttempts($this->throttleKey($request), $maxAttempts)) {
            return;
        }

        $seconds = RateLimiter::availableIn($this->throttleKey($request));

        throw ValidationException::withMessages([
            'identifier' => "Too many login attempts. Please try again in {$seconds} seconds.",
        ]);
    }

    private function throttleKey(Request $request): string
    {
        return Str::transliterate(Str::lower((string) $request->input('identifier')).'|'.$request->ip());
    }

    private function nextUrlFor(User $user): string
    {
        if (! $user->hasCompletedQuestionnaire()) {
            return route('questionnaire.show');
        }

        if (! $user->hasUnlockedAccess()) {
            return route('payment.checkout');
        }

        if (! $user->hasAnalyzedResume()) {
            return route('resume.show');
        }

        if (! $user->hasCompletedProfile()) {
            return route('profile.edit');
        }

        return route('applicant.dashboard');
    }
}
