<?php

namespace App\Services;


use App\Constant\OTPAction;
use App\Models\api\v1\ApiKey;
use App\Models\User;
use App\Constant\OTPStatus;
use App\Models\api\v1\MfaCode;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Mediumart\Orange\SMS\Http\SMSClient;
use Mediumart\Orange\SMS\SMS;
use Symfony\Component\HttpFoundation\Request;

class OtpService
{


    public static function checkIfUsernameIsRegistred($username, $action): bool
    {
        if (!User::whereUsername(trim($username))->first() AND strtoupper(trim($action)) != OTPAction::REGISTRATION)
            return false;

        return true;
    }


    public static function checkIfUsernameHasOtpPendingCOde($username, $code): bool
    {
        return MfaCode::where([['code' => $code],['username' => $username],['status'=> OTPStatus::PENDING]])->first() ?? false;
    }


    public function sendSMS(string $message, string $phone_number, string $credential_1, string $credential_2, string $from_1, string $from_2): bool
    {
        $client         = SMSClient::getInstance($credential_1, $credential_2);
        $sms            = new SMS($client);

        $result         = $sms->message($message)
                                ->from($from_1, $from_2)
                                ->to($phone_number)
                                ->send();

        //@TODO return true for now but we need to check and confirm the message was sent

        return true;
    }

    public static function checkSendTimeOTP(string $username, string $action, $max_interval): bool
    {
        $last_opt = MfaCode::where([
            ['status',      OTPStatus::PENDING],
            ['recepient',   $username],
            ['action',      strtoupper(trim($action))]
        ])->first();

        if($last_opt && $last_opt->created_at->addSeconds($max_interval) > Carbon::parse(now()))
        {
            return true;
        }

        return false;
    }


    public static function getLastApprovedOrDenied(ApiKey $api_key, string $username, string $action): ?MfaCode
    {
        return MfaCode::orderBy('created_at','desc')
            ->where([
                ['api_key_id',          $api_key->id],
                ['status',              OTPStatus::APPROVED],
                ['recepient',           $username],
                ['action',              $action]
            ])
            ->orWhere([
                ['api_key_id',          $api_key->id],
                ['status',              OTPStatus::DENIED],
                ['recepient',           $username],
                ['action',              $action]
            ])
            ->first();
    }

    public static function getInvalidAttemptsCount(ApiKey $api_key, MfaCode $last_otp, string $username, string $action): int
    {
        $lastApprovedOrDeniedOTP    = OtpService::getLastApprovedOrDenied($api_key, $username, $action);
        $invalid_count              = 0;

        if($lastApprovedOrDeniedOTP)
        {
            $nextOTPCodes =  MfaCode::where([
                ['api_key_id',          $api_key->id],
                ['created_at',  '>',    $lastApprovedOrDeniedOTP->created_at],
                ['recepient',           $username],
                ['action',              $action],
                ['id',          '!=',   $last_otp->id]
            ])->get();
            $invalid_count = $nextOTPCodes->sum('InvalidAttempts');
        }

        $invalid_count += $last_otp->InvalidAttempts;
        return $invalid_count;
    }

}
