<?php

namespace App\Http\Controllers\Manager;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Exception;
use Carbon\Carbon;
use App\Models\Vendor\Manager;
use App\Constants\GlobalConst;
use App\Models\ManagerPasswordReset;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
use App\Providers\Admin\BasicSettingsProvider;
use Illuminate\Validation\ValidationException;
use App\Notifications\User\Auth\PasswordResetEmail;

class ManagerForgotPasswordController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function showForgotForm()
    {
        $page_title = setPageTitle("Forgot Password");
        return view('manager.auth.forgot-password.forgot',compact('page_title'));
    }

    /**
     * Send Verification code to Manager email/phone.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function sendCode(Request $request)
    {
        $request->validate([
            'credentials'   => "required|string|max:100",
        ]);

        if(check_email($request->credentials)) $column = "email";
        $manager = Manager::where($column,$request->credentials)->first();
        if(!$manager) {
            throw ValidationException::withMessages([
                'credentials'       => "Manager doesn't exists.",
            ]);
        }

        $token = generate_unique_string("user_password_resets","token",80);
        $code = generate_random_code();

        try{
            ManagerPasswordReset::where("manager_id",$manager->id)->delete();
            $password_reset = ManagerPasswordReset::create([
                'manager_id'       => $manager->id,

                'token'         => $token,
                'code'          => $code,
            ]);
            try{
                $manager->notify(new PasswordResetEmail($manager,$password_reset));
            }catch(Exception $e){}
        }catch(Exception $e) {
            return back()->with(['error' => ['Something went wrong! Please try again.']]);
        }
        return redirect()->route('manager.password.forgot.code.verify.form',$token)->with(['success' => ['Verification code sended to your email address.']]);
    }


    public function showVerifyForm($token) {
        $page_title = setPageTitle("Verify manager");
        $password_reset = ManagerPasswordReset::where("token",$token)->first();
        if(!$password_reset) return redirect()->route('manager.password.forgot')->with(['error' => ['Password Reset Token Expired']]);
        $resend_time = 0;
        if(Carbon::now() <= $password_reset->created_at->addMinutes(GlobalConst::USER_PASS_RESEND_TIME_MINUTE)) {
            $resend_time = Carbon::now()->diffInSeconds($password_reset->created_at->addMinutes(GlobalConst::USER_PASS_RESEND_TIME_MINUTE));
        }
        $manager_email = $password_reset->manager->email ?? "";
        return view('manager.auth.forgot-password.verify',compact('page_title','token','manager_email','resend_time'));
    }

   /**
     * OTP Verification.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function verifyCode(Request $request, $token)
    {
        $request->merge(['token' => $token]);
        $validated = Validator::make($request->all(), [
            'token'         => "required|string|exists:manager_password_resets,token",
            'code'          => "required",
        ])->validate();

        $code = implode('', $request->input('code'));
        $manager_code = ManagerPasswordReset::where('token',$token)->first();

        if ($code == $manager_code->code) {
            $basic_settings = BasicSettingsProvider::get();
            $otp_exp_seconds = $basic_settings->otp_exp_seconds ?? 0;

            $password_reset = ManagerPasswordReset::where("token", $token)->first();

            if (Carbon::now() >= $password_reset->created_at->addSeconds($otp_exp_seconds)) {
                foreach (ManagerPasswordReset::get() as $item) {
                    if (Carbon::now() >= $item->created_at->addSeconds($otp_exp_seconds)) {
                        $item->delete();
                    }
                }
                return redirect()->route('manager.password.forgot')->with(['error' => [__('Session expired. Please try again')]]);
            }
        } else {
            throw ValidationException::withMessages([
                'code'      => __("Verification Otp is Invalid"),
            ]);
        }

        return redirect()->route('manager.password.forgot.reset.form', $token);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function resendCode($token)
    {
        $password_reset = ManagerPasswordReset::where('token',$token)->first();
        if(!$password_reset) return back()->with(['error' => ['Request token is invalid']]);
        if(Carbon::now() <= $password_reset->created_at->addMinutes(GlobalConst::USER_PASS_RESEND_TIME_MINUTE)) {
            throw ValidationException::withMessages([
                'code'      => 'You can resend verification code after '.Carbon::now()->diffInSeconds($password_reset->created_at->addMinutes(GlobalConst::USER_PASS_RESEND_TIME_MINUTE)). ' seconds',
            ]);
        }

        DB::beginTransaction();
        try{
            $update_data = [
                'code'          => generate_random_code(),
                'created_at'    => now(),
                'token'         => $token,
            ];
            DB::table('user_password_resets')->where('token',$token)->update($update_data);
            try{
                $password_reset->manager->notify(new PasswordResetEmail($password_reset->manager,(object) $update_data));
            }catch(Exception $e){}
            DB::commit();
        }catch(Exception $e) {
            DB::rollback();
            return back()->with(['error' => ['Something went wrong. please try again']]);
        }
        return redirect()->route('manager.password.forgot.code.verify.form',$token)->with(['success' => ['Verification code resend success!']]);

    }


    public function showResetForm($token) {
        $page_title = setPageTitle("Reset Password");
        return view('manager.auth.forgot-password.reset',compact('page_title','token'));
    }


    public function resetPassword(Request $request,$token) {
        $basic_settings = BasicSettingsProvider::get();
        $password_rule = "required|string|min:6|confirmed";
        if($basic_settings->secure_password) {
            $password_rule = ["required",Password::min(8)->letters()->mixedCase()->numbers()->symbols()->uncompromised(),"confirmed"];
        }

        $request->merge(['token' => $token]);
        $validated = Validator::make($request->all(),[
            'token'         => "required|string|exists:user_password_resets,token",
            'password'      => $password_rule,
        ])->validate();

        $password_reset = ManagerPasswordReset::where("token",$token)->first();
        if(!$password_reset) {
            throw ValidationException::withMessages([
                'password'      => "Invalid Request. Please try again.",
            ]);
        }

        try{
            $password_reset->manager->update([
                'password'      => Hash::make($validated['password']),
            ]);
            $password_reset->delete();
        }catch(Exception $e) {
            return back()->with(['error' => ['Something went wrong! Please try again.']]);
        }

        return redirect()->route('manager.login')->with(['success' => ['Password reset success. Please login with new password.']]);
    }

}
