<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\ForgotPasswordRequest;
use App\Http\Requests\ResetPasswordRequest;
use App\Mail\PasswordResetMail;
use App\Models\User;
use App\Services\ActivityLogService;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;

class PasswordResetController extends Controller
{
    public function __construct(
        protected ActivityLogService $activityLogService
    ) {}

    /**
     * Show the forgot password form.
     */
    public function showForgotPasswordForm(): Response
    {
        return Inertia::render('Auth/ForgotPassword');
    }

    /**
     * Send password reset link.
     */
    public function sendResetLink(ForgotPasswordRequest $request): RedirectResponse
    {
        $email = $request->validated()['email'];

        // Rate limiting untuk mencegah abuse
        $key = 'forgot-password:'.$email;
        if (RateLimiter::tooManyAttempts($key, 5)) {
            $seconds = RateLimiter::availableIn($key);

            return back()->withErrors([
                'email' => "Terlalu banyak percobaan. Silakan coba lagi dalam {$seconds} detik.",
            ]);
        }

        RateLimiter::hit($key, 300); // 5 menit

        // Cek apakah user exists
        $user = User::where('email', $email)->first();

        if (! $user) {
            // Return success message even if user doesn't exist (security best practice)
            return back()->with('status', 'Jika email terdaftar, link reset password telah dikirim.');
        }

        // Generate token menggunakan Laravel's Password broker
        $token = Password::broker()->createToken($user);

        // Build reset URL
        $resetUrl = route('password.reset', [
            'token' => $token,
            'email' => $email,
        ]);

        // Send custom email
        try {
            Mail::to($email)->send(new PasswordResetMail($token, $email, $resetUrl));

            Log::info('Password reset link sent', [
                'email' => $email,
                'ip' => $request->ip(),
            ]);

            // Log password reset request activity
            $this->activityLogService->logPasswordResetRequest($email, $request);
        } catch (\Exception $e) {
            Log::error('Failed to send password reset email', [
                'email' => $email,
                'error' => $e->getMessage(),
            ]);

            return back()->withErrors([
                'email' => 'Gagal mengirim email. Silakan coba lagi.',
            ]);
        }

        return back()->with('status', 'Jika email terdaftar, link reset password telah dikirim ke email Anda.');
    }

    /**
     * Show the reset password form.
     */
    public function showResetForm(Request $request, string $token): Response
    {
        return Inertia::render('Auth/ResetPassword', [
            'token' => $token,
            'email' => $request->query('email'),
        ]);
    }

    /**
     * Reset the user's password.
     */
    public function reset(ResetPasswordRequest $request): RedirectResponse
    {
        $validated = $request->validated();
        $email = $validated['email'];
        $token = $validated['token'];
        $password = $validated['password'];

        // Rate limiting untuk reset password
        $key = 'reset-password:'.$email;
        if (RateLimiter::tooManyAttempts($key, 5)) {
            $seconds = RateLimiter::availableIn($key);

            return back()->withErrors([
                'email' => "Terlalu banyak percobaan. Silakan coba lagi dalam {$seconds} detik.",
            ]);
        }

        RateLimiter::hit($key, 300); // 5 menit

        // Use Laravel's Password broker untuk reset password
        $status = Password::broker()->reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            function (User $user, string $password): void {
                $user->forceFill([
                    'password' => Hash::make($password),
                ])->setRememberToken(Str::random(60));

                $user->save();

                event(new PasswordReset($user));

                // Invalidate all sessions except current
                DB::table('sessions')
                    ->where('user_id', $user->id)
                    ->where('id', '!=', session()->getId())
                    ->delete();

                Log::info('Password reset successful', [
                    'user_id' => $user->id,
                    'email' => $user->email,
                    'ip' => request()->ip(),
                ]);
            }
        );

        if ($status === Password::PASSWORD_RESET) {
            // Get user for logging
            $user = User::where('email', $email)->first();

            // Log password reset activity
            if ($user) {
                $this->activityLogService->logPasswordReset($user, $request);
            }

            // Clear rate limiter on success
            RateLimiter::clear('forgot-password:'.$email);
            RateLimiter::clear('reset-password:'.$email);

            return redirect()->route('login')->with('status', 'Password berhasil direset. Silakan login dengan password baru.');
        }

        return back()->withErrors([
            'email' => [__($status)],
        ]);
    }
}
