<?php 

abstract class AbstractTransfer {

    protected $beneficiary; # Beneficiary information

    /**
     * Bundle: A transaction data tracker
     * The bundle variable saves and transport information between multiple $_POST submission
     */
    private $bundle;

    # The Root constructor
    
    public function __construct() {

        $this->dir = realpath( __DIR__ . "/../" );

        $this->user = Uss::$global['user'];

        $this->usermeta = Uss::$global['usermeta'];

        $this->post = $_POST;
        
        array_walk_recursive($this->post, function(&$value) {
            $value = trim(htmlspecialchars($value));
        });

        # Add JS & CSS Components

        $this->addAssets();

        $this->restoreTransaction();

        $this->consoleBeneficiaries();

        # Add Custom Section
        
        $this->bundle = empty($_POST['bundle']) ? [] : $this->decodeTransaction( $_POST['bundle'] );

    }


    # Allow external class to get data but not update

    public function __get( $key ) {

        # Return data or Null
        return $this->{$key} ?? null;

    }


    # Apply algorithm to encode transaction

    public function encodeTransaction( array $content ) {

        # Convert 2 JSON
        $encoding = json_encode( $content );
        # Convert 2 Base64
        $encoding = base64_encode($encoding);
        # Rotate The Value;
        $encoding = str_rot13( $encoding );

        return $encoding;
    }


    # Apply algorithm to decode transaction 

    public function decodeTransaction( string $content ) {

        # Rotate The Value;
        $decoding = str_rot13( $content );
        # Revert From Base64
        $decoding = base64_decode( $decoding );
        # Revert to Array
        $decoding = json_decode( $decoding, true );

        return $decoding;

    }


    # Add a new Bundle data and save the encoded Tag
    # This will help you carry the bundle information into further sections of submitted post

    public function trackBundle( string $key, $value ) {

        # Add Bundle to List;
        $this->bundle[$key] = $value;

    }

    # Restore Transaction 

    protected function restoreTransaction() {

        if( !isset($this->post['transaction']) ) return;

        $this->post = $this->decodeTransaction( $this->post['transaction'] );

        unset( $this->post['transaction'] );

    }

    
    # Get all necessary values that will be used across the transaction

    protected function prepareTransaction() {

        $this->transfer['amount'] = (float)$this->post['amount'];
        $this->transfer['charge'] = (float)Uss::$global['options']->get('bank:transfer.charge');
        $this->transfer['fee'] =  $this->transfer['amount'] *  $this->transfer['charge'] * 0.01;
        $this->transfer['total'] = $this->transfer['amount'] + $this->transfer['fee'];
        
        # Update Post

        $reference = uniqid() . strtolower(Core::keygen(15)); // New reference ID

        $this->post['tx_ref'] = ( $this->post['tx_ref'] ?? $reference );
        $this->post['tx_region'] = isset($this->post['bank_country']) ? "international" : "local";
        $this->post['tx_charge'] = Uss::$global['options']->get('bank:transfer.charge');

    }


    # Find and store beneficiary information

    protected function getBeneficiary() {
        
        # Ignore if beneficiary does not need to be saved
        if( !isset($this->post['save_receiver']) && empty($this->bundle['save_receiver']) ) return;

        # Unset the data; It is not part of our form
        $this->trackBundle('save_receiver', true);

        unset($this->post['save_receiver']);

        # Get the beneficiary information which will later be saved on successful transaction
        $this->beneficiary = array(
            "userid" => $this->user['id'],
            "bank_account" => $this->post['bank_account'],
            "bank_region" => $this->post['tx_region'],
            "bank_info" => json_encode([
                "bank_name" => $this->post['bank_name'],
                "bank_holder" => $this->post['bank_holder'],
                "bank_country" => $this->post['bank_country'] ?? null,
                "identifier" => $this->post['identifier'] ?? null,
                "identifier_code" => $this->post['identifier_code'] ?? null
            ])
        );

    }

    # Get and save beneficiary information

    protected function saveBeneficiary() {

        # Ignore if there is no captured beneficiary
        if( empty($this->beneficiary) ) return;

        # Get beneficiary table
        $benTable = DB_TABLE_PREFIX . "_beneficiaries";

        # Confirm that the Beneficiary data is Unique to the Current User
        $SQL = SQuery::select( $benTable, "
            userid = '{$this->beneficiary['userid']}' 
            AND bank_account = '{$this->beneficiary['bank_account']}'
            AND bank_region = '{$this->beneficiary['bank_region']}'
        ");

        # Uniqueness Validation
        $exists = Uss::$global['mysqli']->query( $SQL )->num_rows;
        
        # If the data doesn't exist, add it
        if( !$exists ) {

            # Create SQL Query
            $SQL = SQuery::insert( $benTable, $this->beneficiary );

            # Insert Dataset
            $insert = Uss::$global['mysqli']->query( $SQL );

        };

    }


    # Add JavaScript or CSS Components

    protected function addAssets() {

        # Send Bank Charge to Javascript Environment
        Uss::console('charge', (float)Uss::$global['options']->get('bank:transfer.charge') );

        # Add Javascript File;
        Events::addListener('@body:after', function() {
            $dir = Core::url( realpath( __DIR__ . "/../" ) . "/script.js" );
            echo "\t<script src='{$dir}'></script>\n";
        }, 'transfer-js');

    }


    # Add a loading Element To delay Transaction

    protected function loading() {

        if( empty($this->post) || !empty($_POST['loaded']) ) return;
        
        Udash::config('blank', !false);

        $this->setTemplate( "transaction.loading.html" );

        return true;

    }


    # Put Beneificaries in Javascript

    protected function consoleBeneficiaries() {
        
        // Region
        $userid = Uss::$global['user']['id'];
        $region = Uss::query(2) == 'intl' ? "international" : "local";

        // Beneficiaries
        $SQL = SQuery::select( DB_TABLE_PREFIX . "_beneficiaries", "userid = '{$userid}' AND bank_region = '{$region}'" );
        $beneficiaries = Udash::mysqli_to_array( Uss::$global['mysqli']->query( $SQL ) );

        foreach( $beneficiaries as $key => $data ) {
            $beneficiaries[$key]['bank_info'] = json_decode($data['bank_info'], true);
        };

        Uss::console('beneficiaries', $beneficiaries);
    
    }

}