<?php

namespace App\Http\Controllers\API\v1\Voter;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Util;
use App\UserOTP;
use App\Voter;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Auth;
use GuzzleHttp\Client;

class LoginController extends Controller
{
    public function __invoke(Request $request)
    {
    	//return response()->json(Auth::guard('user'));

		/* Request OTP */
		try{
			$currentDateTime = Carbon::now();

			$expired_at = Carbon::now()->addMinutes(config('onewaysms.minutes'));
			$created_at = $currentDateTime->toDateTimeString();

			$voter = Voter::where('no_kp',$request->no_kp)->firstOrFail();

			if($voter){
				$expiration = $this->checkExpirationTAC($request->no_kp);

				if($expiration['notexpired'] == true){
					throw new \Exception('Expired TAC : ' . $expiration['remaining']);
				} 
				
				$sms_token = $this->getTokenSMS($voter->telefon,$currentDateTime);

				if($sms_token == 'error'){
					throw new \Exception('error in getting the data from SMSToken');
				}

				$user_otp = new UserOTP();
				$user_otp->nokp = $voter->no_kp;
				$user_otp->telefon = $voter->telefon;
				$user_otp->token = $sms_token;
				$user_otp->created_at = $created_at;
				$user_otp->expired_at = $expired_at;
				$user_otp->save();

				return response()->json([
					'status' => 'success',
					'message' => 'generated SMS Token',
					'notel' => $voter->telefon,
					'nokp' => $voter->no_kp,

				]);

			}else{
				return response()->json([
					'status'  =>  'failed',
					'message'  =>  'Does not found NO KP.'
				]);
			}
		}catch(Exception $e){
			return response()->json([
				'status'  =>  'failed',
				'message'  =>  'Error: ' . $e->getMessage()
			]);
		}
    }

	public function checkExpirationTAC($nokp) : Array{
        $currentDateTime = Carbon::now();

		$expiretac = UserOTP::where('nokp',$nokp)
			->whereDate('created_at','=',$currentDateTime)
			->whereDate('expired_at','=',$currentDateTime)
			->whereTime('expired_at','>=',$currentDateTime->toTimeString())
			->whereTime('created_at','<=',$currentDateTime->toTimeString())
			->latest()
			->first();

		if($expiretac){
			$remaining = $this->getRemainingTime($expiretac->expired_at);
			return ['notexpired' => true,'remaining' => $remaining];
		}else{
			return ['notexpired' => false];
		}
	}

	public function verifyTAC(Request $request){

		$authenticateOTP = $this->getTACModel($request->no_kp,$request->token);

		if(!$authenticateOTP['condition']){
			return response()->json([
				'status'  =>  'failed',
				'message'  =>  $authenticateOTP['message']
			]);
		}

		if (Auth::guard('voter')->attempt(['no_kp' => $request->no_kp, 'password' => 'admin', 'election_id' => Util::getCurrentElection()])) {
    		return response()->json([
    			'status'  =>  'success',
    			'message'  =>  'Login successfully.',
    			'user'  => Auth::guard('voter')->user(),
                'election_status' => Util::getElectionStatus(),
    			'token' => Auth::guard('voter')->user()->createToken('My Token', ['vote'])->accessToken
    		]);
    	} else {
    		return response()->json([
    			'status'  =>  'failed',
    			'message'  =>  'Invalid ID.'
    		]);
    	}

		return response()->json([
			'status'  =>  'success',
			'message'  =>  'Login successfully.',
		]);
	}

	private function getTACModel($no_kp,$token){
        $currentDateTime = Carbon::now();

		$result = UserOTP::where('nokp',$no_kp)
				->whereDate('created_at','=',$currentDateTime)
				->whereDate('expired_at','=',$currentDateTime)
				->whereTime('expired_at','>=',$currentDateTime->toTimeString())
				->whereTime('created_at','<=',$currentDateTime->toTimeString())
				->latest()
				->first();

		if(!$result){
			return ['condition' => false, 'message' => 'Token Expired'];
		}

		if($result['token'] == $token){
			return ['condition' => true];
		}else{
			return ['condition' => false, 'message' => 'Invalid Token'];
		}
	}

	private function getTokenSMS($tele,$date){
		$tac_token = $this->randum_number(6,2,false);
		if(env("APP_ENV") == 'production'){
			$mobileno = '6' . $tele;
			$messages = sprintf(config('onewaysms.message'),$tac_token,$date);

			$parameter = [
				'apiusername' => env("ONEWAY_SMS_USERNAME"),
				'apipassword' => env("ONEWAY_SMS_PASSWORD"),
				'senderid' => env("ONEWAY_SMS_SENDERID",'INFO'),
				'mobileno' => $mobileno,
				'message'=> $messages,
				'languagetype'=> env("ONEWAY_SMS_LANG",1)
			];

			$client = new Client(['verify' => false]);
			$status = $client->get('http://gateway.onewaysms.com.my:10001/api.aspx',[
				'query' => $parameter
			]);

			if($status){
				return $tac_token;
			}else{
				return 'error';
			}

		}else{
			return $tac_token;
		}
	}

	private function randum_number($len = 6,$dup = 1, $sort = false){
        if($dup < 1)
            throw new \InvalidArgumentException('Second argument is < 1');
        
            $num = range(0,9);
            shuffle($num);

            $num = array_slice($num, 0, ($len-$dup) + 1);

            if($dup > 0){
                $k = array_rand($num, 1);
                for($i=0;$i<($dup-1);$i++)
                {
                    $num[] = $num[$k];
                }
            }

            if($sort){
                sort($num);
            }

            return implode('',$num);
    }

	private function getRemainingTime($expired_at){
        $currentDateTime = Carbon::now();
		$expiredAt = Carbon::parse($expired_at);

		$remainingSeconds = $currentDateTime->diffInSeconds($expiredAt);

		$remainingFormatted = gmdate('H:i:s', $remainingSeconds);

		return $remainingFormatted;
	}
}
