<?php

class ESnappedAPI extends System {
    
    /**
     * 
     * @var string
     */
    private $authPayload;
    
    /**
     * 
     * @var boolean
     */
    private $authenticated = false;
    
    /**
     * 
     * @var boolean
     */
    private $invoiceCreated = false;
    
    /**
     * 
     * @var array
     */
    private $details = [];
    
    /**
     * 
     * @var array
     */
    private $creds;
    
    public function __construct(){
        parent::__construct();
        $this -> loadCredentials();
        $this -> initComponents();
        $this -> authenticate();
    }
    
    /**
     * 
     * @param array $details
     */
    public function setDepositDetails($details){
        $this -> details = $details;
    }
    
    /**
     * 
     * @return boolean
     */
    public function isInvoiceCreated(){
        return $this -> invoiceCreated;
    }
    
    /**
     *
     * @return boolean
     */
    public function isAuthenticated(){
        return $this -> authenticated;
    }
    
    private function curlEndpoint($arr, $success, $failed = null){
        $handle = curl_init();
         
        $curl_arr = [
            CURLOPT_URL => $arr["url"],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_ENCODING => "utf8",
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST"
        ];
        
        if(isset($arr["headers"])){
            $curl_arr[CURLOPT_HTTPHEADER] = $arr["headers"];
        }
        
        if(isset($arr["data"])){
            $curl_arr[CURLOPT_POSTFIELDS] = $arr["data"];
        }
        
        curl_setopt_array($handle, $curl_arr);
        
        $output = curl_exec($handle);
        
        if($err = curl_error($handle)){
            if($failed != null)
                $failed($err);
        }else{
            $success($output);
        }
        
        curl_close($handle);
    }
    
    private function loadCredentials(){ 
        $this -> creds = $this -> getRowData(parse_ini_file("conf.ini", true), "APN");
    }
    
    private function initComponents(){
        $logDirs = [
            "Logs/APN/", "Logs/APN/Error"
        ];
        
        foreach($logDirs as $dir){
            $path = SITE_ROOT."api/{$dir}";
            
            if(!@file_exists($path))
                mkdir($path);
        }
    }
    
    private function authenticate(){        
        $this -> curlEndpoint([
            "headers" => [
                "Content-type: application/json",
                "accept: application/json",
                "Key: {$this -> creds["Key"]}",
                "Secret: {$this -> creds["Secret"]}"
            ],
            "url" => "{$this -> creds["baseUrl"]}esws/api/connect"
        ], function($output){ 
            $this -> authPayload = json_decode($output);            
            $this -> authenticated = true;
        });
    }
    
    private function invoiceData(){
        $items = [
            [
                "order" => 1,
                "item" => $this -> details["itemName"],
                "quantity" => 1,
                "amount" => sprintf("%.2f", $this -> details["depositAmount"]),
            ]
        ];
        
        $totalAmount = 0;
        
        foreach($items as &$item){
            $item["subTotal"] = sprintf("%.2f", $item["amount"] * $item["quantity"]);
            $totalAmount += $item["subTotal"];
        }
        
        $rate = VAL_STR_CCDEPOSIT_FEE;
        $due = round($totalAmount * ($rate / 100.00), 3);
        
        $totalAmountDue = doubleval($totalAmount + $due);
        
        $invData = [
            "accountFName" => $this -> details["firstName"],
            "accountLName" => $this -> details["lastName"],
            "companyName" => $this -> details["company"],
            "cityMunicipality" => $this -> details["city"],
            "zip" => $this -> details["zip"],
            "stateProvince" => $this -> details["province"],
            "countryCode" => $this -> details["country"],
            "email" => $this -> details["email"],
            "items" => $items,
            "totalAmount" => sprintf("%.2f", $totalAmount),
            "taxRate" => sprintf("%.2f", $rate), // percentage
            "taxDue" => sprintf("%.2f", $due),
            "totalAmountDue" => sprintf("%.2f", $totalAmountDue),
            "dueDate" => date("Y-m-d"),
            "currency" => $this -> details["currency"],
            "notes" => $this -> details["notes"],
            "timezone" => $this -> details["timezone"],
            "merchantReference" => $this -> details["transactionNum"]
        ];
        
        $this -> details["taxDue"] = $invData["taxDue"];
        
        $optionals = [
            "address1",
            "address2",
            "phone",
            "mobile"
        ];
        
        foreach($optionals as $optional){
            if(isset($this -> details[$optional])){
                $invData[$optional] = $this -> details[$optional];
            }
        }
        
        return $invData;
    }
    
    /**
     * 
     * @param string $column
     * @param string $value
     * @return array|unknown[]
     */
    public function getTempDepositDataBy($column, $value){
        $result = $this -> accessSelect("SELECT_TEMP_CCDEPOSIT_BY", 
            [$column, "('){$value}(')"]);
        
        if(count($result) != NO_COUNT)
            return $this -> getRowData($result, NO_COUNT);
        
        return false;
    }
    
    private $invoiceNum = NO_STRING;
    
    /**
     * 
     * @param function $resultCallback
     */
    public function generateInvoice($resultCallback = null){
        if(isset($this -> authPayload -> token)){
            $data = json_encode($this -> invoiceData());
                       
            $this -> curlEndpoint([
                "headers" => [
                    "Content-type: application/json",
                    "accept: application/json",
                    "Authorization: {$this -> authPayload -> token}"
                ],
                "url" => "{$this -> creds["baseUrl"]}esws/api/invoice/new?s=true",
                "data" => $data
            ], function($output) use ($resultCallback){
                $cbobject = json_decode($output);
                                
                if($resultCallback != null)
                    $resultCallback($output);
                                        
                if($cbobject -> code == "OK.06.00.011"){
                    $this -> invoiceCreated = true;
                    $this -> invoiceNum = $cbobject -> reference;
                }
            });
        }
    }
    
    public function saveToTemporaryTable($param){
        $depositData = [
            $this -> details["transactionNum"],
            $param["userAccount"],
            $this -> invoiceNum,
            $this -> currencyToInt($this -> details["depositAmount"], $this -> details["currency"]),
            $this -> details["currency"],
            $this -> currencyToInt($this -> details["taxDue"], $this -> details["currency"]),
            $this -> details["notes"],
            $param["token"],
            date("Y-m-d H:i:s")
        ];
        
        foreach($depositData as &$data){
            $data = "('){$data}(')";
        }
        
        $this -> accessModify('INSERT_TEMP_CCDEPOSIT', $depositData);
    }
}