<?php

namespace App\Http\Controllers;

use Auth;
use Carbon\Carbon;
use App\Models\Bank;
use App\Models\User;
use App\Models\Wallet;
use App\Models\Deposit;
use App\Lib\CurlRequest;
use App\Models\BankAccount;
use Illuminate\Http\Request;
use App\Http\Component\AppController;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;


class AuthorizationController extends AppController
{
    private $activeTemplate;
    
    public function __construct()
    {
        return $this->activeTemplate = activeTemplate();
    }
    public function checkValidCode($user, $code, $add_min = 10000)
    {
        if (!$code) return false;
        if (!$user->ver_code_send_at) return false;
        if ($user->ver_code_send_at->addMinutes($add_min) < Carbon::now()) return false;
        if ($user->ver_code !== $code) return false;
        return true;
    }


    public function authorizeForm()
    {

        if (auth()->check()) {
            $user = auth()->user();
            if (!$user->status) {
                Auth::logout();
            }elseif (!$user->ev) {
                if (!$this->checkValidCode($user, $user->ver_code)) {
                    $user->ver_code = verificationCode(6);
                    $user->ver_code_send_at = Carbon::now();
                    $user->save();
                    sendEmail($user, 'EVER_CODE', [
                        'code' => $user->ver_code
                    ]);
                }
                $pageTitle = 'Email verification form';
                return view($this->activeTemplate.'user.auth.authorization.email', compact('user', 'pageTitle'));
            }elseif (!$user->sv) {
                if (!$this->checkValidCode($user, $user->ver_code)) {
                    $user->ver_code = verificationCode(6);
                    $user->ver_code_send_at = Carbon::now();
                    $user->save();
                    sendSms($user, 'SVER_CODE', [
                        'code' => $user->ver_code
                    ]);
                }
                $pageTitle = 'SMS verification form';
                return view($this->activeTemplate.'user.auth.authorization.sms', compact('user', 'pageTitle'));
            }elseif (!$user->tv) {
                $pageTitle = 'Google Authenticator';
                return view($this->activeTemplate.'user.auth.authorization.2fa', compact('user', 'pageTitle'));
            }else{
                return redirect()->route('user.home');
            }

        }

        return redirect()->route('user.login');
    }

    public function sendVerifyCode(Request $request)
    {
        $user = Auth::user();


        if ($this->checkValidCode($user, $user->ver_code, 2)) {
            $target_time = $user->ver_code_send_at->addMinutes(2)->timestamp;
            $delay = $target_time - time();
            throw ValidationException::withMessages(['resend' => 'Please Try after ' . $delay . ' Seconds']);
        }
        if (!$this->checkValidCode($user, $user->ver_code)) {
            $user->ver_code = verificationCode(6);
            $user->ver_code_send_at = Carbon::now();
            $user->save();
        } else {
            $user->ver_code = $user->ver_code;
            $user->ver_code_send_at = Carbon::now();
            $user->save();
        }



        if ($request->type === 'email') {
            sendEmail($user, 'EVER_CODE',[
                'code' => $user->ver_code
            ]);

            $notify[] = ['success', 'Email verification code sent successfully'];
            return back()->withNotify($notify);
        } elseif ($request->type === 'phone') {
            sendSms($user, 'SVER_CODE', [
                'code' => $user->ver_code
            ]);
            $notify[] = ['success', 'SMS verification code sent successfully'];
            return back()->withNotify($notify);
        } else {
            throw ValidationException::withMessages(['resend' => 'Sending Failed']);
        }
    }

    public function emailVerification(Request $request)
    {
        $request->validate([
            'email_verified_code'=>'required'
        ]);


        $email_verified_code = str_replace(' ','',$request->email_verified_code);
        $user = Auth::user();

        if ($this->checkValidCode($user, $email_verified_code)) {
            $user->ev = 1;
            $user->ver_code = null;
            $user->ver_code_send_at = null;
            $user->save();
            return redirect()->route('user.home');
        }
        throw ValidationException::withMessages(['email_verified_code' => 'Verification code didn\'t match!']);
    }

    public function smsVerification(Request $request)
    {
        $request->validate([
            'sms_verified_code' => 'required',
        ]);


        $sms_verified_code =  str_replace(' ','',$request->sms_verified_code);

        $user = Auth::user();
        if ($this->checkValidCode($user, $sms_verified_code)) {
            $user->sv = 1;
            $user->ver_code = null;
            $user->ver_code_send_at = null;
            $user->save();
            return redirect()->route('user.home');
        }
        throw ValidationException::withMessages(['sms_verified_code' => 'Verification code didn\'t match!']);
    }
    public function g2faVerification(Request $request)
    {
        $user = auth()->user();
        $request->validate([
            'code' => 'required',
        ]);
        $code = str_replace(' ','',$request->code);
        $response = verifyG2fa($user,$code);
        if ($response) {
            $notify[] = ['success','Verification successful'];
        }else{
            $notify[] = ['error','Wrong verification code'];
        }
        return back()->withNotify($notify);
    }


    function setupAccount(){

        $banks = Bank::where('status', 1)->get();
        $data['banks'] = $banks;
        $data['all_banks'] = json_encode($data['banks']);

        $data['user'] = auth()->user();
        $data['pageTitle'] = "My Bank Account";

        if(!empty($data['user']->payment_set) && ( !in_array(config('settings')->active_template, ['power','gpt'] ) )){
			$notify[] = ['success', 'Payment account already setup'];
            return redirect()->intended(route('user.home'))->withNotify($notify);
        }

        return view($this->activeTemplate.'user.bank-setup', $data);
    }


    function processAccountSetup(Request $request){
        
        // Validate
        $validator = Validator::make($request->all(),[
            'bank_code' => 'required|string',
            'bank_name' => 'required|string',
            'account_name' => 'required|string',
            'account_number' => 'required|string'
        ]);

        // Failed to validate
        if ($validator->fails()) {
            $errors = $validator->errors()->all();
            $notify[] = ['error', implode(' ', $errors)];
            return $this->handleResponse($request, implode(' ', $errors), 401, $notify);
        }

        $user = Auth::user();
		
		if( $user->payment_set == 1 ){
			$notify[] = ['success', 'Account setup completed before'];
			return redirect()->intended(route('user.home'))->withNotify($notify);
		}

        // Update Bank Details
        if($user->bankAccount){
            // Find Bank
            $bank = $user->bankAccount;
            $bank->bank_name = $request->bank_name;
            $bank->account_name = $request->account_name;
            $bank->account_number = $request->account_number;
            $bank->bank_code = $request->bank_code;
            $bank->save();
        }else{
			// Add new Bank Details
			$bank = new BankAccount();
			$bank->user_id = $user->id;
			$bank->bank_name = $request->bank_name;
			$bank->account_name = $request->account_name;
			$bank->account_number = $request->account_number;
			$bank->bank_code = $request->bank_code;
			$bank->save();
		}

		$AName = str_replace('  ', ' ', $request->account_name);
		$pAName = explode(' ', $AName );

		if ( isset($pAName[1]) && $pAName[1] ) {
			$user->firstname = trim($pAName[0]);
			if( isset($pAName[2]) && $pAName[2] ){
				$user->lastname  = (strlen($pAName[2]) > strlen($pAName[1])) ? trim($pAName[2]):trim($pAName[1]);
			}else{
				$user->lastname  = trim($pAName[1]);
			}
		}else{
			$user->firstname = trim($pAName[0]);
			$user->lastname  = substr($request->account_name, 0, 1);
		}
		
		$user->withdrawal_usdt_address = @$request->wallet_address;
		$user->payment_set = 1;
		$user->save();
		

        $notify[] = ['success', 'Account setup successfully'];
		return redirect()->intended(route('user.home'))->withNotify($notify);

    }


    function setupMomo(){

        $banks = Bank::where('status', 2)->get();
        $data['banks'] = $banks;
        $data['all_banks'] = json_encode($data['banks']);

        $data['user'] = auth()->user();
        $data['pageTitle'] = "Mobile Money Account";

        if(!empty($data['user']->payment_set)){
			$notify[] = ['success', 'Payment account already setup'];
            return redirect()->intended(route('user.home'))->withNotify($notify);
        }

        return view($this->activeTemplate.'user.mobile-money', $data);
    }


    function momoAccountSetup(Request $request){
        
        // Validate
        $validator = Validator::make($request->all(),[
            'bank_code' => 'required|string',
            'bank_name' => 'required|string',
            'account_name' => 'required|string',
            'account_number' => 'required|string'
        ]);

        // Failed to validate
        if ($validator->fails()) {
            $errors = $validator->errors()->all();
            $notify[] = ['error', implode(' ', $errors)];
            return $this->handleResponse($request, implode(' ', $errors), 401, $notify);
        }

        $user = Auth::user();

		// Add new Bank Details
		$bank = new BankAccount();
		$bank->user_id = $user->id;
		$bank->bank_name = $request->bank_name;
		$bank->account_name = $request->account_name;
		$bank->account_number = $request->account_number;
		$bank->bank_code = $request->bank_code;
		$bank->save();

		$AName = str_replace('  ', ' ', $request->account_name);
		$pAName = explode(' ', $AName );

		if ( isset($pAName[1]) && $pAName[1] ) {
			$user->firstname = trim($pAName[0]);
			if( isset($pAName[2]) && $pAName[2] ){
				$user->lastname  = (strlen($pAName[2]) > strlen($pAName[1])) ? trim($pAName[2]):trim($pAName[1]);
			}else{
				$user->lastname  = trim($pAName[1]);
			}
		}else{
			$user->firstname = trim($pAName[0]);
			$user->lastname  = substr($request->account_name, 0, 1);
		}
		
		$user->payment_set = 1;
		$user->save();
		

        $notify[] = ['success', 'Account setup successfully'];
		return redirect()->intended(route('user.home'))->withNotify($notify);

    }

    function updateWithdrawalUsdt(Request $request){
        
        if($request->method() == 'POST') {
            
            // Validate
            $validator = Validator::make($request->all(),[
                'address' => 'required'
            ]);

            // Failed to validate
            if ($validator->fails()) {
                $notify[] = ['error', implode('..', $validator->errors()->all())];
                return $this->handleResponse($request, implode(' ', @$notify), 401, @$notify);
            }

            try {
                
                // User
                $user = User::where('email', auth()->user()->email)->first();

                // Update
                $user->withdrawal_usdt_address = $request->address;
                $user->payment_set = 1;
                $user->save();

				// Add new Bank Details
				$wallet = new Wallet();
				$wallet->user_id = $user->id;
				$wallet->wallet_address = $request->address;
				$wallet->save();

                $notify[] = ['success', 'USDT Wallet address updated successfully'];
				return redirect()->intended(route('user.home'))->withNotify($notify);

            } catch (\PDOException $e) {
                $notify[] = ['error', $e->getMessage()];
                return $this->handleResponse($request, implode(' ', $notify), 400, $notify);
            }
        }

        if(!empty(auth()->user()->payment_set )){
			$notify[] = ['success', 'Your payment account is already set'];
            return redirect()->intended(route('user.home'))->withNotify($notify);
        }
        
        // Return Response
        $pageTitle = "Setup USDT Address";
        return view($this->activeTemplate. 'user.usdt_setup', compact('pageTitle'));

    }

	
    public function paymentInfo( $id = null )
    {
        $payInfo     = Deposit::with('gateway')->where('id', $id)->first();
		$hasError 	 = false; $response = array();
		
		if( $payInfo ){

			$notify = 'Payment details generated. now pay';

			if( !$payInfo->detail ){
				
				$user = auth()->user();

				$flutterAcc = json_decode($payInfo->gatewayCurrency()->gateway_parameter);
				$secret_key = $flutterAcc->secret_key;

				$response       = CurlRequest::curlPostContents('https://api.flutterwave.com/v3/virtual-account-numbers', json_encode([
					'email'     => $user->email,
					'narration' => strtoupper($user->firstname) . ' ' . strtoupper($user->lastname),
					'firstname' => $user->firstname,
					'lastname'  => $user->lastname,
					'amount'    => $payInfo->final_amo,
					'tx_ref'    => $payInfo->trx,
				]), [
					"Authorization: Bearer $secret_key",
					'Content-Type: application/json',
				]);
				
				$response = json_decode($response);
				
				if (!$response) {
					$hasError = true;
				}
				if( @$response->status != 'success'){
					$hasError = true;
				}
				if( $hasError == false ){
					$payInfo->detail = $response->data;
					$payInfo->pay_link = $response->data->flw_ref;
					$payInfo->try = 1;
					$payInfo->update();
				}
			}
			
			if( $hasError == false ){
				return response()->json([
					'status'  => 'success',
					'message' => ['success' => $notify],
					'data'    => [
						'amount' 			=> $payInfo->detail->amount,
						'bankname' 			=> $payInfo->detail->bank_name,
						'recepient' 		=> str_replace('Please make a bank transfer to','', $payInfo->detail->note),
						'account_number' 	=> $payInfo->detail->account_number
					]
				]);
			}else{
				$notify = 'Sorry, unable generate account.';
				return response()->json([
					'status'  => 'error',
					'message' => ['success' => $notify],
				]);
			}
			
		}else{
			$notify = 'Sorry, unable to fetch data';
			return response()->json([
				'status'  => 'error',
				'message' => ['success' => $notify],
			]);
		}
    }
	
	
}
