<?php

namespace App\Http\Controllers\AdminAuth;

use App\Http\Controllers\Controller;
use App\Mail\AdminOtpMail;
use App\Models\Admin;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;

class AdminPasswordResetController extends Controller
{
    protected $otpExpiryMinutes = 10;
    protected $resendCooldownSeconds = 60;
    protected $otpRequestMaxAttempts = 5;
    protected $otpRequestDecaySeconds = 600;
    protected $otpVerifyMaxAttempts = 5;
    protected $otpVerifyDecaySeconds = 600;

    public function showRequestForm()
    {
        return view('admin.auth.passwords.email');
    }

    public function sendOtp(Request $request)
    {
        $request->validate(['email' => 'required|email']);
        $email = Str::lower(trim((string) $request->email));
        $requestKey = $this->otpRequestThrottleKey($request, $email);

        if (RateLimiter::tooManyAttempts($requestKey, $this->otpRequestMaxAttempts)) {
            $seconds = RateLimiter::availableIn($requestKey);

            return back()
                ->withErrors(['email' => "অল্প সময়ে অনেকবার OTP চাওয়া হয়েছে। {$seconds} সেকেন্ড পরে আবার চেষ্টা করুন।"])
                ->withInput();
        }

        $admin = Admin::where('email', $email)->first();
        if (!$admin) {
            RateLimiter::hit($requestKey, $this->otpRequestDecaySeconds);

            return back()
                ->withErrors(['email' => 'এই ইমেইলে কোনো অ্যাডমিন নেই।'])
                ->withInput();
        }

        // রেট-লিমিট: শেষ রিকোয়েস্ট থেকে 60s না গেলে নতুন OTP নয়
        $last = DB::table('admin_password_resets')
            ->where('email', $email)->orderByDesc('created_at')->first();
        if ($last && Carbon::parse($last->created_at)->diffInSeconds(now()) < $this->resendCooldownSeconds) {
            return back()
                ->withErrors(['email' => 'আরেকটি OTP নিতে অল্পক্ষণ অপেক্ষা করুন।'])
                ->withInput();
        }

        $otp = random_int(100000, 999999);

        DB::table('admin_password_resets')->insert([
            'email'      => $email,
            'token'      => Hash::make($otp),                 // hash store
            'expires_at' => now()->addMinutes($this->otpExpiryMinutes),
            'created_at' => now(),
        ]);

        Mail::to($email)->send(new AdminOtpMail($otp, $this->otpExpiryMinutes));
        RateLimiter::hit($requestKey, $this->otpRequestDecaySeconds);
        RateLimiter::clear($this->otpVerifyThrottleKey($request, $email));

        return redirect()->route('admin.password.verify.form')
            ->with('status', 'OTP ইমেইলে পাঠানো হয়েছে (মেয়াদ ' . $this->otpExpiryMinutes . ' মিনিট)।');
    }

    public function showVerifyForm()
    {
        return view('admin.auth.passwords.verify');
    }

    public function verifyOtp(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'otp'   => 'required|digits:6',
        ]);

        $email = Str::lower(trim((string) $request->email));
        $otp   = $request->otp;
        $verifyKey = $this->otpVerifyThrottleKey($request, $email);

        if (RateLimiter::tooManyAttempts($verifyKey, $this->otpVerifyMaxAttempts)) {
            $seconds = RateLimiter::availableIn($verifyKey);

            return back()
                ->withErrors(['otp' => "অনেকবার ভুল OTP দেওয়া হয়েছে। {$seconds} সেকেন্ড পরে আবার চেষ্টা করুন।"])
                ->withInput($request->except('otp'));
        }

        $record = DB::table('admin_password_resets')
            ->where('email', $email)
            ->where('expires_at', '>', now())
            ->orderByDesc('created_at')
            ->first();

        if (!$record || !Hash::check($otp, $record->token)) {
            RateLimiter::hit($verifyKey, $this->otpVerifyDecaySeconds);

            return back()
                ->withErrors(['otp' => 'ভুল বা মেয়াদোত্তীর্ণ OTP।'])
                ->withInput($request->except('otp'));
        }

        RateLimiter::clear($verifyKey);
        RateLimiter::clear($this->otpRequestThrottleKey($request, $email));

        // Valid → পুরোনো রেকর্ড ক্লিয়ার
        DB::table('admin_password_resets')->where('email', $email)->delete();

        // session flag
        $request->session()->put('admin_password_reset_email', $email);

        return redirect()->route('admin.password.reset.form');
    }

    public function showResetForm(Request $request)
    {
        if (!$request->session()->has('admin_password_reset_email')) {
            return redirect()->route('admin.password.request')
                   ->withErrors(['email' => 'OTP ভেরিফাই করে আসুন।']);
        }
        return view('admin.auth.passwords.reset');
    }

    public function resetPassword(Request $request)
    {
        $request->validate([
            'password' => 'required|string|min:8|confirmed',
        ]);

        $email = $request->session()->get('admin_password_reset_email');
        if (!$email) {
            return redirect()->route('admin.password.request')
                   ->withErrors(['email' => 'সেশন শেষ হয়ে গেছে। প্রথম থেকে করুন।']);
        }

        $admin = Admin::where('email', $email)->first();
        if (!$admin) {
            return redirect()->route('admin.password.request')
                   ->withErrors(['email' => 'অ্যাডমিন পাওয়া যায়নি।']);
        }

        $admin->password = bcrypt($request->password);
        $admin->remember_token = null; // পুরোনো remember টোকেন ইনভ্যালিড
        $admin->save();

        $request->session()->forget('admin_password_reset_email');
        $request->session()->regenerate();

        return redirect()->route('admin.login')->with('status', 'পাসওয়ার্ড রিসেট হয়েছে, লগইন করুন।');
    }

    private function otpRequestThrottleKey(Request $request, string $email): string
    {
        return 'admin-password-reset-request:' . Str::lower($email) . '|' . $request->ip();
    }

    private function otpVerifyThrottleKey(Request $request, string $email): string
    {
        return 'admin-password-reset-verify:' . Str::lower($email) . '|' . $request->ip();
    }
}
