<?php

namespace App\Http\Controllers\Auth;

use App\Helpers\PasswordHelper;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\Validation\ValidationException;
use Inertia\Inertia;
use Inertia\Response;

class NewPasswordController extends Controller
{
    /**
     * Show the password reset page.
     */
    public function create(Request $request): Response|RedirectResponse
    {
        // Validate that email and token are provided
        if (!$request->email || !$request->route('token')) {
            return to_route('password.request')
                ->withErrors(['email' => 'The password reset link is invalid or has expired.']);
        }

        // Validate the token before showing the form
        $status = $this->validateResetToken($request);
        
        if ($status !== Password::PASSWORD_RESET) {
            // Custom message for invalid/used token
            $errorMessage = $status === Password::INVALID_TOKEN 
                ? 'You have already changed your password with this link. Please request a new password reset link if needed.'
                : __($status);
                
            return to_route('password.request')
                ->withErrors(['email' => $errorMessage]);
        }

        return Inertia::render('auth/reset-password', [
            'email' => $request->email,
            'token' => $request->route('token'),
        ]);
    }

    /**
     * Validate the reset token without performing the reset.
     */
    protected function validateResetToken(Request $request): string
    {
        $broker = Password::broker();
        
        $credentials = [
            'email' => $request->email,
            'token' => $request->route('token'),
        ];

        // Get the user
        $user = $broker->getUser($credentials);
        
        if (is_null($user)) {
            return Password::INVALID_USER;
        }

        // Check if token exists and is valid
        if (!$broker->tokenExists($user, $credentials['token'])) {
            return Password::INVALID_TOKEN;
        }

        return Password::PASSWORD_RESET;
    }

    /**
     * Handle an incoming new password request.
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'token' => 'required',
            'email' => 'required|email',
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        // Here we will attempt to reset the user's password. If it is successful we
        // will update the password on an actual user model and persist it to the
        // database. Otherwise we will parse the error and return the response.
        $status = Password::reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            function ($user) use ($request) {
                // Use pw.sql changePasswd stored procedure
                DB::statement('CALL changePasswd(?, ?)', [
                    $user->name,
                    PasswordHelper::encryptPassword($user->name, $request->password),
                ]);

                event(new PasswordReset($user));
            }
        );

        // If the password was successfully reset, we will redirect the user back to
        // the application's home authenticated view. If there is an error we can
        // redirect them back to where they came from with their error message.
        if ($status == Password::PasswordReset) {
            // Laravel automatically deletes the token after successful reset via Password::reset()
            // This ensures the token cannot be reused for security purposes
            return to_route('login')->with('status', __($status));
        }

        throw ValidationException::withMessages([
            'email' => [__($status)],
        ]);
    }
}
