<?php 

include_once "../lib/FrameworkTest.php";

class H2PPayoutTesting extends FrameworkTest{
    /**
     * 
     * @var string
     */
    private $returnURI          = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $amount             = NO_COUNT;
    
    /**
     * 
     * @var string
     */
    private $transactionNum     = NO_STRING; // auto-generated
    
    /**
     * 
     * @var string
     */
    private $currencyCode       = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $fromCurrencyCode   = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $memberCode         = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $bankCode           = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $bankAccountName    = NO_STRING;
    
    /**
     *
     * @var string
     */
    private $countryCode        = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $bankAccountNum     = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $merchantCode       = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $payoutURL          = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $ipAddress          = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $securityCode       = NO_STRING;
    
    public function __construct(){
        parent::__construct();
        
        $this -> setParameter();
        $this -> validation();
    }
    
    private function setParameter(){
        date_default_timezone_set('Asia/Manila');
        
        $h2pSettings = $this -> getRowData($this -> accessSelect("SELECT_DEV_SETTING", ["help2pay_conf"]));
        
        if($this -> isLoopData($h2pSettings)){
            $h2pSettings = json_decode($this -> getColumnData($h2pSettings, "dev_setting_value"));
                        
            $this -> merchantCode   = $h2pSettings -> merchant_code;
            $this -> payoutURL      = str_replace("{merchantcode}", $this -> merchantCode, $h2pSettings -> payout_url);
            $this -> ipAddress      = $h2pSettings -> ip_address;
            $this -> securityCode   = $h2pSettings -> security_code;
        }
        
        $this -> returnURI          = $this -> getDataPost("returnURI");
        
        if($this -> returnURI == NO_STRING)
            $this -> returnURI = SITE_PROTOCOL."://".SITE_DOMAIN_FULL."/api/H2PWithdrawalWebhook.php";
        
        $this -> amount             = $this -> getDataPost("amount");
        $this -> currencyCode       = $this -> getDataPost("currency");
        $this -> fromCurrencyCode   = $this -> getDataPost("fromCurrency");
        $this -> memberCode         = $this -> getDataPost("memberCode");
        $this -> countryCode        = $this -> getDataPost("countryCode");
        $this -> bankCode           = $this -> getDataPost("bankCode");
        $this -> bankAccountName    = $this -> getDataPost("bankAccountName");
        $this -> bankAccountNum     = $this -> getDataPost("bankAccountNum");
        
    }
    
    private function validation(){
        $validationRemarks = [];
        
        $memberAccount = $this -> getRowData($this -> getAccountCommon($this -> memberCode));
        
        if($this -> isLoopData($memberAccount)){
            if(!$this -> getColumnData($memberAccount, COLUMN_TEST_ACCOUNT_FLG)){
                $validationRemarks[] = json_encode([
                    "code" => "01",
                    "message" => "Member Code ({$this -> memberCode}) is not under tester category."
                ]);
            }
            
            $fullName = "{$this -> getColumnData($memberAccount, COLUMN_FIRST_NAME)} {$this -> getColumnData($memberAccount, COLUMN_LAST_NAME)}";
            
            if(strcmp($this -> bankAccountName, $fullName) !== 0){
                $validationRemarks[] = json_encode([
                    "code" => "02",
                    "message" => "Member Name ({$this -> bankAccountName}) is not correct."
                ]);
            }
        }else{
            $validationRemarks[] = json_encode([
                "code" => "03",
                "message" => "Member Code ({$this -> memberCode}) doesn't exist."
            ]);
        }
        
        if(!$this -> checkRemoteAddress()){
            $validationRemarks[] = json_encode([
                "code" => "04",
                "message" => "Invalid IP Address: {$this -> getColumnData($_SERVER, "REMOTE_ADDR")}"
            ]);
        }
        
        if($this -> isLoopData($validationRemarks))
            die(print_r($validationRemarks, true));
        
        $this -> transactionNum = $this -> getTransactionNumberCommon(VAR_TRANSACTION_WITHDRAW);
    }
    
    /**
     * 
     * @var array
     */
    private $data       = [];
    
    /**
     * 
     * @var string
     */
    private $rawKey     = NO_STRING;
    
    private function buildData(){
        $dateTime = date("Y-m-d H:i:s");
        
        $this -> data = [
            "ClientIP" => $this -> ipAddress,
            "ReturnURI" => $this -> returnURI,
            "MerchantCode" => $this -> merchantCode,
            "TransactionID" => $this -> transactionNum,
            "CurrencyCode" => $this -> currencyCode,
            "MemberCode" => $this -> memberCode,
            "Amount" => sprintf("%.2f", $this -> amount),
            "TransactionDateTime" => date("Y-m-d h:i:sA", strtotime($dateTime)),
            "BankCode" => $this -> bankCode,
            "toBankAccountName" => $this -> bankAccountName,
            "toBankAccountNumber" => $this -> bankAccountNum
        ];
        
        // key generation
        $this ->rawKey = $this -> getColumnData($this -> data, "MerchantCode")
        .$this -> getColumnData($this -> data, "TransactionID")
        .$this -> getColumnData($this -> data, "MemberCode")
        .$this -> getColumnData($this -> data, "Amount")
        .$this -> getColumnData($this -> data, "CurrencyCode")
        .date("YmdHis", strtotime($dateTime))
        .$this -> getColumnData($this -> data, "toBankAccountNumber")
        .$this -> securityCode;
        
        $transactionKey = md5($this -> rawKey);
        $this -> data["Key"] = $transactionKey;
        
        $exchange = $this->getExchangeCommon($this -> amount
            , $this -> currencyCode
            , $this -> fromCurrencyCode
            , false
            , true
            , NO_STRING
            , $this -> memberCode);
        
        $this -> setRateEx($this -> getColumnData($exchange, PARAM_RATE));
        $this -> setFeeEx(round($exchange[PARAM_AMOUNT] * 0.02, VAL_INT_2));      
    }
    
    private function withdrawalProcessingData(){
        $rtn = [];
        
        $rtn[] = $this -> memberCode;								                                        // account number(1)
        $rtn[] = $this -> currencyCode;														                                        // currency(2)
        $rtn[] = $this -> currencyToInt($this -> amount, $this -> currencyCode);			                                    // Amount of money(3)
        $rtn[] = $this -> currencyCode;														                                        // currency(4)
        $rtn[] = $this -> bankAccountName;													                                        // Account holder(5)
        $rtn[] = $this -> countryCode;												                                        // Recipient country(6)
        $rtn[] = NO_STRING;												                                        // Recipient address 1(7)
        $rtn[] = NO_STRING;												                                        // Recipient address 1(8)
        $rtn[] = 'Local Bank Transfer (Southeast Asia)';								                                        // Recipient message(9)
        $rtn[] = 'Local Bank Transfer (Southeast Asia)';								                                        // Receiving bank name(10)
        $rtn[] = NO_STRING;											                                        // Receiving bank branch name(11)
        $rtn[] = NO_STRING;												                                        // Receiving bank SWIFT(12)
        $rtn[] = $this -> countryCode;												                                        // Receiving bank country(13)
        $rtn[] = NO_STRING;											                                        // Receiving bank address 1(14)
        $rtn[] = NO_STRING;											                                        // Receiving bank address 2(15)
        $rtn[] = $this -> memberCode;												                                        // Receiving bank account number(16)
        $rtn[] = NO_COUNT;										                                        // Relay bank flag(17)
        $rtn[] = NO_STRING;											                                        // Relay bank name(18)
        $rtn[] = NO_STRING;										                                        // Relay bank SWIFT(19)
        $rtn[] = NO_STRING;										                                        // Relay bank country(20)
        $rtn[] = NO_STRING;										                                        // Relay bank address 1(21)
        $rtn[] = NO_STRING;										                                        // Relay bank address 2(22)
        $rtn[] = NO_STRING;										                                        // Relay bank message(23)
        $rtn[] = NO_STRING;															                                        // phone number(24)
        $rtn[] = $this -> currencyCode;												                                        // Debit account currency(25)
        $rtn[] = $this -> currencyToInt($this -> amount, $this -> currencyCode);	                                        // Withdrawal account amount(26)
        $rtn[] = $this -> getRateEx();													                                        // rate(27)
        $rtn[] = $this -> currencyToInt($this -> getFeeEx(), $this -> currencyCode);	                                        // Fee(28)
        $rtn[] = $this -> transactionNum;														                                    // Transaction Number(29)
        $rtn[] = NO_STRING;											                                        // Receiving bank branch code(30)
        $rtn[] = VAL_STR_H2P_METHOD;																	                                        // withdraw solution (31)
                
        return $rtn;
    }
    
    private function storeToTemporaryTable(){
        $this -> accessModify("INSERT_WITHDRAW_H2P_TEMP", $this -> withdrawalProcessingData(), false);
    }
    
    private function insertWithdrawalTransaction(){              
        $this -> accessModify("INSERT_WITHDRAW", $this -> withdrawalProcessingData(), false);
    }
    
    private function processPayout(){
        $param = array();
        $param[] = $this -> transactionNum;
        $param[] = $this -> getColumnData($this -> data, "Key");
        $param[] = "en";
        $param[] = $this -> bankCode;
        
        $this -> accessModify('UPDATE_WITHDRAW_H2P_KEY', $param, false);
        
        $handle = curl_init();
        
        curl_setopt_array($handle, [
            CURLOPT_URL => $this -> payoutURL,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_ENCODING => "utf8",
            CURLOPT_POSTFIELDS => http_build_query($this -> data),
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_HTTPHEADER => [
                "Content-type: application/x-www-form-urlencoded"
            ]
        ]);
        
        $output = curl_exec($handle);
        
        if($err = curl_error($handle))
            $output = $err;
        
        curl_close($handle);
        
        return $output;
    }
    
    public function listen(){
        $this -> buildData();    
        
        echo "Payout URL: {$this -> payoutURL}\n";
        echo "Raw Key: {$this -> rawKey}\n";
        echo "Request Data: ".print_r($this -> data, true);
        
        $this -> storeToTemporaryTable();
        
        $xmlResult = new SimpleXMLElement($this -> processPayout());
        
        if($xmlResult){
            switch($xmlResult -> statusCode){
                case "000":
                    echo "\nSuccessful\n";
                    echo "Result: {$xmlResult -> message}";
                    $this -> insertWithdrawalTransaction();
                    break;
                default:
                    echo "Result: {$xmlResult -> message}";
                    break;
            }
        }
    }
}

$payoutTest = new H2PPayoutTesting();
$payoutTest -> listen();
