<?php

namespace App\Http\Controllers;

use App\Models\OtpCode;
use App\Models\Role;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class AuthController extends Controller
{
    public function showLogin()
    {
        return view('auth.login');
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            'login' => ['required', 'string'],
            'password' => ['required', 'string'],
        ]);

        $field = filter_var($credentials['login'], FILTER_VALIDATE_EMAIL) ? 'email' : 'mobile';
        $user = User::query()->where($field, $credentials['login'])->first();

        if (!$user || !Hash::check($credentials['password'], $user->password)) {
            return back()->withErrors([
                'login' => 'The provided credentials do not match our records.',
            ])->onlyInput('login');
        }

        if ($user->status === 'otp_pending') {
            return redirect()->route('register.verify.form', ['email' => $user->email])->with('status', 'Please verify the OTP sent to your email and mobile before logging in.');
        }

        if ($user->status !== 'active') {
            return back()->withErrors([
                'login' => 'Your account is not active. Please contact support.',
            ])->onlyInput('login');
        }

        Auth::login($user, $request->boolean('remember'));

        $request->session()->regenerate();

        if ($request->user()?->isAdmin()) {
            return redirect()->route('admin.dashboard')->with('status', 'Welcome back, administrator.');
        }

        return redirect()->route('dashboard')->with('status', 'Welcome back.');
    }

    public function showRegister()
    {
        return view('auth.register');
    }

    public function register(Request $request)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', 'unique:users,email'],
            'mobile' => ['required', 'string', 'min:10', 'max:20', 'unique:users,mobile'],
            'password' => ['required', 'confirmed', 'min:8'],
            'agree_terms' => ['accepted'],
        ]);

        $customerRole = Role::query()->where('slug', 'customer')->firstOrFail();

        $user = User::query()->create([
            'role_id' => $customerRole->id,
            'name' => $validated['name'],
            'email' => $validated['email'],
            'mobile' => $validated['mobile'],
            'password' => Hash::make($validated['password']),
            'status' => 'otp_pending',
            'wallet_balance' => 0,
        ]);

        $otp = $this->issueOtp($user);
        $request->session()->put('otp_user_email', $user->email);
        $request->session()->flash('demo_otp', $otp->code);

        return redirect()->route('register.verify.form', ['email' => $user->email])->with('status', 'Account created. Enter the OTP to activate your account.');
    }

    public function showVerify(Request $request)
    {
        $email = $request->query('email', $request->session()->get('otp_user_email'));
        abort_unless($email, 404);

        $user = User::query()->where('email', $email)->firstOrFail();

        return view('auth.verify', [
            'user' => $user,
            'demoOtp' => session('demo_otp'),
        ]);
    }

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

        $user = User::query()->where('email', $validated['email'])->firstOrFail();

        $otp = $user->otpCodes()
            ->where('purpose', 'register')
            ->whereNull('verified_at')
            ->where('code', $validated['otp'])
            ->where('expires_at', '>=', now())
            ->latest()
            ->first();

        if (!$otp) {
            return back()->withErrors([
                'otp' => 'The OTP is invalid or has expired.',
            ]);
        }

        $otp->update(['verified_at' => now()]);
        $user->update([
            'status' => 'active',
            'email_verified_at' => now(),
        ]);

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

        return redirect()->route('dashboard')->with('status', 'Your account has been verified successfully.');
    }

    public function resendOtp(Request $request)
    {
        $validated = $request->validate([
            'email' => ['required', 'email'],
        ]);

        $user = User::query()->where('email', $validated['email'])->firstOrFail();
        $otp = $this->issueOtp($user);

        return back()->with('status', 'A fresh OTP has been generated for demo use: ' . $otp->code);
    }

    public function logout(Request $request)
    {
        Auth::logout();

        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('home')->with('status', 'You have been logged out.');
    }

    private function issueOtp(User $user): OtpCode
    {
        $user->otpCodes()->where('purpose', 'register')->whereNull('verified_at')->delete();

        return OtpCode::query()->create([
            'user_id' => $user->id,
            'channel' => 'email',
            'recipient' => $user->email,
            'code' => (string) random_int(100000, 999999),
            'purpose' => 'register',
            'expires_at' => now()->addMinutes(10),
        ]);
    }
}
