<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\Affiliate;
use App\Models\Verification;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;

class VerificationController extends Controller
{
    public function index()
    {
        $verificationId = session()->get('verificationId', null);

        if (!empty($verificationId)) {
            $verification = Verification::where('id', $verificationId)
                ->whereNull('verified_at')
                ->where('expired_at', '>', time())
                ->first();

            if (!empty($verification)) {

                $user = User::find($verification->user_id);

                if (!empty($user) and $user->status != User::$active) {
                    $data = [
                        'pageTitle' => trans('auth.email_confirmation'),
                        'username' => !empty($verification->mobile) ? 'mobile' : 'email',
                        'usernameValue' => !empty($verification->mobile) ? $verification->mobile : $verification->email,
                    ];

                    return view('web.default.auth.verification', $data);
                }
            }
        }

        return redirect('/login');
    }

    public function resendCode()
    {
        $verificationId = session()->get('verificationId', null);

        if (!empty($verificationId)) {
            $verification = Verification::where('id', $verificationId)
                ->whereNull('verified_at')
                ->where('expired_at', '>', time())
                ->first();
            if (!empty($verification)) {
                $channel = !empty($verification->mobile) ? 'mobile' : 'email';
                $sent = $this->dispatchVerificationCode($verification, $channel);

                return redirect('/verification')->with([
                    'toast' => [
                        'title' => trans('auth.account_verification'),
                        'msg' => $sent
                            ? 'تم إرسال رمز التفعيل.'
                            : 'تعذر إرسال الرمز. جرّب «إعادة الإرسال» أو تواصل مع الدعم.',
                        'status' => $sent ? 'success' : 'error',
                    ],
                ]);
            }
        }

        return redirect('/login');
    }

    public function checkConfirmed($username, $value, $user = null)
    {
        if (!empty($value)) {
            $verification = Verification::where($username, $value)
                ->where('expired_at', '>', time())
                ->where(function ($query) {
                    $query->whereNull('user_id')
                        ->orWhereHas('user');
                })
                ->first();

            $data = [];
            $time = time();

            if (!empty($verification)) {
                if (!empty($verification->verified_at)) {
                    return [
                        'status' => 'verified'
                    ];
                } else {
                    $data['created_at'] = $time;
                    $data['expired_at'] = $time + Verification::EXPIRE_TIME;

                    if (time() > $verification->expired_at) {
                        $data['code'] = $this->getNewCode();
                    } else {
                        $data['code'] = $verification->code;
                    }
                }
            } else {
                $data[$username] = $value;
                $data['code'] = $this->getNewCode();
                
                // Ensure user_id is either a valid user ID or null (never 0)
                $userId = null;
                if (!empty($user) && !empty($user->id) && $user->id > 0) {
                    $userId = $user->id;
                } elseif (auth()->check()) {
                    $authId = auth()->id();
                    if (!empty($authId) && $authId > 0) {
                        $userId = $authId;
                    }
                }
                $data['user_id'] = $userId;
                
                $data['created_at'] = $time;
                $data['expired_at'] = $time + Verification::EXPIRE_TIME;
            }

            $data['verified_at'] = null;

            $verification = Verification::updateOrCreate([$username => $value], $data);
            $verification = ensureVerificationHasId($verification, array_merge($data, [
                $username => $value,
            ]));

            session()->put('verificationId', $verification->id);

            $sent = $this->dispatchVerificationCode($verification, $username);

            return [
                'status' => 'send',
                'code_sent' => $sent,
            ];
        }

        abort(404);
    }

    /**
     * Send verification code; never throw — registration should reach /verification even if SMTP fails.
     */
    private function dispatchVerificationCode(Verification $verification, string $channel): bool
    {
        try {
            if ($channel === 'mobile') {
                $verification->sendSMSCode();

                return true;
            }

            if ($verification->sendEmailCode()) {
                return true;
            }

            $this->flashVerificationDeliveryFailed($channel, $verification);

            return false;
        } catch (\Throwable $e) {
            Log::error('verification.send.failed', [
                'channel' => $channel,
                'verification_id' => $verification->id,
                'email' => $verification->email,
                'mobile' => $verification->mobile,
                'message' => $e->getMessage(),
            ]);

            $this->flashVerificationDeliveryFailed($channel, $verification);

            return false;
        }
    }

    private function flashVerificationDeliveryFailed(string $channel, Verification $verification): void
    {
        session()->flash('verification_delivery_failed', true);

        $message = 'تعذر إرسال رمز التفعيل تلقائياً (' . ($channel === 'email' ? 'بريد' : 'SMS') . '). '
            . 'اضغط «إعادة الإرسال» بعد دقائق أو راجع مجلد السبام.';

        if ($channel === 'email' && !empty($verification->code) && session()->has('verificationId')) {
            session()->flash('verification_fallback_code', (string) $verification->code);
            $message .= ' يمكنك استخدام الرمز المعروض أدناه لإكمال التفعيل.';
        }

        session()->flash('verification_delivery_message', $message);
    }

    public function confirmCode(Request $request)
    {
        $value = $request->get('username');
        $code = $request->get('code');
        $username = $this->username($value);
        $request[$username] = $value;
        $time = time();

        Verification::where($username, $value)
            ->whereNull('verified_at')
            ->where('code', $code)
            ->where('created_at', '>', $time - 24 * 60 * 60)
            ->update([
                'verified_at' => $time,
                'expired_at' => $time + 50,
            ]);

        $rules = [
            'code' => [
                'required',
                Rule::exists('verifications')->where(function ($query) use ($value, $code, $time, $username) {
                    $query->where($username, $value)
                        ->where('code', $code)
                        ->whereNotNull('verified_at')
                        ->where('expired_at', '>', $time);
                }),
            ],
        ];

        if ($username == 'mobile') {
            $rules['mobile'] = 'required';
            $value = ltrim($value, '+');
        } else {
            $rules['email'] = 'required|email';
        }

        $this->validate($request, $rules);

        $authUser = auth()->check() ? auth()->user() : null;

        $referralCode = session()->get('referralCode', null);

        if (empty($authUser)) {
            $authUser = User::where($username, $value)
                ->first();

            $loginController = new LoginController();

            if (!empty($authUser)) {
                if (\Auth::loginUsingId($authUser->id)) {

                    if (!empty($referralCode)) {
                        Affiliate::storeReferral($authUser, $referralCode);
                    }

                    return $loginController->afterLogged($request, true);
                }
            }

            return $loginController->sendFailedLoginResponse($request);
        }
    }

    private function username($value)
    {
        $username = 'email';
        $email_regex = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i";

        if (preg_match($email_regex, $value)) {
            $username = 'email';
        } elseif (is_numeric($value)) {
            $username = 'mobile';
        }

        return $username;
    }

    private function getNewCode()
    {
        return rand(10000, 99999);
    }
}
