<?php
// app/api/xfer/make

    header("Content-Type:application/json");
    include("../dbconn.php");
    include("../utils.php");
    
    // parametros obligatorios
    $parmsob = array("sessionid","originaccountid","usr","amount");
    if (!parametrosValidos($_GET, $parmsob)){
        badEnd("400", array("msg"=>"Parametros obligatorios " . implode(",", $parmsob)));
    }
    
    //Definicion de variables y almacenamiento de valores enviados por GET
    $out= new stdClass();
    $sessionid = $_GET["sessionid"];
    $originaccount = $_GET["originaccountid"];
    $usr = $_GET["usr"];
    $amount = (float)$_GET["amount"];
    
    if($amount <= 0){
        badEnd("403", array("msg"=>determinateMsgFail(array(
            "esp"=>"Monto no puede ser menor o igual a 0",
            "eng"=>"Amount cannot be less than or equal to 0"), $lang, "Monto no puede ser menor o igual a 0")));
    }
    
    //Validamos la session
    $idSessionUser = isSessionValid($db, $sessionid);
    
    // Obtenemos el lenguaje del usuario
    $lang = updateLang($db,$sessionid);
    
    //Validamos el si el usuario puede crear cuentas
    isLevelValid($db, $idSessionUser);
    
    //Validamos que el usuario no se este transfiriendo a si mismo
    $sql = "SELECT usr, id FROM users WHERE id = ".$idSessionUser;
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $userdesdata = $rs->fetch_assoc();
        
    if($userdesdata["usr"] == $usr){
        badEnd("400",array("msg"=>determinateMsgFail(array(
            "esp"=>"No puedes transferir a si mismo",
            "eng"=>"You cannot transfer yourself"), $lang, "No puedes transferir a si mismo")));
    }
    
    //Origen de la transferencia
    $usrorigin = $userdesdata["usr"];
    
    //Consultamos los datos del usuario que realiza la transferencia
    $sql = "SELECT accounts.currencyid AS accurrencyid, ".
    "       accounts.id AS accountid ".
    "       FROM accounts, users ".
    "       WHERE accounts.userid = users.id ".
    "       AND users.sessionid = '".$sessionid."' ".
    "       AND accounts.id = ".$originaccount;
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $accountdata = $rs->fetch_assoc();
    
    $sql = "SELECT SUM(amount) as qty FROM transactions WHERE accountid = ".$accountdata["accountid"];
    if (!$res=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $balance = $res->fetch_assoc();
    
    $sql = "SELECT SUM(amount) AS qty ".
    "       FROM ( ".
    "           SELECT SUM(CASE WHEN orders.side = 1 THEN orders.quantity ELSE orders.total END) AS amount ".
    "           FROM orders ".
    "           WHERE orders.accountid = ".$accountdata["accountid"].
	"           AND orders.canceled IS NULL ".
	"           AND orders.type != 1 ".
    "       UNION ALL ".
    "           SELECT SUM(transactions.amount) AS amount ".
    "           FROM transactions, orders ".
    "           WHERE orders.id = transactions.orderid ".
    "           AND transactions.accountid = ".$accountdata["accountid"].
    "           AND orders.accountid = ".$accountdata["accountid"].
	"           AND orders.canceled IS NULL ".
	"           AND transactions.amount < 0 ".
	"           AND orders.type != 1 ".
    "       ) amount";
    if (!$res=$db->query($sql))
        badEnd("500", array("msg"=>$db->error.$sql));
        
    $balanceorder = $res->fetch_assoc();
    
    if(($balance["qty"] - $balanceorder['qty']) <= 0 || ($balance["qty"] - $balanceorder['qty']) < $amount){
        badEnd("403", array("msg"=>determinateMsgFail(array(
            "esp"=>"Saldo insuficiente",
            "eng"=>"Insufficient balance"), $lang, "Saldo insuficiente")));
    }
    
    //Consultamos el id del usuario
    $sql = "SELECT count(id) AS qty FROM users ".
    "       WHERE UPPER(usr) = UPPER('".$usr."')";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $userdesdata = $rs->fetch_assoc();
        
    if($userdesdata["qty"] == 0){
        badEnd("404",array("msg"=>determinateMsgFail(array(
            "esp"=>"Usuario no encontrado",
            "eng"=>"User not found"), $lang, "Usuario no encontrado")));
    }
    
    //Consultamos los datos del usuario para validar su nivel
    $sql = "SELECT id, usr, level, type FROM users ".
    "       WHERE UPPER(usr) = UPPER('".$usr."')";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $userdesdatalevel = $rs->fetch_assoc();
        
    if($userdesdatalevel["level"] == 0){
        badEnd("404",array("msg"=>determinateMsgFail(array(
            "esp"=>"Usuario no registrado o verificado en AFX",
            "eng"=>"User not registered or verified in AFX"), $lang, "Usuario no registrado o verificado en AFX")));
    }
    
    //Consultamos los datos del usuario de destino
    $sql = "SELECT accounts.id AS accountid ".
    "       FROM accounts, users ".
    "       WHERE accounts.userid = users.id ".
    "       AND users.usr = '".$usr."'".
    "       AND accounts.currencyid = ".$accountdata["accurrencyid"].
    "       AND accounts.paymentmethodid = -1";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $accountdestination = $rs->fetch_assoc();
    
    //Consultamos los datos de la moneda para validar que tipo es y decimales
    $sql = "SELECT * FROM currencies ".
    "       WHERE id = ".$accountdata["accurrencyid"];
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $currencydata = $rs->fetch_assoc();
    
    //Si el usuario posee una cuenta en la moneda de origen puede continuar
    //Si no se le genera una
    if($accountdestination["accountid"] == null){
        
        //Consultamos el id del usuario
        $sql = "SELECT * FROM users ".
        "       WHERE UPPER(usr) = UPPER('".$usr."')";
        if (!$rs=$db->query($sql))
            badEnd("500", array("msg"=>$db->error));
        
        $userdesdata = $rs->fetch_assoc();
        
        //Validamos si es una criptomoneda o fiat
        $isCripto = false;
        $isFiat = false;
    
        if(intval($currencydata['interface']) == 1 || intval($currencydata['interface']) == 3 || intval($currencydata['interface']) == 2){
            $isFiat = true;
        }else if(intval($currencydata['interface']) == 4 || intval($currencydata['interface']) == 5){
            $isCripto = true;
        }
        
        
        $db->autocommit(FALSE);
        
        if($isCripto && !$isFiat){
            
            //Si interface = 5, generamos la wallet con la api de la TCV
            if(intval($currencydata['interface']) == 5){
                $rsp = queryPrivate('deposit_address', $TCV_JWT, $TCV_URL, $VERSION_API, false, ['currency' => $currencydata['symbol']]);
                $out->test = $rsp;
                
                //Si el address es null o la respuesta distinta a 201, error
                if($rsp['address'] == NULL || $rsp['httpres'] != 201){
                    badEnd("402", array("msg"=>determinateMsgFail(array(
                        "esp"=>"Error al obtener direccion: ".$rsp['error']['message'],
                        "eng"=>"Error getting address: ".$rsp['error']['message']), $lang, "Error al obtener direccion: ".$rsp['error']['message'])));
                }
                
                $walletid = $rsp['address'];
            
            }elseif(intval($currencydata['interface']) == 4){
                $parms = array("label"=>"afxaddr");
                $request = array('method'=>'getnewaddress','parms' => $parms);
                $rsp = json_decode(queryServicesBTC($BTC_URL, $request), true);
    
                // Validamos que el error no sea nulo para mandar el mensaje
                if($rsp['error'] != null){
                    badEnd('500',array("msg"=>$rest['error']['message']));
                }
                
                if($rsp['result'] == null){
                    badEnd('402',array("msg"=>determinateMsgFail(array(
                        "esp"=>"Error al obtener direccion: ".$rsp['error']['message'],
                        "eng"=>"Error getting address: ".$rsp['error']['message']), $lang, "Error al obtener direccion: ".$rsp['error']['message'])));
                }
                
                $walletid = $rsp['result'];
            }else{
                
                $walletid = randomString(30);
            }
        
            //Insertamos la nueva cuenta
            $sql = "INSERT INTO accounts".
            "       (".
            "       paymentmethodid, ".
            "       userid, ".
            "       currencyid, ".
            "       details1, ".
            "       status ".
            "       )".
            "       VALUES(".
            "       -1, ".
            "       ".$userdesdata["id"].", ".
            "       ".$accountdata["accurrencyid"].", ".
            "       '".$walletid."', ".
            "       1 ".
            "       )";
            if (!$db->query($sql)){
                $error = $db->error;
                $db->rollback();
                $db->close();
                badEnd("500", array("msg"=>$error." 1 ".$sql));
            }
            
            // Retornamos el id que fue insertado
            $idcreated = (int)$db->insert_id;
        
            //Al ser una cripto, creamos una wallet
            $sql = "INSERT INTO wallets".
            "       (".
            "       wallet, ".
            "       secretKey, ".
            "       accountid, ".
            "       expirationDate".
            "       )".
            "       VALUES(".
            "       '".$walletid."', ".
            "       '".randomString(8)."', ".
            "       ".$idcreated.", ".
            "       DATE_ADD(NOW(), INTERVAL 1 YEAR)".
            "       )";
            if (!$db->query($sql)){
                $error = $db->error;
                $db->rollback();
                $db->close();
                badEnd("500", array("msg"=>$error."2"));
            }
        
        }else if($isFiat && !$isCripto){
            //Insertamos la nueva cuenta
            $sql = "INSERT INTO accounts".
            "       (".
            "       paymentmethodid, ".
            "       userid, ".
            "       currencyid, ".
            "       status".
            "       )".
            "       VALUES(".
            "       -1, ".
            "       ".$userdesdata["id"].", ".
            "       ".$accountdata["accurrencyid"].", ".
            "       1".
            "       )";
            if (!$db->query($sql)){
                $error = $db->error;
                $db->rollback();
                $db->close();
                badEnd("500", array("msg"=>$error."3"));
            }
        }else{
            $db->rollback();
            $db->close();
            badEnd("500", array("msg"=>determinateMsgFail(array(
                "esp"=>"No se logro determinar el tipo de moneda, avise para verificar el arreglo de monedas",
                "eng"=>"It was not possible to determine the type of currency, advise to verify the currency array"), $lang, "No se logro determinar el tipo de moneda, avise para verificar el arreglo de monedas")));
        }
        
        $db->autocommit(TRUE);
        
        //Consultamos nuevamente los datos del usuario de destino
        $sql = "SELECT accounts.id AS accountid ".
        "       FROM accounts, users ".
        "       WHERE accounts.userid = users.id ".
        "       AND users.usr = '".$usr."'".
        "       AND accounts.currencyid = ".$accountdata["accurrencyid"].
        "       AND accounts.paymentmethodid = -1";
        if (!$rs=$db->query($sql))
            badEnd("500", array("msg"=>$db->error));
        
        $accountdestination = $rs->fetch_assoc();
    }
    
    //Consultamos la cuenta que tiene la moneda del retiro de AFX
    $sql = "SELECT * FROM accounts WHERE userid = -1".
    "       AND currencyid = ".$accountdata["accurrencyid"].
    "       AND paymentmethodid = -4";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
    
    //Guardamos la data de la cuenta AFX
    $afxdata = $rs->fetch_assoc();
    
    //Obtenemos el nivel de usuario para determinar su fee
    $sql = "SELECT * FROM users WHERE sessionid = '".$sessionid."'";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
    
    //Guardamos la data de la cuenta
    $userdata = $rs->fetch_assoc();
    
    $level = 1;
    
    if($userdata["level"] == 0){
        $level = 1;
    }else{
        $level = $userdata["level"];
    }
    
    //Obtenemos el fee de cada operacion por la moneda de la cuenta
    $sql = "SELECT * FROM cmspreffees WHERE currencyid = ".$accountdata["accurrencyid"].
    "       AND levelid = ".$level.
    "       AND usertype = ".$userdata["type"];
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
    
    //Guardamos la data de la cuenta
    $fee = $rs->fetch_assoc();
    
    //Validamos que el monto sea mas que el minimo aceptado
    if(validateMin($accountdata["accurrencyid"], $userdata["type"], 2, $db, $amount)){
        badEnd("403", array("msg"=>determinateMsgFail(array(
            "esp"=>"Monto m&iacute;nimo autorizado: ".numberFormatt($fee['minxfer'], $currencydata['decimals']),
            "eng"=>"Minimum authorized amount: ".numberFormatt($fee['minxfer'], $currencydata['decimals'])), $lang, "Monto m&iacute;nimo autorizado: ".numberFormatt($fee['minxfer'], $currencydata['decimals']))));
    }
    
    //Calculamos el monto real quitandole la comision
    if($fee["pctfeexfer"] != null || $fee["nmlfeesxfer"] != null ){
        if($fee["pctfeexfer"] == null){
            $realfee = number_format($amount - ($amount - $fee["nmlfeesxfer"]), $currencydata['decimals'], '.', '');
            $realamount = number_format($amount - $realfee, $currencydata['decimals'], '.', '');
        }else{
            $realfee = number_format(($fee["pctfeexfer"]*$amount)/100, $currencydata['decimals'], '.', '');
            $realamount = number_format($amount - $realfee, $currencydata['decimals'], '.', '');
        }
    }else{
        $realfee = 0;
        $realamount = number_format($amount - $realfee, $currencydata['decimals'], '.', '');
    }
    
    if($realamount <= 0){
        badEnd("403", array("msg"=>determinateMsgFail(array(
            "esp"=>"Total neto no puede ser menor o igual a 0",
            "eng"=>"Total cannot be less than or equal to 0"), $lang, "Total neto no puede ser menor o igual a 0")));
    }
    
    //Obtenemos los datos de la moneda para saber si es cripto o FIAT
    $sql = "SELECT * FROM currencies WHERE id = ".$accountdata["accurrencyid"];
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
    
    //Guardamos la data de la cuenta AFX
    $row = $rs->fetch_assoc();
    
    //Obtenemos los datos del usuario de destino
    $sql = "SELECT users.id AS userid, ".
    "       users.usr AS userusr, ".
    "       users.type AS usertype, ".
    "       userpersons.fname AS userpersonfname, ".
    "       userpersons.flastname AS userpersonflastname, ".
    "       usercompanies.name AS usercompanyname ".
    "       FROM users".
    "       LEFT JOIN userpersons ON userpersons.usrid = users.id ".
    "       LEFT JOIN usercompanies ON usercompanies.usrid = users.id".
    "       WHERE users.usr = '".$usr."'";
    if (!$rs=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $userdestinationdata = $rs->fetch_assoc();
    
    $validator = getValidator(8);
    
    $db->autocommit(FALSE);
        
    //insertamos la transferencia desde el origen
    $sql = "INSERT INTO transactions".
    "       (".
    "       datecreated, ".
    "       dsc, ".
    "       accountid, ".
    "       accountorigin, ".
    "       amount, ".
    "       amountghost, ".
    "       accountdestination, ".
    "       validator, ".
    "       validthru ".
    "       )".
    "       VALUES(".
    "       NOW(), ".
    "       'Transferencia a ".strtolower($usr)."', ".
    "       ".$accountdata["accountid"].", ".
    "       ".$accountdata["accountid"].", ".
    "       0, ".
    "       -".$realamount.", ".
    "       ".$accountdestination["accountid"].", ".
    "       '".$validator."', ".
    "       DATE_ADD(NOW(), INTERVAL 10 MINUTE)".
    "       )";
    if (!$db->query($sql)){
        $error = $db->error;
        $db->rollback();
        $db->close();
        badEnd("500", array("msg"=>$error."111"));
    }
    
    //Guardamos el id de la transaccion de deposito
    $txid = (int)$db->insert_id;
    $out->transactionid = $txid;
    
    //Le colocamos a la primera transferencia el txid
    $sql = "UPDATE transactions SET".
    "       txid= ".$txid.
    "       WHERE id = ".$txid;
    if (!$db->query($sql)){
        $error = $db->error;
        $db->rollback();
        $db->close();
        badEnd("500", array("msg"=>$error));
    }
    
    //insertamos el fee de la transferencia para el origen
    $sql = "INSERT INTO transactions".
    "       (".
    "       datecreated, ".
    "       dsc, ".
    "       accountid, ".
    "       txid, ".
    "       accountorigin, ".
    "       amountghost, ".
    "       amount, ".
    "       accountdestination, ".
    "       validator, ".
    "       validthru ".
    "       )".
    "       VALUES(".
    "       NOW(), ".
    "       'Comisión de Transferencia', ".
    "       ".$accountdata["accountid"].", ".
    "       ".$txid.", ".
    "       ".$accountdata["accountid"].", ".
    "       -".$realfee.", ".
    "       0, ".
    "       ".$afxdata["id"].", ".
    "       '".$validator."', ".
    "       DATE_ADD(NOW(), INTERVAL 10 MINUTE)".
    "       )";
    if (!$db->query($sql)){
        $error = $db->error;
        $db->rollback();
        $db->close();
        badEnd("500", array("msg"=>$error."222"));
    }
    
    //insertamos el fee de la transferencia
    $sql = "INSERT INTO transactions".
    "       (".
    "       datecreated, ".
    "       dsc, ".
    "       accountid, ".
    "       txid, ".
    "       accountorigin, ".
    "       amount, ".
    "       amountghost, ".
    "       accountdestination, ".
    "       validator, ".
    "       validthru ".
    "       )".
    "       VALUES(".
    "       NOW(), ".
    "       'Comisión de Transferencia', ".
    "       ".$afxdata["id"].", ".
    "       ".$txid.", ".
    "       ".$accountdata["accountid"].", ".
    "       0, ".
    "       ".$realfee.", ".
    "       ".$afxdata["id"].", ".
    "       '".$validator."', ".
    "       DATE_ADD(NOW(), INTERVAL 10 MINUTE)".
    "       )";
    if (!$db->query($sql)){
        $error = $db->error;
        $db->rollback();
        $db->close();
        badEnd("500", array("msg"=>$error."333"));
    }
    
    //insertamos la transferencia hacia el destino
    $sql = "INSERT INTO transactions".
    "       (".
    "       datecreated, ".
    "       dsc, ".
    "       accountid, ".
    "       txid, ".
    "       accountorigin, ".
    "       amount, ".
    "       amountghost, ".
    "       accountdestination, ".
    "       validator, ".
    "       validthru ".
    "       )".
    "       VALUES(".
    "       NOW(), ".
    "       'Transferencia de ".$usrorigin."', ".
    "       ".$accountdestination["accountid"].", ".
    "       ".$txid.", ".
    "       ".$accountdata["accountid"].", ".
    "       0, ".
    "       ".$realamount.", ".
    "       ".$accountdestination["accountid"].", ".
    "       '".$validator."', ".
    "       DATE_ADD(NOW(), INTERVAL 10 MINUTE)".
    "       )";
    if (!$db->query($sql)){
        $error = $db->error;
        $db->rollback();
        $db->close();
        badEnd("500", array("msg"=>$error."444".$sql));
    }
    
    //Datos del destinatario
    $out->destinationuser = new stdClass();
    $out->destinationuser->id = (int)$userdestinationdata["userid"];
    
    if($userdestinationdata["usertype"] == 1){
        $out->destinationuser->name = $userdestinationdata["userpersonfname"].($userdestinationdata["userpersonflastname"] == "" ? "" : " ".$userdestinationdata["userpersonflastname"]);
    }else{
        $out->destinationuser->name = $userdestinationdata["usercompanyname"];
    }
    
    // Obtenemos el nombre del usuario
    $sql = "SELECT IF(userpersons.fname IS NULL, usercompanies.name, CONCAT(userpersons.fname,' ',userpersons.flastname)) AS name ".
    "       FROM users ".
    "       LEFT JOIN userpersons ON userpersons.usrid = users.id ".
    "       LEFT JOIN usercompanies ON usercompanies.usrid = users.id ".
    "       WHERE sessionid = '".$sessionid."'";
    if (!$res=$db->query($sql))
        badEnd("500", array("msg"=>$db->error));
        
    $userdataaudit = $res->fetch_assoc();
    
    $ipaddress = getRealIP();
    //auditoria
    setAudit($db, "OPERACIONES", $sessionid, "APP", "Se registró una transferencia por ".$amount." (".$out->transactionid.") en ".$currencydata['name'].", del usuario ".$userdataaudit['name']." al usuario ".$out->destinationuser->name, $ipaddress);
    
    $db->commit();
    $db->close();
    
    $email = $userdata["usr"];
    $subject = "Código  de Transferencia AFX";
    $subject = '=?UTF-8?B?'.base64_encode($subject).'?=';
    
    $body = "<html>".
            "   <head>".
            "       <title></title>".
            "       <link href='https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap' rel='stylesheet'>".
            "       <link href='https://fonts.googleapis.com/css2?family=Roboto&display=swap' rel='stylesheet'>".
            "       <style>".
            "           .goodText {".
            "               font-family: 'Open Sans', sans-serif;".
            "           }".
            "           .code {".
            "               font-family: Helvetica, sans-serif".
            "           }".
            "           .copy {".
            "               font-family: 'Roboto', sans-serif;".
            "               font-weight: 400;".
            "               font-size: 12px;".
            "           }".
            "       </style>".
            "   </head>".
            "   <body>".
            "       <div style='background-color: #F8F8FA;padding: 20px;'>".
            "           <img style='margin: auto; display: block;margin-bottom:10px;' width='110' height='110' src='".$homeurl."/img/afx-logo-email.png'/>".
            "           <div style='margin: auto; display: block;background-color: #FFF;border-radius: 22px;width: 60%;padding:30px;'>".
            "               <img style='margin: auto; display: block;margin-bottom:20px;' width='160' height='130' src='".$homeurl."/img/img_retiro.png'/>".
            "               <h1 class='goodText' style='color:#474C58;text-align:center;font-size: 20px;font-weight: bold;'>Hola ".strtolower($email)."</h1>".
            "               <p class='goodText' style='font-size: 18px;color: #474C58;text-align:center;margin-bottom:30px;margin-left:20px;margin-right:20px;'>Para completar la transferencia de fondos ingrese el c&oacute;digo a continuaci&oacute;n:</p>".
            "               <div style='margin: auto; display: block;background-color: #4287CE;border-radius: 8px;width: 200px; height: 57px;text-align:center;'>".
            "                   <p style='margin: auto; display: block;color: #FFF;font-size: 18px;text-align:center;line-height: 58px;font-weight:bold;letter-spacing: 10px;'>".$validator."</p>".
            "               </div>".
            "               <p class='goodText' style='text-align:center;font-size:12px;color: #474C58;'>Este c&oacute;digo expirar&aacute; en 10 minutos.</p>".
            "           </div>".
            "           <p class='copy' style='margin-top:40px; color: #767E93;text-align:center;'>&copy; 2020 - AFX Trade</p>".
            "       </div>".
            "   </body>".
            "</html>";
    
    /*$body = "Hola ".strtolower($email).", para completar la transferencia de fondos ingrese el c&oacute;digo a continuaci&oacute;n:<br><br>".
            "<b>".$validator."</b><br><br>".
            "<b>Este c&oacute;digo expirar&aacute; en 10 minutos.</b><br><br>".
            "<br>Gracias de antemano<br>AFX<br>";*/
            
    enviarCorreo($fromeMail, strtolower($email), $subject, $body);
    
    header("HTTP/1.1 200");
    echo (json_encode($out));
    die();
?>
