<?php

namespace App\Http\Controllers\Auth;

use App\Actions\Fortify\ResetUserPassword;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\RequestPasswordResetCodeRequest;
use App\Http\Requests\Auth\ResetPasswordWithCodeRequest;
use App\Jobs\V1\SendPasswordResetJob;
use App\Jobs\V1\SendPasswordUpdatedJob;
use App\Models\User;
use App\Models\Vrm\AuthToken;
use App\Services\Vrm\TokenService;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class PasswordResetCodeController extends Controller
{
    /**
     * Show the forgot password page.
     */
    public function create(): View
    {
        return view('pages.member.auth.forgot-password');
    }

    /**
     * Send a password reset code to the provided email.
     */
    public function store(RequestPasswordResetCodeRequest $request, TokenService $tokenService): RedirectResponse
    {
        $email = (string) $request->string('email');
        $user = User::query()->where('email', $email)->first();

        if ($user) {
            AuthToken::query()
                ->where('user_id', $user->id)
                ->where('type', 'password_reset')
                ->where('name', 'reset_password')
                ->delete();

            $resetCode = $tokenService->generateNumericOtp(8);

            $tokenService->generateToken(
                userId: (int) $user->id,
                type: 'password_reset',
                name: 'reset_password',
                token: $resetCode,
                expiryMinutes: 60,
            );

            dispatch(new SendPasswordResetJob($user, $resetCode));
        }

        return redirect()->route('password.reset', ['email' => $email])->with(
            'status',
            __('If your email exists in our system, an 8-digit reset code has been sent.'),
        );
    }

    /**
     * Show the reset password page.
     */
    public function edit(Request $request): View
    {
        return view('pages.member.auth.reset-password', [
            'email' => (string) $request->query('email', ''),
        ]);
    }

    /**
     * Verify reset code, reset password, then sign the user in.
     */
    public function update(
        ResetPasswordWithCodeRequest $request,
        TokenService $tokenService,
        ResetUserPassword $resetUserPassword,
        LoginResponseContract $loginResponse,
    ): RedirectResponse|\Symfony\Component\HttpFoundation\Response {
        $email = (string) $request->string('email');
        $user = User::query()->where('email', $email)->first();

        if (! $user) {
            return back()->withErrors([
                'verification_code' => __('The reset code is invalid or expired.'),
            ])->onlyInput('email');
        }

        $token = $tokenService->verifyToken(
            token: (string) $request->string('verification_code'),
            type: 'password_reset',
            name: 'reset_password',
            userId: (int) $user->id,
            destroyOnUse: true,
        );

        if (! $token) {
            return back()->withErrors([
                'verification_code' => __('The reset code is invalid or expired.'),
            ])->onlyInput('email');
        }

        $resetUserPassword->reset($user, [
            'password' => (string) $request->input('password'),
            'password_confirmation' => (string) $request->input('password_confirmation'),
        ]);

        dispatch(new SendPasswordUpdatedJob($user));

        Auth::guard('web')->login($user);
        $request->session()->regenerate();

        return $loginResponse->toResponse($request);
    }
}
