<?php

namespace App\Http\Controllers\Api\Auth;

use App\User;
use App\UserMobilePhone;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Route;
use Laravel\Passport\Client;

use App\Classes\GenerateToken;
use App\PhoneValidation;
use App\Classes\Record;
use App\Classes\SendSMS;
use App\Classes\SmsManager;

use DB;
use Illuminate\Support\Facades\Hash;

class LoginController extends Controller
{
    protected SmsManager $smsManager;
    private $client;

    public function __construct()
    {
        $this->client = Client::find(2);

	$this->smsManager = new SmsManager();
    }

  private function getMinutesFromExpireDateTime($updated_at){
        $now=strtotime("now");
        $timeSmsSent=strtotime($updated_at);
        $pastMinutes=floor(($now-$timeSmsSent)/60);
        return $pastMinutes;
    }

    public function login(Request $request)
    {
	//if(Auth::guard('api')->check()) return "Autenticado"; else return "Nao autenticado";
        $this->validate($request, [
            'email' => 'required',
            'password' => 'required'
        ], [
            'email.required' => 'O Campo Email é Obrigatório',
            'password.required' => 'O Campo Senha é Obrigatório',
        ]);

        $params = [
            'grant_type' => 'password',
            'client_id' => $this->client->id,
            'client_secret' => $this->client->secret,
            'username' => request('email'),
            'password' => request('password'),
            'scope' => '*'
        ];

        $currentUser = User::query()->where('email', '=',$request->email)->orWhere('username', '=', $request->email)->first();

        // return $currentUser;

        if(!$currentUser) return response()->json(['message'=> 'Nome do utilizador ou senha invalidos'], 400);

        if(!$currentUser->status) return response()->json(['message'=> 'Utilizador bloqueado!'], 400);

        $prefix = substr($currentUser->phone, 0, 2); 
        $sufix = substr($currentUser->phone, 7, 2); 
        
        //? Extrair minutos ....
        $phone = PhoneValidation::query()->where('phone', $currentUser->phone)->first();

	if(!$phone) return response()->json(['message'=> 'Utilizador invalido!'], 400);
        
        $minutes = $this->getMinutesFromExpireDateTime($phone->updated_at);
        
        if($minutes < $phone->duration) return response()->json(['message'=> 'Caro cliente '.$currentUser->name.', ja foi enviado um token de validacao para o seu contacto: '.$prefix.'*****'.$sufix . ', por favor valide a sua conta ou volte a tentar o login em '.((int)$phone->duration-$minutes).' minutos'], 400);

	if($request->token){
            $phone = PhoneValidation::query()->where('phone', $currentUser->phone)->where('codigo', $request->token)->first();
            if(!$phone) return response()->json(['message'=> 'Token de validacao invalido!'], 400);

            User::query()->where('email', $request->email)->orWhere('username', '=', $request->email)->update([
                'is_online' => 0
            ]);
        }

	if($currentUser->is_online && ($currentUser->phone_reference != $request->mobile_reference)){
            
	    $request->request->add(['username' => $currentUser->name, 'phone' => $currentUser->phone]);
            $this->resendCode($request);

            $prefix = substr($currentUser->phone, 0, 2); 
            $sufix = substr($currentUser->phone, 7, 2); 

            return response()->json(['message'=> 'Caro Cliente ' .$currentUser->name. ', estas a tentar efectuar login num dispositivo diferente, para confirmar-mos a tua identidade foi enviado um codigo de autenticacao no teu numero de telefone: '.$prefix.'*****'.$sufix], 400);
        }

        //? Bloqueia o utilizador quando as 3 tentativas de login estiverem esgotadas
        if($currentUser->login_attempts >= 2) {

            User::query()->where('email', $request->email)->orWhere('username', '=', $request->email)->update([
                'status' => 0
            ]);

            $pushMsgBloqued = "Caro cliente ". $currentUser->name . ",  errou a SENHA 3 vezes. A tua conta está bloqueada. Pra recuperar a tua conta entre em contacto com a nossa linha de atendimento atraves dos nossos canais digitais, Facebook, Whatsapp ou pelo tefone 846002000.";

            $pushBodyBloqued = "Caro cliente ". $currentUser->name . ",  a tua conta está bloqueada.";

            if($request->firebase_token)
            $this->sendPush($pushBodyBloqued, $pushMsgBloqued, $request->firebase_token);

	    //if(Auth::guard('api')->check())
            //$this->logout($request);
           // if(Auth::guard('api')->check()){
             //   $proxy = Request::create('logout', 'POST');

              //  return Route::dispatch($proxy);
           // }
            return response()->json(['message'=> 'Utilizador bloqueado!'], 400);
        } 



        //? Soma as tentativas de Login sempre que o utilizador errar a senha..
        if($currentUser && !Hash::check($request->password, $currentUser->password)) 
        {
            User::query()->where('email', $request->email)->orWhere('username', '=', $request->email)->update([
                'login_attempts' => (int)$currentUser->login_attempts+1
            ]);

            $usr = User::query()->where('email', '=',$request->email)->orWhere('username', '=', $request->email)->first();

            $pushMsg = "Caro cliente ". $currentUser->name . ",  tens mais " . (3 - (int)$usr->login_attempts) . " tentativa(s). Se falhares 3 vezes a senha a tua conta será bloqueada.";

            $pushBody = "Caro cliente ". $currentUser->name . ",  a tua conta será bloqueada se digitares o pin incorrecto 3 vezes. Por favor verifique a tua senha e tenta novamente.";

            if($request->firebase_token)
            $this->sendPush($pushBody, $pushMsg, $request->firebase_token);

            return response()->json(['message'=> 'Nome do utilizador ou senha invalidos'], 400);

        }
     

        //? Zerar o login_attempts sempre que o user acertar o login..
        User::query()->where('email', $request->email)->orWhere('username', '=', $request->email)->update([
            'login_attempts' => 0,
            'is_online' => 1
        ]);
        
        //? Actualiza o token e a referencia do Mobile no novo login efectuado pelo utilizador
        User::query()->where('email', $request->email)->orWhere('username', '=', $request->email)->update([
            'firebase_token' => $request->firebase_token,
            'phone_reference' => $request->mobile_reference
        ]);

        //? Quarda as referencias do dispositivo que efectuou o login..
        UserMobilePhone::create([
            'mobile_reference' => $request->mobile_reference,
            'firebase_token' => $request->firebase_token,
            'user_id' => $currentUser->id
        ]);


        $request->request->add($params);

        $proxy = Request::create('oauth/token', 'POST');

        return Route::dispatch($proxy);

    }

    public function refresh(Request $request)
    {
        $this->validate($request, [
            'refresh_token' => 'required'
        ]);

        $params = [
            'grant_type' => 'refresh_token',
            'refresh_token' => request('refresh_token'),
            'client_id' => $this->client->id,
            'client_secret' => $this->client->secret,
            'username' => request('email'),
            'password' => request('password'),
        ];

        $request->request->add($params);

        $proxy = Request::create('oauth/token', 'POST');

        return Route::dispatch($proxy);

    }

    public function logout(Request $request)
    {
	//$accessToken = Auth::guard('api')->user()->token;
	//$accessToken = $request->user()->token();
        $accessToken = Auth::user()->token();

        DB::table('oauth_refresh_tokens')->where('access_token_id', $accessToken->id)
            ->update(['revoked' => true]);

        $accessToken->revoke();

	User::query()->where('email', $request->user()->email)->orWhere('username', '=', $request->user()->email)->update([
            'is_online' => 0
        ]);

        return response()->json([], 204);
    }

    public function resetLink(Request $request)
    {

        $this->validate($request, [
            'email' => 'required|email'
        ]);

        $status = Password::sendResetLink($request->only('email'));

        if ($status === Password::RESET_LINK_SENT) {
            return response()->json(['message' => 'Email Enviado com Sucesso para o endereço ' . $request->email . '. Verifique o seu campo de emails'], 200);
        }

        if ($status == Password::INVALID_USER) {
            return response()->json(['message' => 'Email não verificado, tente novamente '], 400);
        }



    }


	private function sendPush($pushBody, $pushMsg, $pushFirebaseToken){
        
        $notification = array(
            'icon' => 'ic_i_mali_cover',
            'title' => 'PIN incorrecto',
            'body' => $pushBody,
            'click_action' => 'com.imali.payapp.payment_NOTICIA',
	//'click_action' => 'com.imali.payapp.payment_TRANSFER_DETAILS',
            'color' => '#ffffff'
        );

        $data = array(
            'sms' => $pushMsg,
            'terminal' => 'firebase'
        );

        $this->pushNotifification($pushFirebaseToken, $notification, $data);
    }

    public function pushNotifification($token, $notification = array(), $data = array())
    {
        $apiKey = 'AAAA8zVzEPQ:APA91bHl_DXB6UGb_6gZlmFnaLTQoANtX_OBjvl3nOy2bSlnFhxedvk6EhGj7cZoIvmlbKeCnqGxXbuyMH_rEPuhRXvuitXzo6Pfl2TMXLar1PlifXqEhYq6tS55UMrY2Kffzj-P_UH-';
        $fields = array('to' => $token, 'notification' => $notification, 'data' => $data);
        $headers = array('Authorization: key=' . $apiKey, 'Content-Type: application/json');
        $url = 'https://fcm.googleapis.com/fcm/send';

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($curl);
        curl_close($curl);

        return json_decode($result, true);

    }

	public function resendCode(Request $request)
    {
        $token = new GenerateToken();

        $data = ['phone' => $request->phone, 'username' => $request->username, 'codigo' => $token->generatePhoneNumberCode()];
        
        $this->smsManager->smsVerifyUserDevice($data);
        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();

        if ($validate === 0) {
            $save = PhoneValidation::create([
                'phone' => $request->phone,
                'contry_code' => $request->contry_code,
                'expire_at' => now(),
                'duration' => 5,
                'codigo' => $data['codigo'],
                'is_Validated' => 1
            ]);
            if ($save) {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone . '  ' . $data['codigo'],
                    'details' => 'Código de Verificação enviado com sucesso!',
                    'operation' => 'Resend Verification code',
                    'status' => 'Success',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Código de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
           $save = $validate->update(['codigo' => $data['codigo']]);
            if ($save) {
                $data = ['phone' => $request->phone, 'codigo' => $validate->codigo];
                return response()->json(['message' => 'Código de Verificação reenviado com sucesso!', 'codigo' => $data['codigo'], 'phone' => $data['phone']], 200);
            }
        }

    }

}
