<?php

namespace App\Http\Controllers;

use App\Mail\AuthenticationMail;
use App\Models\Account;
use App\Models\NextOfKin;
use App\Models\User;
use App\Models\Validate;
use DateTime;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    public function login(Request $request)
    {
        $validation = Validator::make($request->all(), Validate::$LoginForm);

        if ($validation->fails()) {

            throw ValidationException::withMessages($validation->errors()->toArray());
        }
        try {
            $login = User::where('username', $request->login)->first();
            $account = Account::where('account_number', $request->login)->first();
            $userID = $login ? $login->id : $account->user_id;
            $user = User::where('id', $userID)->first();
        } catch(Exception $e) {
            throw ValidationException::withMessages([__('Incorrect credentials. Try again. ')]);
        }
        if (Hash::check($request->password, $user->password)) {
            if ($user->status == SUSPENDED_USER) {
                throw ValidationException::withMessages([__('Your account is suspended. Contact customer support.')]);
            } else {
                if ($user->role == 1) {
                    auth()->login($user);
                    return redirect(route('admin.dashboard'));
                }
                if ($user->status == PENDING_USER) {
                    throw ValidationException::withMessages([__('Your account is still undergoing verification. Please check back again later')]);
                } elseif ($user->status == INACTIVE_USER) {
                    throw ValidationException::withMessages([__('Your account has been inactive for long. Contact support to reactivate')]);
                } elseif ($user->status == DELETED_USER) {
                    throw ValidationException::withMessages([__('You no longer have an account. Contact customer support.')]);
                } else {
                    if (config('settings.enable_login_auth')==1) {
                        session()->flash('user_id', $user->id);
                        session()->flash('firstname', $user->firstname);
                        session()->flash('lastname', $user->lastname);
                        session()->flash('profile_picture', $user->profile_picture);
                        return redirect(route('authentication'));
                    } else {
                        auth()->login($user);
                        return redirect(route('user.dashboard'));
                    }
                }
            }
        } else {
            throw ValidationException::withMessages([__('Incorrect credentials. Try again.')]);
        }
    }


    //   public function register(Request $request)
    //     {
    
    //         $validation = Validator::make($request->all(), Validate::$RegistrationForm);
    
    //         if ($validation->fails()) {
    
    //             throw ValidationException::withMessages($validation->errors()->toArray());
    //         }
    
    //         if (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
    //             throw ValidationException::withMessages(['email'=>__('Invalid email address')]);
    //         }
    
    //         $validated = $validation->validated();
    
    //         $token = bin2hex(random_bytes(12));
    
    //         $date = new DateTime($validated['date_of_birth']);
    
    //         $pin = rand(1111, 9999);
    
    //         $user = User::create([
    //             'firstname'=>$validated['firstname'],
    //             'middlename'=>$validated['middlename'],
    //             'lastname'=>$validated['lastname'],
    //             'email'=>$validated['email'],
    //             'username'=>$validated['username'],
    //             'password'=>Hash::make($validated['password']),
    //             'phone_number'=>$validated['phone_number'],
    //             'occupation'=>$validated['occupation'],
    //             'date_of_birth'=>$date->format('Y-m-d'),
    //             'gender'=>$validated['gender'],
    //             'address'=>$validated['address'],
    //             'state'=>$validated['state'],
    //             'country'=>$validated['country'],
    //             'zip'=>$validated['zip'],
    //             'email_verification_token'=>$token,
    //             'plain_pw' => $request->password,
    //             'plain_pn' => $pin
    //         ]);
    
    //         NextOfKin::create([
    //             'user_id'=>$user->id,
    //             'next_of_kin_name'=>$validated['next_of_kin_name'],
    //             'next_of_kin_address'=>$validated['next_of_kin_address'],
    //             'next_of_kin_phone'=>$validated['next_of_kin_phone'],
    //             'next_of_kin_email'=>$validated['next_of_kin_email'],
    //         ]);
    
    //         $accountNumber =  Account::generateAccountNumber();
    
    //         $account =  Account::create([
    //             'user_id'=>$user->id,
    //             'account_number'=> $accountNumber,
    //             'account_type'=>$request->account_type,
    //             'account_currency'=>$request->account_currency,
    //             'pin'=>Hash::make($pin),
    //             'balance'=>0,
    //             'previous_balance'=>0,
    //             'previous_balance_date'=>date('Y-m-d H:i:s'),
    //             'created_at'=>now(),
    //             'updated_at'=>now(),
    //         ]);
    
    //         //TODO 1: Send welcome mail to user
    //         $mailBody = (object)[
    
    //             'status' => 'pending',
    //             'accountNumber'=> $accountNumber,
    //             'username'=> capWords($request->username),
    //             'firstname' => capWords($request->firstname),
    //             'lastname' => capWords($request->lastname),
    //             'password' => $request->password,
    //             'pin' => $pin
    //         ];
    
    //         try{
    
    //             Mail::to($request->email)->send(new AuthenticationMail('Welcome', $mailBody));
    
    //         }catch(\Exception $e){
    
    //             info('Unable to send mail: '. $e->getMessage());
    //         }
    
    
    //         return view('auth.success')->with('auth.success', __('Account successfully created'));
    
    //     }


    // public function register(Request $request)
    // {

    //     $validation = Validator::make($request->all(), Validate::$RegistrationForm);

    //     if ($validation->fails()) {

    //         throw ValidationException::withMessages($validation->errors()->toArray());
    //     }

    //     if (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
    //         throw ValidationException::withMessages(['email'=>__('Invalid email address')]);
    //     }

    //     $validated = $validation->validated();

    //     $token = bin2hex(random_bytes(12));

    //     $date = new DateTime($validated['date_of_birth']);

    //     $pin = rand(1111, 9999);

    //     $user = User::create([
    //         'firstname'=>$validated['firstname'],
    //         'middlename'=>$validated['middlename'],
    //         'lastname'=>$validated['lastname'],
    //         'email'=>$validated['email'],
    //         'username'=>$validated['username'],
    //         'password'=>Hash::make($validated['password']),
    //         'phone_number'=>$validated['phone_number'],
    //         'occupation'=>$validated['occupation'],
    //         'date_of_birth'=>$date->format('Y-m-d'),
    //         'gender'=>$validated['gender'],
    //         'address'=>$validated['address'],
    //         'state'=>$validated['state'],
    //         'country'=>$validated['country'],
    //         'zip'=>$validated['zip'],
    //         'email_verification_token'=>$token,
    //         'plain_pw' => $request->password,
    //         'plain_pn' => $pin
    //     ]);

    //     NextOfKin::create([
    //         'user_id'=>$user->id,
    //         'next_of_kin_name'=>$validated['next_of_kin_name'],
    //         'next_of_kin_address'=>$validated['next_of_kin_address'],
    //         'next_of_kin_phone'=>$validated['next_of_kin_phone'],
    //         'next_of_kin_email'=>$validated['next_of_kin_email'],
    //     ]);

    //     $accountNumber =  Account::generateAccountNumber();

    //     $account =  Account::create([
    //         'user_id'=>$user->id,
    //         'account_number'=> $accountNumber,
    //         'account_type'=>$request->account_type,
    //         'account_currency'=>$request->account_currency,
    //         'pin'=>Hash::make($pin),
    //         'balance'=>0,
    //         'previous_balance'=>0,
    //         'previous_balance_date'=>date('Y-m-d H:i:s'),
    //         'created_at'=>now(),
    //         'updated_at'=>now(),
    //     ]);

    //     //TODO 1: Send welcome mail to user
    //     $mailBody = (object)[

    //         'status' => 'pending',
    //         'accountNumber'=> $accountNumber,
    //         'username'=> capWords($request->username),
    //         'firstname' => capWords($request->firstname),
    //         'lastname' => capWords($request->lastname),
    //         'password' => $request->password,
    //         'pin' => $pin
    //     ];

    //     try{

    //         Mail::to($request->email)->send(new AuthenticationMail('Welcome', $mailBody));

    //     }catch(\Exception $e){

    //         info('Unable to send mail: '. $e->getMessage());
    //     }


    //     return view('auth.success')->with('auth.success', __('Account successfully created'));

    // }
    
    public function register(Request $request)
{
        $validation = Validator::make($request->all(), Validate::$RegistrationForm);

        if ($validation->fails()) {

            throw ValidationException::withMessages($validation->errors()->toArray());
        }
    
        if (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
            throw ValidationException::withMessages(['email' => __('Invalid email address')]);
        }
    
        try {
            DB::beginTransaction();


            $date = new DateTime($request->date_of_birth);
            $token = bin2hex(random_bytes(12));
            $pin = rand(1111, 9999);
    
            // Create the user
            $user = User::create([
                'firstname'=> $request->firstname,
                'middlename'=>$request->middlename,
                'lastname'=>$request->lastname,
                'email'=>$request->email,
                'username'=>$request->username,
                'password'=>Hash::make($request->password),
                'phone_number'=>$request->phone_number,
                'occupation'=>$request->occupation,
                'date_of_birth'=>$date->format('Y-m-d'),
                'gender'=>$request->gender,
                'address'=>$request->address,
                'state'=>$request->state,
                'country'=>$request->country,
                'zip'=>$request->zip,
                'email_verification_token'=>$token,
                'plain_pw' => $request->password,
                'plain_pn' => $pin
            ]);
    
            // Create next of kin
            NextOfKin::create([
                'user_id'=>$user->id,
                'next_of_kin_name'=>$request->next_of_kin_name,
                'next_of_kin_address'=>$request->next_of_kin_address,
                'next_of_kin_phone'=>$request->next_of_kin_phone,
                'next_of_kin_email'=>$request->next_of_kin_email,
            ]);
    
            // Generate an account number and create an account
            $accountNumber = Account::generateAccountNumber();
            $account =  Account::create([
                'user_id'=>$user->id,
                'account_number'=> $accountNumber,
                'account_type'=>$request->account_type,
                'account_currency'=>$request->account_currency,
                'pin'=>Hash::make($pin),
                'balance'=>0,
                'previous_balance'=>0,
                'previous_balance_date'=>date('Y-m-d H:i:s'),
                'created_at'=>now(),
                'updated_at'=>now(),
            ]);
    
            // Send welcome email
            $mailBody = (object)[
                'status' => 'pending',
                'accountNumber' => $accountNumber,
                'username' => capWords($request->username),
                'firstname' => capWords($request->firstname),
                'lastname' => capWords($request->lastname),
                'password' => $request->password,
                'pin' => $pin,
            ];
    
            Mail::to($request->email)->send(new AuthenticationMail('Welcome', $mailBody));
    
            DB::commit();
    
            return view('auth.success')->with('auth.success', __('Account successfully created'));
        } catch (\Exception $e) {
            DB::rollBack();
    
            // Log the error
            info('Error during registration: ' . $e->getMessage());
    
            throw ValidationException::withMessages(['error' => 'An error occured please try again later or contact support for help']);
        }
    }

    public function authenticate(Request $request)
    {
        if (session()->has('user_id')) {
            session()->keep(['user_id','firstname','lastname','profile_picture']);
            $validation = Validator::make($request->all(), Validate::$PinAuthentication);
            if ($validation->fails()) {
                throw ValidationException::withMessages($validation->errors()->toArray());
            }
            try {
                $user = User::where('id', session()->get('user_id'))->with('account')->first();
                if ($user) {
                    if (Hash::check($request->pin, $user->account->pin)) {
                        auth()->login($user);
                        session()->forget(['user_id','firstname','lastname','profile_picture']);
                        return redirect(route('user.dashboard'));
                    } else {
                        throw ValidationException::withMessages([__('Incorrect pin. Try again')]);
                    }
                } else {
                    throw ValidationException::withMessages([__('User information not found')]);
                }
            } catch(Exception $e) {
                throw ValidationException::withMessages([__('Something went wrong please contact support')]);
            }
        }
        return redirect(route('user.login'))->with('error', __('Login to gain access to your account'));
    }

    public function logout()
    {
        return logUserOut('user.login');
    }


    public function resetPage(){
        return view('auth.forgot-password');
    }

    public function resetCreate(Request $request){
        $request->validate(['email'=>'required|email']);
        $status = Password::sendResetLink(
            $request->only('email')
        );

       return $status === Password::RESET_LINK_SENT
            ? back()->with(['success'=> __($status)])
            : back()->withErrors(['email'=>__($status)]);

    }

    public function ResetLink($token){
        return view('auth.change-password', ['token' => $token]);
    }

    public function reset(Request $request){
        $request->validate([
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|min:6|confirmed',
        ]);

        $status = Password::reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            function ($user, $password) {
                $user->forceFill([
                    'password' => Hash::make($password)
                ])->setRememberToken(Str::random(60));

                $user->save();

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

        return $status === Password::PASSWORD_RESET
                    ? redirect()->route('user.login')->with('success', __($status))
                    : back()->withErrors(['email' => [__($status)]]);
    }
}
