<?php
/**
 * Created by PhpStorm.
 * User: freuddebian
 * Date: 04/08/18
 * Time: 22:36
 */


include 'DataBaseConnector.php';
/**
 * Cette classe matérialise la resource qui execute une requete
 */
class Requester
{

//TODO ajouter la comparaison partiel de la ville query with la ville
// Step 3: instantiate a new Twilio Rest Client
    /**
     * @var Messenger Le messenger de TWILIO
     */
    var $messenger;
    /**
     * @var DataBaseConnector Le connecteur de base de données
     */
    var $db;
    /**
     * @var int ID de l'utilisateur
     */
    var $user_id;
    /**
     * @var mixed le message
     */
    var $messageText;
    /**
     * @var array Les langues anglaises
     */
    var $enLangs=["en","en-US","en_US","ca","in","gb","GB","us","en-029","en-AU","en-BZ","en-CA","en-GB","en-IE","en-IN","en-JM","en-MY","en-NZ","en-PH","en-SG","en-TT","en-US","en-ZA","en-ZW","au","bz","ie","in","jm","my","nz","ph","sg","tt","za"];
    /**
     * Requester constructor.
     */
    public function __construct($user_id,$lang="fr")
    {

        $this->db = new DataBaseConnector();
        $this->user_id = $user_id;
        $this->messenger=new Messenger();
        $la=$lang;
        $pos=strpos($la,"-");
        if($pos!=false){
            $la=strtolower(explode("-",$la)[0]);
        }
        if(in_array($la,$this->enLangs))$la='en';
       
        try{
            if(!file_exists("./../static/$la/message.json")){
                $la="en";
            }

        $this->messageText=file_get_contents("./../static/$la/message.json");
        $this->messageText=json_decode($this->messageText,true);
        }catch(\Throwable $e){
            $subject = "Password Recovery";
            $message ="erreur : la=".$la;
            $from = "noreply@ilink-app.com";
            $headers = "From:" . $from;
            $this->messenger->setSubject($subject);
            $this->messenger->setHeader($headers);
            $this->messenger->setMessage($message);
            $this->messenger->setContact($number);
            $this->messenger->setReceiverMail($mail['email']);
            try{
                $this->messenger->sendMail();
            }catch (\Throwable $e){
                $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());;
            }
        }
    }

    /**
     * Retourne la config administrateur sans chargement
     * @return false|string
     */
    public function getPasValue(){
        $pasObject=$this->db->getPasValue();
        if($pasObject)return json_encode(['pas'=>$pasObject]);
        else return json_encode(['error'=>mysqli_error($this->db->con)]);
    }

    /**
     * Retourne la config de la publicité en fonction du pays
     * @param $id_country ID du pays
     * @return false|string
     */
    public function getPubValue($id_country){
        $pasObject=$this->db->getPubValue($id_country);
        if($pasObject)return json_encode(['pub'=>$pasObject]);
        else return json_encode(['error'=>mysqli_error($this->db->con)]);
    }

    /**
     * Supprime un agent
     * @param string $code code agent
     * @return false|string
     */
    public function deleteAgent($code){
        $agent=$this->db->getAgentWithCodeMembre($code);
        if($agent){
            $codeId=$agent['idCode'];
            $res=mysqli_query($this->db->con,"DELETE FROM networks_agents where codeGenerer_id='$codeId'");
            $re=mysqli_query($this->db->con,"DELETE FROM codeGenerer where id='$codeId'");
            return json_encode(['count_network'=>mysqli_num_rows($res),"count_code"=>mysqli_num_rows($re)]);
        }
    }

    /**
     * Connecte un utilisateur avec son numero de telephone et son mot de passe
     * @param string $phone
     * @param string $password
     * @return array|bool|mysqli_result|null L'utilisateur ou un message d'erreur
     */
    public function loginPhonePassword($phone, $password)
    {
        // check for user
        $user = $this->loginUser($phone, $password);
        if (!$user) {
            $user = $this->loginAgent($phone, $password);
            if (!$user) {
                $response["error"] = 1;
                $response["error_msg"] =$this->messageText["PHONE_OR_NUMBER_INCORRECT"] ;
                return $response;
            }
        }
        return $user;
    }

    /**
     * Retourne toutes les infos sur un agent
     * @param string $code code agent
     * @return false|string
     */
    public function getAgentInfoByCode($code){
        $codes=$this->getChildCode($code);
        if(isset($codes["child"])){
            $codes['network']= $this->db->getAgentNetworkByCode($code);
            if($codes['child'] == 'geolocated'){
                $codes['provider_classes'] = $this->db->getProviderClasses($codes['network']['id']);
            }
        }
        return json_encode($codes);
    }

    /**
     * Retourne les reseaux d'un superviseur
     * @param string $codesuperviseur
     * @return array
     */
    public function getSuperviseurNetwork($codesuperviseur)
    {
        $point = $this->db->getSuperviseurNetwork($codesuperviseur, $this->user_id);
        if (isset($point['success'])) {
            $response['success'] = 1;
            $response['datas'] = $point['val'];
            $response['catchild']=$point['catchild'];
            $response['catparent']=$point['catparrain'];
            return $response;
        } else {
            $response = ['error' => 1,
             'error_msg' => $this->messageText['UNABLE_TO_GET_GEOLOCATED_POINT'], 'sql_error' => $point["error"]];
            return $response;
        }
    }

    /**
     * Recupere la liste des coordonnées des points agents d'une ville
     * @param $country
     * @return array
     */
    public function getAllCountryPoint($country)
    {
        $point = $this->db->getAllPointInCountry($country);
        if ($point) {
            $response['success'] = 1;
            $response['datas'] = $point;
            return $response;
        } else {
            $response = ['error' => 1, 'error_msg' => "impossible de recupere les points de cette ville"];
            return $response;
        }
    }

    /**
     * Retrouve le mot de passe oublié d'un agent 
     * @param string $number
     * @return array
     */
    public function recoverPasswordAgent($number)
    {
        $result = $this->db->isPhoneExistedAgent($number);
        if ($result) {
            $randomcode = $this->db->random_string();
            $hash = $this->db->hashSSHA($randomcode);
            $encrypted_password = $hash["encrypted"]; // encrypted password
            $salt = $hash["salt"];
            $user = $this->db->forgotPasswordAgent($result['agent_id'], $encrypted_password, $salt);
            if ($user) {
                $mail = $this->db->getEmailAgent($result['agent_id']);
                if ($mail) {
                    $subject = "Password Recovery";
                    $message = sprintf($this->messageText['TEXT_RECOVERY_PASSWORD'],$randomcode);
                    $from = "noreply@ilink-app.com";
                    $headers = "From:" . $from;
                    $this->messenger->setSubject($subject);
                    $this->messenger->setHeader($headers);
                    $this->messenger->setMessage($message);
                    $this->messenger->setContact($number);
                    $this->messenger->setReceiverMail($mail['email']);
                    try{
                        $this->messenger->sendMail();
                    }catch (\Throwable $e){
                        $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());;
                    }
                    $this->messenger->sendSms();

                    // Stop Sending SMS
                    $response["success"] = 1;

                    $response["message"] =sprintf($this->messageText['MESSAGE_SUCCESS_RECOVERY_PASSWORD'],$mail["email"]);
                    return $response;
                } else {
                    $response["error"] = -6;
                    $response["message"] = "impossible d'envoyer le mail";
                    $response["last_error"] = mysqli_error($this->db->con);
                    return $response;
                }
            } else {
                $response["error"] = -7;
                $response["message"] = "impossible de changer le mots de passe";
                $response["last_error"] = mysqli_error($this->db->con);
                return $response;

            }
        }else
        return ['error' => -5, 'message' => "Ce numéro n'existe pas",'phone'=>$number];
    }

    /**
     * Retrouve le mot de passe oublié d'un utilisateur
     * @param string $number
     * @return array
     */
    public function recoverUserPassword($number)
    {
        if ($this->db->isPhoneExistedSimple($number)) {
            $randomcode = $this->db->random_string();
            $hash = $this->db->hashSSHA($randomcode);
            $encrypted_password = $hash["encrypted"]; // encrypted password
            $salt = $hash["salt"];
            $user = $this->db->forgotPasswordSimple($number, $encrypted_password, $salt);
            if ($user) {
                $mail = $this->db->getEmailSimple($number);
                if ($mail) {
                    $subject = "Password Recovery";
                    $message = sprintf($this->messageText['TEXT_RECOVERY_PASSWORD'],$randomcode);
                    $from = "noreply@ilink-app.com";
                    $headers = "From:" . $from;
                    $this->messenger->setSubject($subject);
                    $this->messenger->setHeader($headers);
                    $this->messenger->setMessage($message);
                    $this->messenger->setContact($number);
                    $this->messenger->setReceiverMail( $mail["email"]);
                    try{
                        $this->messenger->sendMail();
                    }catch (\Throwable $e){
                        $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());;
                    }
                    //$this->messenger->sendSms();

                    // Stop Sending SMS
                    $response["success"] = 1;
                    $response["message"] = sprintf($this->messageText['MESSAGE_SUCCESS_RECOVERY_PASSWORD'],$mail["email"]);
                    return $response;
                } else {
                    $response["error"] = -6;
                    $response["message"] = "impossible d'envoyer le mail";
                    $response["last_error"] = mysqli_error($this->db->con);
                    return $response;
                }
            } else {
                $response["error"] = -7;
                $response["message"] = "impossible de changer le mots de passe";
                $response["last_error"] = mysqli_error($this->db->con);
                return $response;

            }
        }else
        return ['error' => -5, 'message' => 'Ce numéro n\'existe pas',"phone"=>"$number"];

    }

    /**
     * Envoie un mail
     * @param string $email
     * @param string $subject
     * @param string $message
     * @param string $headers
     */
    private function sendMail($email, $subject, $message, $headers)
    {
        mail($email, $subject, $message, $headers);
    }

    /**
     * Envoi un message
     * @param string $message
     * @param string $number
     */
    private function sendMessage($message, $number)
    {
        $sms = $this->client->account->messages->create(
            $number,
            array(
                // Step 6: Change the 'From' number below to be a valid Twilio number
                // that you've purchased
                'from' => sender_number,


                // the sms body
                'body' => $message
            )
        );
    }

    /**
     * Retourne les points agents d'un réseau autour d'un rayon de kilometres
     * @param string $reseau
     * @param $position
     * @param float $distance
     * @param int $page
     * @return false|string
     */
    public function getPointAroundKm($reseau, $position, $distance, $page)
    {
        $list=$this->db->getPointInDistance($reseau,$position,$distance,$page);
        return json_encode($list);
  }

    /**
     * Retourne tous les points agents d'un réseau
     * @param $network
     * @return false|string
     */
    public function getNetworkPoint($network)
    {
        $points = $this->db->getPointsNetwork($network, $this->user_id);
        if (!isset($points['error'])) {
            $pts=['success'=>1,'datas'=>$points];
            return json_encode($pts);
        } else
            return json_encode(['error' => -4, 'error_msg' => 'error query','mysql'=> mysqli_error($this->db->con),"data"=>$points,"network"=>$network,"user"=>$this->user_id]);

    }

    /**
     * Calcule la distance entre 2 points sur la carte
     * @param int $lat1 Latitude du 1er point
     * @param int $lon1 Longitude du 1er point
     * @param int $lat2 Latitude du 2eme point
     * @param int $lon2 Longitude du 2eme point
     * @return float
     */
    function distance($lat1, $lon1, $lat2, $lon2)
    {

        $theta = $lon1 - $lon2;

        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +
            cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = "K";

        if ($unit == "K") {
            return ($miles * 1.609344);
        } else if ($unit == "N") {
            return ($miles * 0.8684);
        } else {
            return $miles;
        }
    }

    /**
     * Inscrire un agent
     * @param $request Requete d'inscription
     * @return false|string
     */
    public function registerGeolocated($request)
    {
        if($this->db->isPhoneExistedAgent($request->phone)) {
            // user is already existed - error response
            $response['agent']= $request->lastname;
            $response["error"] = 1;
            $response["error_msg"] = sprintf($this->messageText['ALREADY_PHONE_NUMBER'],$request->phone);
            return json_encode($response);
        }

        if($this->db->isPhoneExistedAgent($request->phone_transaction)) {
            // user is already existed - error response
            $response['agent']= $request->lastname;
            $response["error"] = 1;
            $response["error_msg"] = sprintf($this->messageText['ALREADY_TRANSACTION_PHONE_NUMBER'],$request->phone_transaction);
            return json_encode($response);
        }

        if (!$this->db->checknumberValidity($request->phone))
            return json_encode([ 'agent' => $request->lastname , 'error' => 'invalid phone number', 'error_msg' => $this->messageText['INVALID_PHONE']]);

        if (!$this->db->checknumberValidity($request->phone_transaction))
            return json_encode([ 'agent' => $request->lastname , 'error' => 'invalid transaction phone number', 'error_msg' => $this->messageText['INVALID_TRANSACTION_PHONE']]);

        $membercodetest = $this->db->isMemberCodeExisted($request->member);
        if ($membercodetest) {
            $user = $this->db->storeUser($request->address, $request->lastname, $request->email, $request->phone,$request->password, $request->network,
                $request->member, $request->latitude, $request->longitude, $request->town,$request->phone_transaction,$request->provider_class_id ?? null);
            if ($user != null && !isset($user['error'])) {
                //if ($user) {
                // user stored successfully
                //Create wallet if network has wallet
                if($this->db->getConfigWallet($request->network->id))
                    $this->db->createWalletForAgent($request->phone_transaction);
                $user["success"] = 1;
                $validation = $user["validation_code"];
                $username = $user["lastname"];
                $subject = "Bienvenue sur Ilink";
                $code=$user["code_membre"];
                $phone = $user['phone'];
                $ct=($user['category']=='geolocated'?$this->messageText['AGENT_GEO']:($user['category']=='super'?$this->messageText['ADMIN']:$this->messageText['SUPER_ADMIN']));
                $message1 =sprintf($this->messageText['MESSAGE_1'],$username,$ct,$phone,$request->password,$code,$validation);
                $message2 = sprintf($this->messageText['MESSAGE_2'],$username,$ct,$phone,$request->password,$code);

                //Envoyez le mail de bienvenue
                try{
                    /* API URL */
                    $url = WALLET_SERVICE_URL.'/notify-new-user';
                    /* Init cURL resource */
                    $ch = curl_init($url);
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
                    /* set the content type json */
                    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                        'Content-Type:application/json',
                        'Authorization:'.WALLET_SERVICE_TOKEN,
                    ));
                    /* set return type json */
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_POST, 1);

                    $body = new \stdClass();
                    $body->subject = $subject;
                    $body->email = $user['email'];
                    $body->message = $user['category'] == 'super' ? $message2 : $message1;
                    $body->category = $user['category'];
                    $body->user_id = $user['agentId'];
                    $body->user_type = 'agent';
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
                    /* execute request */
                    curl_exec($ch);
                    /* close cURL resource */
                    curl_close($ch);
                }catch (Throwable $e){
                    $this->write_log("Error Notify New Agent ".$request->lastname." : ".$e->getMessage()."\n");
                }

                $this->messenger->setContact($user['phone']);
                $sms = $this->messenger->sendSms();


            }
            return json_encode($user);

            /*  echo "Réseau : ".strtoupper($user["network"])."<br />";
              echo "<br />";
              echo "Nom(s) :".$user["lastname"]."<br />";
              echo "Email par défaut du réseau : ".$user["email"]."<br />";
              echo "Telephone :".$user["phone"]."<br />";
              echo "Code membre pour le réseau : ".$user["code_membre"]."<br />";
              echo "<br />";*/
        } else {
            return json_encode([ 'agent' => $request->lastname , 'error' => 'unable to get member', 'error_msg' => $this->messageText['NO_CODE_MEMBER']]);

        }
    }

    /**
     * Retourne tous les réseaux
     * @return false|string
     */
    public function getNetwork()
    {
        return json_encode($this->db->getNetwork());
    }

    /**
     * Connecter un utilisateur
     * @param string $phone
     * @param $password
     * @return array|bool|mysqli_result|null
     */
    public function loginUser($phone, $password)
    {
        $user = $this->db->getUserByPhoneAndPasswordSimple($phone, $password);
        if (!isset($user['error'])) {
            // user found
            // echo json with success = 1
            $user["success"] = 1;
            if(isset($user['active']))
            $user['etat']=$user['active'];

        } else {
            switch ($user['error']){
                case -2:$user['error_msg']=$this->messageText['WRONG_PHONE_NUMBER'];
                $user['sql']=mysqli_error($this->db->con);
                break;
                case -3:
                    $user['error_msg']=$this->messageText['WRONG_PASSWORD'];break;
            }
        }
        return $user;
    }

    /**
     * Connecte un agent (superviseur ou hyperviseur)
     * @param string $phone
     * @param string $password
     * @return array|null
     */
    public function loginAgent($phone, $password)
    {
        $user = $this->db->getUserByPhoneAndPasswordGeolocated($phone, $password);
        if (!isset($user['error'])) {
            // user found
            // echo json with success = 1
            $user["success"] = 1;
            return $user;

        } else

            return $user;

    }

    /**
     * Retourne la liste des demandes d'adhesion d'un superviseur
     * @param string $codeparrain
     * @return array|string
     */
    public function getSupervisorAdhesionList($codeparrain)
    {
        $resparrain=mysqli_query($this->db->con,"SELECT na.id as id FROM networks_agents na INNER JOIN codeGenerer cg ON na.codeGenerer_id=cg.id WHERE cg.code_membre='$codeparrain'");
        if($resparrain){
            $parrain=mysqli_fetch_array($resparrain,MYSQLI_ASSOC)['id'];

            $r=mysqli_query($this->db->con,"select ag.firstname as firstname,ag.lastname as lastname, ag.email as email,na.phone as phone ,ne.name as network,cg.code_membre as code_membre,cg.code_parrain as code_parrain,ds.etat as etat
 from  agents ag INNER JOIN networks_agents na ON ag.id=na.agent_id INNER JOIN codeGenerer cg ON na.codeGenerer_id=cg.id INNER JOIN networks ne ON na.network_id=ne.id INNER JOIN demandeAdhesion ds ON 1=1 WHERE ds.networks_agent_id='$parrain' AND cg.code_membre!='$codeparrain' AND na.etat='0' AND ds.etat='0' AND cg.code_parrain='$codeparrain'");
            $rows=[];
            if($r) {
                while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {

                    $rows[] = $row;
                }
                if (count($rows) > 0) {
                    return $rows;
                } else {
                    echo mysqli_error($this->db->con);
                    return $rows;
                }
            }else{

                return ['error'=>mysqli_error($this->db->con)];
            }
        }else{
            return mysqli_error($this->db->con);

        }
    }

    /**
     * Retourne la categorie des "fils" d'un menbre
     * @param string $codeparrain
     * @return array|null
     */
    public function getChildCode($codeparrain)
    {
        $r=$this->db->getCategoryAgent($codeparrain);
        if(isset($r) and $r['etat']==1){
        switch ($r['category']){
            case 'hyper':
                $r['child']='super';
                break;
            case 'super':
                $r["child"]="geolocated";
                break;
    }
}
        return $r;
    }

    /**
     * Corrige un erreur d'accent sur les champs firstname de la table users_simple
     * @return array|bool|mysqli_result
     */
    public function updateWrongPoint()
    {
        $result=[];
        try{
             $result = mysqli_query($this->db->con, "UPDATE users_simple SET firstname = REPLACE(firstname, 'Ã©', 'é') WHERE firstname LIKE '%Ã©%'");
        }catch (\Throwable $e) {
             var_dump(mysqli_error($this->db->con));
        }
        $da="freud junior";

        return $result;
    }

    /**
     * Envoi une notification à un agent
     * @param $agent_code
     * @param $message
     * @param null $data
     */
    public function sendPushNotificationToAgent($agent_code, $message, $data = null , $date = null)
    {
        $client = new \GuzzleHttp\Client([
            'base_uri' => NOTIFICATION_SERVICE_URL,
        ]);
        $headers = [
            'Authorization' => NOTIFICATION_SERVICE_KEY,
        ];
        $body = new \stdClass();
        $body->agent_code = $agent_code;
        $body->message = $message;
        $body->data = $data;
        $body->date = $date;
        $promise = $client->requestAsync('POST', '/onesignal/pushToAgent', ['json' => $body, 'headers' => $headers])->then();
        $promise->wait();
    }

    /**
     * Enregistre une demande de credit
     * @param string $phone Numero du demandeur
     * @param float $montant
     * @param string $code Code de l'agent
     * @return false|string
     */
    public function storeCreditAsk($phone, $montant, $code)
    {
        $result=$this->db->storeDemandeCredit($phone,$montant,$code);
       if ($result) {
                $usr=$result['agent'];
                $codeParrain=$usr['code_parrain'];
                $parrain=$this->db->getAgentWithCodeMembre($codeParrain);
                $num=$parrain['transactionNumber'];
               $subject = $this->messageText['NEW_DEMAND_TITLE'];
               $email = $usr['email'];
               $message = sprintf($this->messageText['SEND_CREDIT_DEMAND_TEXT_SUCCESS'],$phone,$montant,$num);
               $from = "noreply@ilink-app.com";
               $headers = "From:" . $from;
               $name = "ilink";

               $this->messenger->setHeader($headers);
               $this->messenger->setContact($phone);
               $this->messenger->setMessage($message);
               $this->messenger->setReceiverMail($email);
               $this->messenger->setSubject($subject);
               try{
                   $this->messenger->sendMail();
                   //Send notification
                   $data = new \stdClass();
                   $data->screen = "historyItemDetails";
                   $data->data = new \stdClass();
                   $data->data->id = $result['id'];
                   $data->data->montant = $montant.'';
                   $data->data->date_creation =  date('Y-m-d H:i:s');
                   $data->data->date_modification = date('Y-m-d H:i:s');
                   $data->data->status = '0';
                   $data->data->phone = $phone;
                   $data->data->code_membre = $usr['code_membre'];
                   $data->data->code_parrain = $usr['code_parrain'];
                   $data->data->category = $usr['category'];
                   $data->data->name = $usr['reseau'] ;
                   $data->data->reseau = $usr['reseau'] ;
                   $data->data->firstname = $usr['firstname'] ;
                   $data->data->lastname = $usr['lastname'];
                   $this->sendPushNotificationToAgent($codeParrain,
                       sprintf($this->messageText['NOTIFICATION_CREDIT_DEMAND_TEXT_SUCCESS'],$result['agent_name'],$montant,$result['currency_code']),$data,$result['datetime']);
               }catch (\Throwable $e){
//                   echo json_encode(error_get_last());
                   $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());
               }
               try {
                   $this->messenger->sendSms();
               }catch (\Throwable $e){
                   $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());
               }
           } else {
               // user failed to store
               $response["error"] = 1;
               $response["result"]=$result;
               $response["error_msg"] = $this->messageText['UNABLE_TO_SEND_DEMAND'];
               $response["sql"]=mysqli_error($this->db->con);
               $response["last"]=error_get_last();
               $response["montant"]=$montant;
               $response["phone"]=$phone;
               echo json_encode($response);

           }
            return json_encode($result);

        }


    /**
     * Retourne les reseaux d'un pays en fonction de l'indicatif
     * @param string $indicatif
     * @return array
     */
    public function getCountryNetWork($indicatif)

    {
        $res=mysqli_query($this->db->con,
            "SELECT nt.id AS id, nt.name AS name,nt.country_id AS countryId FROM networks  nt INNER JOIN countries ct
                   ON nt.country_id=ct.id WHERE ct.code_dial='$indicatif' AND nt.name!=''AND nt.status=1");
        if($res){
            $rows=[];
            while($row=mysqli_fetch_array($res,MYSQLI_ASSOC)){
                $rows[]=$row;
            }
            return $rows;
       }else
           return ['error'=>'unable to query list networks','error_sql'=>mysqli_error($this->db->con)];

    }

    /**
     * Retourne les infos d'une ville en focntion du nom
     * @params string $name Nom de la ville
     * @return array
     */
    public function getTownInfoByName($name)
    {

        $res=mysqli_query($this->db->con,"SELECT nt.name as name,nt.id as id ,ct.code_dial as indicatif FROM towns nt INNER JOIN countries ct ON nt.country_id=ct.id WHERE UPPER(nt.name)=UPPER('$name')");
        if($res){
            while($row=mysqli_fetch_array($res,MYSQLI_ASSOC)){
                $rows[]=$row;
            }
            if($rows==null){
                return ['error'=>'unable to query town information','ville'=>$name,'error_sql'=>mysqli_error($this->db->con)];

            }
            return $rows;
        }else
            return ['error'=>'unable to query town information','ville'=>$name,'error_sql'=>mysqli_error($this->db->con)];

    }

    /**
     * Retourne la liste des villes d'un pays en focntion de l'indicatif
     * @param string $indicatif
     * @return array
     */
    public function getListTownsCountry($indicatif)
    {

        $res=mysqli_query($this->db->con,"SELECT nt.name as name,nt.id as id ,ct.code_dial as indicatif FROM towns nt INNER JOIN countries ct ON nt.country_id=ct.id WHERE ct.code_dial='$indicatif'");
        if($res){
            $rows=[];
            while($row=mysqli_fetch_array($res,MYSQLI_ASSOC)){
                $rows[]=$row;
            }
            return $rows;
        }else
            return ['error'=>'unable to query list towns','indicatif'=>$indicatif,'error_sql'=>mysqli_error($this->db->con)];

    }

    /**
     * Valider un compte agent en verifiant son code de validation
     * @param string $phone Numero telephone
     * @param string $code_validation Code
     * @param int $mbre_reseau Nombre d'utilisateurs du reseau , pour un hyperviseur
     * @param boolean $mr_sous_reseau 
     * @return array
     */
    public function validateAgent($phone, $code_validation, $mbre_reseau=null, $mr_sous_reseau=null)
    {
        if(isset($phone) && isset($code_validation)){
             $res=mysqli_query($this->db->con,"SELECT na.id as agentId,ag.id as agId,cg.category as category,cg.code_membre as code_membre,cg.code_parrain AS code_parrain FROM agents ag INNER JOIN networks_agents na on ag.id=na.agent_id inner JOIN codeGenerer cg ON na.codeGenerer_id=cg.id WHERE (na.phone='$phone' OR na.transactionNumber='$phone') AND na.validation_code='$code_validation' ORDER BY agId DESC LIMIT 1");
             if($res){
                 if(mysqli_num_rows($res)>0){
                     $net=mysqli_fetch_array($res,MYSQLI_ASSOC);
                     $agentId=$net['agentId'];
                     $agId=$net['agId'];
                     $codeparrain = $net['code_parrain'];
                     $codeMembre=$net['code_membre'];
                     $re = mysqli_query($this->db->con, "SELECT ag.id as parrainId, ag.number_super as nbre_reseau,ag.number_geoBysuper as nbre_sous_reseau FROM agents ag INNER JOIN networks_agents na ON ag.id=na.agent_id inner JOIN codeGenerer cg ON na.codeGenerer_id=cg.id WHERE cg.code_membre='$codeparrain'");
                     if($re) {
                         $parrain = mysqli_fetch_array($re, MYSQLI_ASSOC);
                         $nbre_sup = $parrain['nbre_sous_reseau'];
                         $nbre = $parrain['nbre_reseau'];
                         $parrainId=$parrain['parrainId'];
                         switch ($net['category']) {
                             case 'hyper':
                                 if (isset($mbre_reseau) && isset($mr_sous_reseau)) {
                                     $r = mysqli_query($this->db->con, "UPDATE `networks_agents` SET etat = '1' WHERE `id` = $agentId ");
                                     $var3["message_erreur_1"] = mysqli_error($this->db->con);
                                     $rs = mysqli_query($this->db->con, "UPDATE agents SET number_super='$mbre_reseau',number_geoBysuper='$mr_sous_reseau' WHERE id='$agId'");
                                     if ($r && $rs) {

                                         $var3["success"] = 1;
                                         $var3["message"] = "User has been validated successfully !";
                                         return $var3;
                                     } else {
                                         $var3["error"] = 1;
                                         $var3["message"] = mysqli_error($this->db->con);
                                         return $var3;
                                     }
                                 } else {

                                     $var3["error"] = -2;
                                     $var3["message"] = "no nbre reseau et sous reseau";
                                     return $var3;

                                 }
                                 break;
                             case 'geolocated':
                                 $r = mysqli_query($this->db->con, "UPDATE networks_agents SET etat = '1' WHERE id = '$agentId' ");
                                 if ($r) {
                                     $nbre -= $nbre > 0 ? 1 : 0;
                                     mysqli_query($this->db->con, "UPDATE agents SET number_geoBysuper = '$nbre' WHERE `id` = '$parrainId' ");
                                     $var3["success"] = 1;
                                     $var3["message"] = "User has been validated successfully !";
                                     return $var3;
                                 } else {
                                     $var3["error"] = 1;
                                     $var3["message"] = mysqli_error($this->db->con);
                                     return $var3;
                                 }
                                 break;
                             case 'super':
                                     $rs = mysqli_query($this->db->con, "UPDATE agents SET number_geoBysuper='$nbre_sup',number_super='$nbre_sup' WHERE id='$agId'");
                                     if ($rs) {
                                         if (mysqli_num_rows($re) > 0) {
                                             $r = mysqli_query($this->db->con, "UPDATE `networks_agents` SET etat = '1' WHERE id ='$agentId'");
                                             if ($r) {
                                                 $nbre -= $nbre > 0 ? 1 : 0;
                                                 if(mysqli_query($this->db->con, "UPDATE `agents` SET number_super = '$nbre' WHERE id='$parrainId'")){
                                                     $var3["success"] = 1;
                                                     $var3['nbre_sup']=$nbre;
                                                     $var3["message"] = "User has been validated successfully !";
                                                     return $var3;

                                                 }else {
                                                     $var3["error"] = 1;
                                                     $var3["message"] = mysqli_error($this->db->con);
                                                     return $var3;
                                                 }

                                             } else {
                                                 $var3["error"] = 1;
                                                 $var3["message"] = mysqli_error($this->db->con);
                                                 return $var3;
                                             }

                                         } else {
                                             $var3["error"] = -4;
                                             $var3["message"] = "impossible de trouve le parrain";
                                             $var3["error_sql"]=mysqli_error($this->db->con);
                                             $var3["re"]=$re;
                                             $var3['parrain']=$net;
                                             return $var3;

                                         }
                                     } else {
                                         $var3["error"] = -3;
                                         $var3["message"] = mysqli_error($this->db->con);
                                         return $var3;
                                     }
                                 break;
                         }
                     }else{
                         return ['error'=>'impossible de recuperer le parrain','error_msg'=>mysqli_error($this->db->con)];

                     }
                 }else{
                     return ['error'=>'invalide code','error_msg'=>"code de validation incorrect"];
                 }
             }else{
                 return ['error'=>'unable to query info network agent','error_msg'=>mysqli_error($this->db->con)];
             }
        }

    }

    /**
     * Valide une demande d'adhesion vers un superviseur
     * @param string $code Code du demandeur
     * @param string $phone Numero de telephone du demande
     * @return false|string
     */
    public function activeSupervisorAdhesion($code, $phone)
    {
        $idsUser=mysqli_query($this->db->con,"SELECT c.code_country , ag.email as email,ag.firstname as firstname,ag.lastname as lastname,na.validation_code as validation_code,na.phone as phone,
na.id as agent_id,ds.id,cg.code_membre as code_membre ,ds.id as demande_id FROM agents ag INNER JOIN networks_agents na ON ag.id=na.agent_id INNER JOIN networks n on n.id = na.network_id INNER JOIN countries c ON c.id = n.country_id INNER JOIN demandeAdhesion ds ON 1=1 INNER JOIN codeGenerer cg ON na.codeGenerer_id=cg.id WHERE ds.phone='$phone'  AND cg.code_membre='$code'");
        if($idsUser){
            $idsusr=mysqli_fetch_array($idsUser,MYSQLI_ASSOC);
            $idAgent=$idsusr['agent_id'];
            $demandeId=$idsusr['demande_id'];
            $code_membre=$idsusr['code_membre'];
            $datetime = $this->db->getCurrentTimeByCountryCode($idsusr['code_country']);
            $udateDemande=mysqli_query($this->db->con,"UPDATE demandeAdhesion SET etat='1' , date_modified = '$datetime' WHERE id='$demandeId'");
            if($udateDemande){
                $user=$idsusr;
                $validation = $user["validation_code"];
                $username = $user["lastname"];
                $subject = $this->messageText['WELCOME_ILINK'];
                $phone = $user['phone'];
                $ct=$this->messageText['ADMIN'];
                $message1 =sprintf($this->messageText['MESSAGE_3'],$ct,$phone,$code_membre,$validation);

                $from = "noreply@ilink-app.com";
                $headers = "From:" . $from;
                $name = "ilink";

                $this->messenger->setReceiverMail($user['email']);
                $this->messenger->setContact($user['phone']);
                $this->messenger->setMessage($message1);
                $this->messenger->setSubject($subject);
                $this->messenger->setHeader($headers);
                try{
                    $this->messenger->sendMail();
                }catch (\Throwable $e){
                    $this->write_log($e->getMessage().'\n'.$e->getTraceAsString());;
                }

                $sms = $this->messenger->sendSms();


            }else{
                echo mysqli_error($this->db->con);
            }
            echo json_encode($idsusr);
        }else{
            echo mysqli_error($this->db->con);
        }


    }

    /**
     * Inscrire un nouvel utilisateur
     * @param $request Requete d'inscription
     * @return false|string
     */
    public function registerUser($request)
    {
        if ($this->db->isPhoneExistedSimple($request->phone)) {
            // user is already existed - error response
            $response["error"] = 1;
            $response["error_msg"] = "numero existe deja";
            return json_encode($response);
        } else {
            if ($this->db->checknumberValidity($request->phone)) {
                $user = $this->db->storeUserSimple($request->address, $request->lastname, $request->email,
                    $request->phone,
                    $request->password, $request->network);
                if ($user != null && !isset($user['error'])) {
                    // Create wallet user
                    $this->db->createWalletIlink($request->phone);

                    $user["success"] = 1;
                    $username = $user["lastname"];
                    $subject = $this->messageText['WELCOME_ILINK'];
                    $phone = $user['phone'];
                    $validation_code=$user['validation_code'];
                    $ct=$this->messageText['USER_'];
                    $message1 =sprintf($this->messageText['MESSAGE_1_USER'],$username,$ct,$phone,$request->password,$code,$validation_code);
//                    $message2 = sprintf($this->messageText['MESSAGE_2'],$username,$ct,$phone,$request->password,"");
                    //Envoyez le mail de bienvenue
                    try{
                        /* API URL */
                        $url = WALLET_SERVICE_URL.'/notify-new-user';
                        /* Init cURL resource */
                        $ch = curl_init($url);
                        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
                        /* set the content type json */
                        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                            'Content-Type:application/json',
                            'Authorization:'.WALLET_SERVICE_TOKEN,
                        ));
                        /* set return type json */
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                        curl_setopt($ch, CURLOPT_POST, 1);

                        $body = new \stdClass();
                        $body->subject = $subject;
                        $body->email = $user['email'];
                        $body->message = $message1;
                        $body->user_id = $user['id'];
                        $body->user_type = 'user';
                        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
                        /* execute request */
                        curl_exec($ch);
                        /* close cURL resource */
                        curl_close($ch);
                    }catch (Throwable $e){
                        $this->write_log("Error Notify New Simple user ".$request->lastname." : ".$e->getMessage()."\n");
                    }

                    $this->messenger->setContact($user['phone']);
                    $sms = $this->messenger->sendSms();

                } else {
                    $user = ['error' => 'impossible de créer l\'utilisateur', 'error_sql' => mysqli_error($this->db->con)];
                }
                return json_encode($user);
            } else {
                return json_encode(['error' => 'unable to get membrre', 'error_msg' =>$this->messageText['INVALID_PHONE']]);

            }

        }
    }

    /**
     * Generer un agent geolocalisé vide pour un agent
     * @param string $phone
     * @param $code_parrain
     * @return false|string
     */
    public function generateEmptyAgentNetworkForAgent($phone, $code_parrain)
    {
        if ($this->db->isPhoneExistedInCategory($phone)) {
            // user is al5eady existed - error response
            $response["error"] = 1;
            $response["error_msg"] =$this->messageText['ALREADY_PHONE_NUMBER'];
            return json_encode($response);
        }else{
                $user=$this->db->generateNetworkAgent($phone,$code_parrain);
                if(isset($user['success'])) {
                    $validation = $user["validation_code"];
                    $subject = $this->messageText['WELCOME_ILINK'];;
                    $phone1 = $user['phone'];
                    $ct=$this->messageText['AGENT_GEO'];
                    $message1 =sprintf($this->messageText['MESSAGE_3'],$ct,$phone,$validation);


                    $this->messenger->setContact($phone1);
                    $this->messenger->setMessage($message1);
                    $this->messenger->setSubject($subject);

                    if ($sms = $this->messenger->sendSms()) {

                        $user['message'] = $sms;
                    } else {
                        return json_encode(['error' => 'imossible d\'envoyer le message']);
                    };
                }
                return json_encode($user);
        }

    }

    /**
     * Assigner un reseau à un agent
     * @param int $agentId
     * @param string $code_parrain
     * @param string $phone
     * @return false|string
     */
    public function assignNetworkToAgent($agentId, $code_parrain, $phone , $provider_class_id = null)
    {
        $agent = $this->db->getAgentById($agentId);
        if (isset($agent)) {
            $indicatif=$agent["indicatif"];
            if ($this->db->isPhoneExistedInCategory(null,null,$indicatif.$phone)) {
            $response["error"] = 1;
            $response["error_msg"] =$this->messageText['ALREADY_PHONE_NUMBER'];
            return json_encode($response);
        } else {
                $parrain=$this->getChildCode($code_parrain);
                if(isset($parrain) and $parrain['child']==='geolocated'){
                $user = $this->db->generateNetworkAgent($phone, $code_parrain,$agent,$provider_class_id);
                if (isset($user['success'])) {
                     $result = $this->db->assignNetworkAgent($agentId, $user['id']);
                            if (isset($result['success'])) {
                                $geoLocated['success'] = 1;
                                $geoLocated['agent_id'] = $agentId;
                                $validation = $user["validation_code"];
                                $subject = $this->messageText['WELCOME_ILINK'];;
                                $phone1 = $user['phone'];
                                $message1 = sprintf($this->messageText['MESSAGE_ATTRIBUTE'],$phone1,$validation);

                                $this->messenger->setContact($phone1);
                                $this->messenger->setMessage($message1);
                                $this->messenger->setSubject($subject);
                                $this->messenger->setReceiverMail($agent['email']);
                                if ($sms = $this->messenger->sendSms()) {

                                    $user['message'] = $sms;
                                } else {
                                    return json_encode(['error' => 'imossible d\'envoyer le message']);
                                };

                                return json_encode($geoLocated);
                            } else {
                                return json_encode($result);
                            }
                        } else {
                            return json_encode($user);
                        }

                
            }else{
                return json_encode(['error'=>'impossible']);
            }
        }
    } else {
            return json_encode(['error' => mysqli_error($this->db->con)]);
        }
}


    /**
     * Retourne la liste de de tous les réseaux géolocalisés d'un agent
     * @return array
     */
    public function listNetworksGeo()
    {
        if($this->user_id){
            $result= $this->db->getListNetworkOfGeoPoint($this->user_id);
            if(!isset($result['error'])){
            $networks=['success'=>1,'networks'=>$result];
            return $networks;

            }else
            return $result;
        }else{
            return ['error'=>'unable to find user_id'];
        }

    }

    /**
     * Retourne la liste de de tous les réseaux libre d'un agent
     * @return array
     */
    public function listFreeNetworksForSuper()
    {
        if($this->user_id){
            $result= $this->db->getListFreeNetworkOfGeoPoint($this->user_id);
            if(!isset($result['error'])){
                $networks=['success'=>1,'networks'=>$result];
                return $networks;

            }else
                return $result;
        }else{
            return ['error'=>'unable to find user_id'];
        }
    }

    /**
     * Retourne les demandes de credits recues
     * @return false|string
     */
    public function getAgentReceiveDemande()
    {
        if($this->user_id){
            $result= $this->db->getListDemandeReceiveAgent($this->user_id);
            if(!isset($result['error'])){
                $networks=['success'=>1,'demands'=>$result];
                return json_encode($networks);

            }else
                return json_encode($result);
        }else{
            return json_encode(['error'=>'unable to find user_id']);
        }

    }

    /**
     * Retourne les demandes de crédits envoyés
     * @return false|string
     */
    public function getAgentSendDemande()
    {
        if($this->user_id){
            $result= $this->db->getListDemandeSendAgent($this->user_id);
            if(!isset($result['error'])){
                $networks=['success'=>1,'demands'=>$result];
                return json_encode($networks);

            }else
                return json_encode($result);
        }else{
            return json_encode(['error'=>'unable to find user_id']);
        } }

    /**
     *
     * @param string $phone
     * @return false|string
     */
    public function treatDemand($phone)
    {
        if($this->user_id){
            $result= $this->db->treatDemand($this->user_id);
            if(isset($result['success'])){
                $this->messenger->setContact($phone);
                $this->messenger->setMessage($this->messageText['MESSAGE_TREAT']);
                $this->messenger->sendSms();
            }
                return json_encode($result);
        }else{
            return json_encode(['error'=>'unable to find user_id']);
        }

    }

    /**
     * Retourne les pays actifs dans la plateforme
     * @return array|false|string
     */
    public function getActiveCountries()
    {
        $mq=mysqli_query($this->db->con,"SELECT DISTINCT ct.id,ct.code_dial,ct.name,ct.code_country FROM countries ct INNER JOIN networks ne ON ne.country_id=ct.id");
        if($mq){
            while($row=mysqli_fetch_array($mq,MYSQLI_ASSOC)){
                $rows[]=$row;
            }
            return json_encode($rows);
        }else{
            return ['error'=>mysqli_error($this->db->con)];
        }
    }

    /**
     * Retourne un agent en fonction de son ID
     * @return array|bool|null
     */
    public function getAgentById()
    {
        return$this->db->getAgentById($this->user_id);
    }

    /**
     * Mettre a jour la position d'un agent
     * @param int $agentId
     * @param float $longitude
     * @param float $latitude
     * @return false|string
     */
    public function updatePosition($agentId, $longitude, $latitude)
    {
        $result=[];
            $q = mysqli_query($this->db->con, "UPDATE agents SET longitude='$longitude',latitude='$latitude' WHERE  id='$agentId'");
            if($q){
                return json_encode(['success'=>1]);
            }else return json_encode(['error'=>0,'sql'=>mysqli_error($this->db->con)]);

        }

    /**
     * Valide un utilisateur
     * @param string $phone
     * @return array
     */
    public function validateUser($phone)
    {

        if(isset($phone)){
            $res=mysqli_query($this->db->con,"SELECT * from users_simple WHERE phone='$phone'");
            if($res){
                if(mysqli_num_rows($res)>0){
                    $user=mysqli_fetch_array($res,MYSQLI_ASSOC);
                    $userId=$user['id'];
                    $r = mysqli_query($this->db->con, "UPDATE users SET active = '1' WHERE id = '$userId' ");
                    if($r) {
                        $var3["success"] = 1;
                        $var3["message"] = "User has been validated successfully !";
                        $res=mysqli_query($this->db->con,"SELECT * from users_simple WHERE phone='$phone'");
                        $user=mysqli_fetch_array($res,MYSQLI_ASSOC);
                        $var3['user']=$user;
                        return $var3;

                    }else{
                        return ['error'=>'impossible de recuperer le parrain','error_msg'=>mysqli_error($this->db->con)];

                    }
                }else{
                    return ['error'=>'invalide code','error_msg'=>"code de validation incorrect"];
                }
            }else{
                return ['error'=>'unable to query info network agent','error_msg'=>mysqli_error($this->db->con)];
            }
        }

    }

    /**
     * Retourne le porte feuille d'un agent
     * @param int $idAgent
     * @return array|null
     */
    function getAgentWallet($idAgent){
        $res=mysqli_query($this->db->con,"SELECT * FROM wallets where id_networkAgent=$idAgent");
        if($res){
            $agent=$row=mysqli_fetch_array($res,MYSQLI_ASSOC);
            return $agent;
        }
        return null;
    }

    /**
     * Creer un requete de retrait dans une carte de crédit
     * @param string $numCarte Numero de la carte
     * @param int $cvv
     * @param float $montant
     * @param $taxe
     * @param int $idAgent
     * @return array
     */
    function createRequestRetrait($numCarte, $cvv, $montant, $taxe, $idAgent){
        $agent=$this->getAgentWallet($idAgent);
        $agentCommission=floatval($taxe*0.8);
        $newBalance=floatval($agent['balance_princ'])+floatval($montant);
        $commission=floatval($agent['balance_com'])+$agentCommission;
        $id=$agent["id"];
    $resCreditPrinc=mysqli_query($this->db->con,"INSERT INTO wallet_transaction(montant,type,statut,result,numCarte,id_wallet) VALUES ($montant,'credit',1,1,$numCarte,$id)");
    if($resCreditPrinc){
        $resCreditCom=mysqli_query($this->db->con,"INSERT INTO wallet_transaction(montant,type,statut,result,numCarte,id_wallet) VALUES ($agentCommission,'credit',1,1,$numCarte,$id)");
        if($resCreditCom){
            $resCredit=mysqli_query($this->db->con,"UPDATE wallets SET balance_princ=$newBalance,balance_com=$commission where id=$id");
        }else{
            echo mysqli_error($this->db->con);
        }
    }else{
        echo mysqli_error($this->db->con);
    }
     return ["result"=>"success","agent"=>$this->getAgentWallet($idAgent)];
}

     function virementComission($idAgent){
         $wallet=$this->getAgentWallet($idAgent);
          $newBalancePrinc = $wallet["balance_princ"] + $wallet["balance_com"];
         $id=$wallet["id"];
         $result =mysqli_query($this->db->con,"UPDATE wallets SET balance_princ= $newBalancePrinc ,balance_com=0 where id=$id");
         if($result){
            return ["result"=>"success","agent"=>$this->getAgentWallet($idAgent)];
         }else{
             return ["result"=>"failed","error"=>mysqli_error($this->db->con)];
         }
     }

     function write_log($message){
        try{
         $log_filename = "../logs";
         if (!file_exists($log_filename))
         {
             // create directory/folder uploads.
             mkdir($log_filename, 0777, true);
         }
         $log_file_data = $log_filename.'/log_' . date("j-n-Y") . '.log';
         //Write action to txt log
         $log  = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
             "Messsage: ".$message.PHP_EOL.
             "-------------------------".PHP_EOL;
         //-
         file_put_contents($log_file_data, $log, FILE_APPEND);
        }catch (\Throwable $e){

        }
     }

}
