// Account management toosl
#include "clog.h"
#include "cgi.h"
#include "input.h"
#include "wrenchboard_api.h"
#include "payments.h"
#include "creditcards.h"
#include "common_tool.h"
#include "email.h"
#include "safestring.h"
#include <string>
#include "pgsql.h"
#include "pgsql_wrapper.h"
#include "cfg.h"
#include <curl/curl.h>
#include "stripe_charge.h"

/*
CREATE TABLE payment_types (
    id SERIAL,
    type_code varchar(25) UNIQUE NOT NULL,
	code varchar(5) UNIQUE NOT NULL,
    dir INT DEFAULT 0
	)
 ALTER TABLE ONLY payment_types
    ADD CONSTRAINT payment_types_id_key UNIQUE (id);
	
INSERT INTO payment_types(type_code,code,dir) VALUES('OFFER_PYM_DEPOSIT','OFDPS',0);
INSERT INTO payment_types(type_code,code,dir) VALUES('OFFER_PYM_REFUND','OFRFD',1); -- // refund if offer was rejected or not accepted
*/
long UpdateMemberWallet(long member_id,long wallet_id,long amount, long payment_id);

long  WrenchMemberTopupPayment( CVars in, CVars &out )
{
	    logfmt(FLOG_MAX, "long WrenchMemberTopupPayment(CVars in, CVars &out)" );
		long ret = PHP_API_BAD_PARAM;
		ULONG payment_id = 0;
		const char * loc = getenv("REMOTE_ADDR");
		in["loc"]  = loc; in["loc"].set_valid(true);
	 
	    long member_id = REQ_LONG( in, "member_id", 1, -1 );
        REQ_STRING (in, "tx_ref",   4, 50, "(.*)");
        long trx_id = REQ_LONG( in, "trx_id", 1, -1 );
		
		// let us make sure you have the wallet
		// do we have a wallet for this action
		CVars vw;
		vw["currency"] = "NAIRA";  // this might become a variable based on the country
		vw["currency"].set_valid( true );
		long wallet_id = CheckWallet(member_id,vw);
		if(!wallet_id || wallet_id == 0 ){
		return -1; // no wallet  -- 
		}
		in["curr_balance"] ="0";

        long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND currency='%s' ", member_id, vw["currency"].c_str());
        if (retDb)
        { 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true );
            logfmt(FLOG_MAX, "Current balance Read ********************" );
        }
        else  {   return -1; /* unable to read wallet*/ }

	    long retDb2 = load_db_record( out, "SELECT * FROM flutterwave_payments "
	                                       " WHERE member_id = %lu AND tx_ref ='%s' "
	                                       " AND id = %lu AND status = 5", in["member_id"].Long(), in["tx_ref"].c_str(),trx_id );
		if (retDb2> 0)
		{
		        in["amount"] =out["amount"];  in["amount"].set_valid( true );

                CVars x;
                x["member_id"] = member_id; x["member_id"].set_valid( true );
                x["code"] = "TOPUP"; x["code"].set_valid( true );
                x["dir"] = "1"; x["dir"].set_valid( true );
                x["loc"] = in["loc"]; x["loc"].set_valid( true );

                x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
                x["amount"] = in["amount"]; x["amount"].set_valid( true );
                x["fee"] = "0"; x["fee"].set_valid( true );

                x["currency"] = out["currency"]; x["currency"].set_valid( true );
               // x["what_offer"] = offer_id; x["what_offer"].set_valid( true );
                x["what_fluwv"] = trx_id; x["what_fluwv"].set_valid( true );  // assign coupon id


                x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
                payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );

              if (payment_id) {
                ret = PHP_CREATED_OK;
                x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
                // now generate the confirmation
                char confirmation[15] = "";
                Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call

                UpdateMemberWallet( x["member_id"].Long(), wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount

                x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
                x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
                pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
                pgsql_exec("UPDATE flutterwave_payments SET payment_id=%lu, completed = now() WHERE id = %lu AND member_id=%lu ",payment_id,trx_id,member_id );
              load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
            } else {
                out["status"] = "Unable to create payment";
            }

		}
        else
        {   out["status"] = "Invalid coupon";
            ret= PHP_API_BAD_PARAM;
        }		
		
		
		
		
	 logfmt(FLOG_MAX, "/ long WrenchMemberTopupPayment(CVars in, CVars &out)" );
	return 0;
}

long  WrenchFamilyTransferCredit( CVars in, CVars &out );
long  WrenchFamilyPayment( CVars in, CVars &out )
{
        logfmt(FLOG_MAX, "long WrenchFamilyPayment(CVars in, CVars &out)" );
        long ret = PHP_API_BAD_PARAM;
        ULONG payment_id = 0;
        const char * loc = getenv("REMOTE_ADDR");
        in["loc"]  = loc; in["loc"].set_valid(true);

        long member_id = REQ_LONG( in, "member_id", 1, -1 );
        long recipient_id = REQ_LONG( in, "recipient", 1, -1 );
        long transfer_id  = REQ_LONG( in, "transfer_id", 1, -1 );
        REQ_STRING(in, "currency", 2, 20, "(.*)");
        REQ_STRING(in, "origing_wallet", 2, 50, "(.*)");
        REQ_STRING(in, "target_wallet", 2, 50, "(.*)");

       // REQ_STRING (in, "code",   4, 15, "(.*)");
        long code_id = 0; /// REQ_LONG( in, "code_id", 1, -1 );

    // let us make sure you have the wallet
        // do we have a wallet for this action
        CVars vw;
        vw["currency"] = in["currency"];
        vw["currency"].set_valid( true );
        long wallet_id = CheckWallet(member_id,vw);
        if(!wallet_id || wallet_id == 0 ){
        out["status"] = "wallet_not_found";
        return ret; // no wallet
        }
        in["curr_balance"] ="0";

        long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet "
                                          " WHERE member_id = %lu AND currency='%s' AND uid = '%s'", member_id, vw["currency"].c_str(), in["origing_wallet"].c_str());
        if (retDb > 0 )
        { 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true );
            logfmt(FLOG_MAX, "Current balance Read ********************" );
        }
        else  {
          out["status"] = "wallet_balance_not_found";
         return ret; /* unable to read wallet*/ }

       if (load_db_record( out, "SELECT amount AS rec_curr_balance FROM members_wallet "
                                                     " WHERE member_id = %lu AND currency='%s' AND uid = '%s'", recipient_id, vw["currency"].c_str(), in["target_wallet"].c_str()) > 0 ) //
        { 	in["rec_curr_balance"] =out["rec_curr_balance"];  in["rec_curr_balance"].set_valid( true );
            logfmt(FLOG_MAX, "Current balance Read ********************" );
        }
        else  {
          out["status"] = "wallet_balance_not_found";
         return ret; /* unable to read wallet*/ }


	    long retDb2 = load_db_record( out, "SELECT * FROM family_transfer "
	                                       " WHERE member_id = %lu AND currency ='%s' AND id = %lu AND status = 1 ", in["member_id"].Long(), in["currency"].c_str(),transfer_id );
		if (retDb2>0)
		{
		        in["coupon_amount"] =out["amount"];  in["coupon_amount"].set_valid( true );

                CVars x;
                x["member_id"] = member_id; x["member_id"].set_valid( true );
                x["code"] = "FAMDE"; x["code"].set_valid( true );
                x["dir"] = "0"; x["dir"].set_valid( true );
                x["loc"] = in["loc"]; x["loc"].set_valid( true );
                x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
                x["amount"] = out["amount"]; x["amount"].set_valid( true );
                x["fee"] = "0"; x["fee"].set_valid( true );
                x["what_family_transfer"] = transfer_id; x["what_family_transfer"].set_valid( true );
                x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
                payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );

              if (payment_id) {
                ret = PHP_CREATED_OK;
                x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
                // now generate the confirmation
                char confirmation[15] = "";
                Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
                DeductMemberWallet( x["member_id"].Long(), wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount
                x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
                x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
                pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
                pgsql_exec("UPDATE family_transfer SET pay_confirm = '%s' WHERE id = %lu ",confirmation, transfer_id );
                CVars xrx;
                load_db_record( xrx, "SELECT id AS transfer_id, * FROM family_transfer WHERE id = %lu ", transfer_id );
                return WrenchFamilyTransferCredit( xrx, out ); // let us try credit
            } else {
                out["status"] = "Unable to create payment";
            }

		}
        else
        {   out["status"] = "error_invalid_transfer";
            ret= PHP_API_BAD_PARAM;
        }

        logfmt(FLOG_MAX, "/long WrenchFamilyPayment(CVars in, CVars &out)" );
	   return ret;
}

long  WrenchFamilyTransferCredit( CVars in, CVars &out ){

        logfmt(FLOG_MAX, "long WrenchFamilyTransferCredit(CVars in, CVars &out)" );
        long ret = PHP_API_BAD_PARAM;
        ULONG payment_id = 0;
        const char * loc = getenv("REMOTE_ADDR");
        in["loc"]  = loc; in["loc"].set_valid(true);
        long transfer_id  = REQ_LONG( in, "transfer_id", 1, -1 );

        long retDb2 = load_db_record( out, "SELECT * FROM family_transfer "
	                                       " WHERE member_id = %lu "
	                                       " AND currency ='%s' "
	                                       " AND pay_confirm IS NOT NULL AND credit_confirm IS NULL "
	                                       " AND id = %lu AND status = 1 ", in["member_id"].Long(), in["currency"].c_str(),transfer_id );

		if (retDb2>0)
		{

                long member_id = out["recipient"].Long(); // This is the recipient
                CVars vw;
                vw["currency"] = in["currency"];
                vw["currency"].set_valid( true );
                long wallet_id = CheckWallet(member_id,vw);
                if(!wallet_id || wallet_id == 0 ){
                out["status"] = "wallet_not_found";
                return ret; // no wallet
                }
                in["curr_balance"] ="0";

		        long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet "
                                                  " WHERE member_id = %lu AND currency='%s' AND uid = '%s'", out["recipient"].Long(), out["currency"].c_str(), out["target_wallet"].c_str());
                if (retDb > 0 )
                { 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true );
                    logfmt(FLOG_MAX, "Current balance Read ********************" );
                }
                else  {
                  out["status"] = "wallet_balance_not_found";
                 return ret; /* unable to read wallet*/ }


                CVars x;
                x["member_id"] = out["recipient"]; x["member_id"].set_valid( true ); // the recipient on family table
                x["code"] = "FAMCR"; x["code"].set_valid( true );
                x["dir"] = "1"; x["dir"].set_valid( true );
                x["loc"] = in["loc"]; x["loc"].set_valid( true );
                x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
                x["amount"] = out["amount"]; x["amount"].set_valid( true );
                x["fee"] = "0"; x["fee"].set_valid( true );
                x["what_family_transfer"] = transfer_id; x["what_family_transfer"].set_valid( true );
                x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
                payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );

              if (payment_id) {
                ret = PHP_CREATED_OK;
                x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
                // now generate the confirmation
                char confirmation[15] = "";
                Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
                UpdateMemberWallet( x["member_id"].Long(), wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount
                x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
                x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
                pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
                pgsql_exec("UPDATE family_transfer SET credit_confirm = '%s' WHERE id = %lu ",confirmation, transfer_id );
                CVars xrx;
                if (   load_db_record( out, "SELECT f.id AS transfer_id, f.*, "
                                      " f.amount*0.01||'('||f.currency||') Reward sent to '||m.firstname  AS title, "
                                      " m.firstname FROM family_transfer f LEFT JOIN members m ON m.id = f.recipient WHERE f.id = %lu ", transfer_id )> 0 ){

                                          out["status"] = "OK";
                                          out["status_message"] = "trasnfer_completed";
                                          ret = PHP_API_OK;

                                          CVars xxx, yy;
                                         // char title[90];
                                          xxx["member_id"] = in["member_id"]; xxx["member_id"].set_valid( true );  // for the original sender
                                         // snprintf(title, sizeof (title), "%lu(%s) Reward sent to %s",out["amount"].Long()*0.01,out["currency"].c_str(),  out["firstname"].c_str());
                                          xxx["title"] = out["title"]; xxx["title"].set_valid( true );
                                          xxx["description"] =   out["description"]; xxx["description"].set_valid( true );
                                          WrenchLogRecent(out, yy); // out contains everything needed
                                      }


            } else {
                out["status"] = "Unable to create payment";
            }

		}
        else
        {   out["status"] = "error_invalid_credit";
            ret= PHP_API_BAD_PARAM;
        }


        logfmt(FLOG_MAX, "OUT *** long WrenchFamilyTransferCredit(CVars in, CVars &out)" );
    return ret;
}

long  WrenchMemberCouponPayment( CVars in, CVars &out )
{
        logfmt(FLOG_MAX, "long WrenchMemberCouponPayment(CVars in, CVars &out)" );
        long ret = PHP_API_BAD_PARAM;
        ULONG payment_id = 0;
        const char * loc = getenv("REMOTE_ADDR");
        in["loc"]  = loc; in["loc"].set_valid(true);

        long member_id = REQ_LONG( in, "member_id", 1, -1 );
        REQ_STRING (in, "code",   4, 15, "(.*)");
        long code_id = REQ_LONG( in, "code_id", 1, -1 );

    // let us make sure you have the wallet
        // do we have a wallet for this action
        CVars vw;
        vw["currency"] = "NAIRA";  // this might become a variable based on the country
        vw["currency"].set_valid( true );
        long wallet_id = CheckWallet(member_id,vw);
        if(!wallet_id || wallet_id == 0 ){
        return -1; // no wallet
        }
        in["curr_balance"] ="0";

        long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND currency='%s' ", member_id, vw["currency"].c_str());
        if (retDb)
        { 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true );
            logfmt(FLOG_MAX, "Current balance Read ********************" );
        }
        else  {   return -1; /* unable to read wallet*/ }


	    long retDb2 = load_db_record( out, "SELECT * FROM coupons_allocation WHERE member_id = %lu AND code ='%s' AND id = %lu AND active IS NULL", in["member_id"].Long(), in["code"].c_str(),code_id );
		if (retDb2)
		{
		        in["coupon_amount"] =out["amount"];  in["coupon_amount"].set_valid( true );

                CVars x;
                x["member_id"] = member_id; x["member_id"].set_valid( true );
                x["code"] = "COUP"; x["code"].set_valid( true );
                x["dir"] = "1"; x["dir"].set_valid( true );
                x["loc"] = in["loc"]; x["loc"].set_valid( true );

                x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
                x["amount"] = in["coupon_amount"]; x["amount"].set_valid( true );
                x["fee"] = "0"; x["fee"].set_valid( true );

               // x["what_offer"] = offer_id; x["what_offer"].set_valid( true );
                x["what_coupon"] = code_id; x["what_coupon"].set_valid( true );  // assign coupon id


                x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
                payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );

              if (payment_id) {
                ret = PHP_CREATED_OK;
                x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
                // now generate the confirmation
                char confirmation[15] = "";
                Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call

                UpdateMemberWallet( x["member_id"].Long(), wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount

                x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
                x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
                pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
                pgsql_exec("UPDATE coupons_allocation SET active = now() WHERE id = %lu AND CODE='%s' ",code_id,in["code"].c_str() );
              load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
            } else {
                out["status"] = "Unable to create payment";
            }

		}
        else
        {   out["status"] = "Invalid coupon";
            ret= PHP_API_BAD_PARAM;
        }

        logfmt(FLOG_MAX, "/long WrenchMemberCouponPayment(CVars in, CVars &out)" );
	   return ret;
}
/*
Construct Virtual card Wallet
*/
long AssignVirtualCardWallet(CVars in,CVars out){
 logfmt(FLOG_MAX, "long CheckWallet()" );
 long wallet_id = 0;
 CVars y;
 try{
        REQ_STRING(in, "request_uid", 12, 160, "(.*)");
        long request_id = REQ_LONG(in,   "request_id", 0, -1);

		if ( load_db_record( y, "SELECT r.*,m.id AS target_member_id FROM members_card_request r LEFT JOIN members m ON m.uid::text=r.target_uid::text WHERE r.status = %lu AND r.uid::text ='%s' AND r.id =%lu",CARD_ACTIVATE_CARD, in["request_uid"].c_str(),request_id ) > 0 )
		{
            CVars x;
            x["member_id"] = y["target_member_id"]; x["member_id"].set_valid( true );
            x["currency"] = "VUSD"; x["currency"].set_valid( true );
            x["transfer_limit"] = "100000"; x["transfer_limit"].set_valid( true );
            x["card_issue_id"] = y["card_issue_id"]; x["card_issue_id"].set_valid( true );
            x["card_id"] = y["card_id"]; x["card_id"].set_valid( true );
            x["brand"] = y["brand"]; x["brand"].set_valid( true );
            x["card_last4"] = y["card_last4"]; x["card_last4"].set_valid( true );
            wallet_id = insert_db_record( DBS_VALID, "members_wallet", "members_wallet_id_seq", x );
            if(wallet_id> 0){
            	pgsql_exec("UPDATE members_card_request SET status = %lu  WHERE uid::text ='%s' AND id =%lu",CARD_WALLET_ADD, in["request_uid"].c_str(),request_id);	//
            }
		}
		else{
             wallet_id  = -1;
		}
	} catch (bad_parameter) {
	 logfmt(logINFO, "ERROR CALL long AssignVirtualCardWallet(CVars in, CVars &out)");
	}
  return wallet_id;
}

/*
call to verify the user have the wallet in place - or create it
if this fail , dont continue with collecting money , no place to put it.
*/
long CheckWallet(long member_id,CVars in){
 logfmt(FLOG_MAX, "long CheckWallet()" );
 long wallet_id = 0;
 CVars y;
	if ( load_db_record( y, "SELECT * FROM members_wallet WHERE currency ='%s' AND member_id =%lu",in["currency"].c_str(),member_id ) > 0 )
	{
      wallet_id  = y["id"].Long();
	}
	else{
        CVars x;
        x["member_id"] = member_id; x["member_id"].set_valid( true );
        x["currency"] = in["currency"]; x["currency"].set_valid( true );
        x["transfer_limit"] = "1000000"; x["transfer_limit"].set_valid( true );
        wallet_id = insert_db_record( DBS_VALID, "members_wallet", "members_wallet_id_seq", x );
	}
  return wallet_id;
}

long UpdateMemberWallet(long member_id,long wallet_id,long amount, long payment_id){
CVars y;
if ( load_db_record( y, "SELECT * FROM members_wallet WHERE id = %lu AND member_id =%lu", wallet_id,member_id ) > 0 )
	{

        CVars x;
        x["member_id"] = member_id; x["member_id"].set_valid( true ); //
        x["payment_id"] = payment_id; x["payment_id"].set_valid( true ); //
        x["amount"] = amount; x["amount"].set_valid( true ); //
        x["balance"] = y["amount"]; x["balance"].set_valid( true ); //
        insert_db_record( DBS_VALID, "members_wallet_detail", "members_wallet_detail_id_seq", x );


      	pgsql_exec("UPDATE members_wallet SET amount=amount + %lu,prev_amount=%lu WHERE member_id = %lu AND id=%lu",amount,y["amount"].Long(),member_id , wallet_id);	// pay attention to who you pay here
	}
	return 1;
}

long DeductMemberWallet(long member_id,long wallet_id,long amount, long payment_id){
	logfmt(FLOG_MAX, "DeductMemberWallet ************************" );
	logfmt(FLOG_MAX, "Review this design so as not to loose money  ");
	logfmt(FLOG_MAX, "DeductMemberWallet ************************" );

CVars y;
if ( load_db_record( y, "SELECT * FROM members_wallet WHERE id = %lu AND member_id =%lu", wallet_id,member_id ) > 0 )
	{

        CVars x;
        x["member_id"] = member_id; x["member_id"].set_valid( true ); //
        x["payment_id"] = payment_id; x["payment_id"].set_valid( true ); //
        x["amount"] = amount; x["amount"].set_valid( true ); //
        x["balance"] = y["amount"]; x["balance"].set_valid( true ); //
        insert_db_record( DBS_VALID, "members_wallet_detail", "members_wallet_detail_id_seq", x );
      	pgsql_exec("UPDATE members_wallet SET amount=amount - %lu,prev_amount=%lu WHERE member_id = %lu AND id=%lu",amount,y["amount"].Long(),member_id , wallet_id);	// pay attention to who you pay here
	}
	return 1;
}

long  WrenchStartPayment( CVars in, CVars &out ){

   logfmt(logINFO, "WrenchStartPayment()");
    long ret = PHP_API_BAD_PARAM;
    const PGresult *res;
    out["status_text"] = "Start";
    out["status"] = "-1";

    try {
            long member_id = REQ_LONG( in, "member_id", 1, -1 );
            long amount = REQ_LONG( in, "amount", 1, -1 );
            REQ_STRING (in, "currency",   2, 10, "(.*)");
            REQ_STRING(in, "uid", 3, 150, "(.*)");
            OPTIONAL(in, "card_uid") REQ_STRING(in, "card_uid", 3, 150, "(.*)");

            const PGresult *res = pgsql_query("SELECT uid,id AS member_id FROM members WHERE id=%lu AND uid='%s'", member_id, in["uid"].c_str());
            if (res != NULL && pgsql_num_rows(res) > 0) {
                map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
                CVars rec;
                map_to_cvars(f, rec);
                out["status"] = "STARTED";
                out = rec;
            }
            else{
             out["status"] = "ERROR";
            return ret;
            }

            CVars xx;

            xx["member_id"] = member_id;
            xx["member_id"].set_valid(true);
            xx["amount"] = in["amount"];
            xx["amount"].set_valid(true);
            xx["currency"] = in["currency"];
            xx["currency"].set_valid(true);

            xx["card_uid"] = in["card_uid"];
            xx["card_uid"].set_valid(true);

            out["credit_ref_no"] = "0";
            out["credit_ref_no"] = insert_db_record(DBS_VALID, "members_credit", "members_credit_id_seq", xx);

    		if ( out["credit_ref_no"].Long() > 0) {
               if( load_db_record( out, "SELECT uid AS credit_reference, fee, currency, amount, amount+fee AS total, card_uid "
                                     " FROM members_credit WHERE member_id = %lu AND id=%lu ", member_id,  out["credit_ref_no"].Long())> 0){
                      out["status"] = "OK";
                      out["flutterwave_key"] = CfgReadChar("flutterwave.public_key");
                      ret = PHP_API_OK;
                                     }

    		}

    } catch (bad_parameter) {
        out["status"] = "ERROR";
    }

    logfmt(logINFO, "/WrenchStartPayment()");
    return ret;

return 0;
}


long  WrenchNewCardPayment( CVars in, CVars &out )
{
    long payment_return = 0; // just return 0 if not okay , payment_id is all okay
    logfmt(FLOG_MAX, "long WrenchNewCardPayment(CVars in, CVars &out)" );
    long member_id = REQ_LONG( in, "member_id", 1, -1 );
    long amount = REQ_LONG( in, "amount", 1, -1 );
    OPTIONAL(in, "WHAT_CHARGE_TYPE") REQ_STRING(in, "WHAT_CHARGE_TYPE", 3, 15, "(.*)");
    long card_id = 0;

    if ( in["WHAT_CHARGE_TYPE"] == "USE_CARD_ID"){
        card_id = REQ_LONG( in, "card_id", 1, -1 );
        in["what_purhcase"] = "MEMBER_RETCARD_PAYM";  in["what_purhcase"].set_valid( true );
    }
    else
    {
        REQ_STRING(in, "cardnumber", 12, 16, "(.*)"); //4111111111111111"
        REQ_STRING(in, "cvc", 3, 4, "(.*)"); //234"
        REQ_LONG(in,   "paymenttype", 0, -1);
        REQ_STRING(in, "exp_month", 2, 2, "(.*)");
        REQ_STRING(in, "exp_year", 4, 4, "(.*)");
        in["what_purhcase"] = "MEMBER_NEWCARD_PAYM";  in["what_purhcase"].set_valid( true );
    }


	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);

	long payment_id =0;

    // do we have a wallet for this action
    CVars vw;
    vw["currency"] = "USD";  // this might become a variable based on the country
    vw["currency"].set_valid( true );
    long wallet_id = CheckWallet(member_id,vw);
    if(!wallet_id || wallet_id == 0 ){
    return -1; // no wallet
    }
    in["curr_balance"] ="0";
    long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND currency='%s' ", member_id, vw["currency"].c_str());
	if (retDb)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true );
	    logfmt(FLOG_MAX, "Current balance Read ********************" );
	}
	else  {   return -1; /* unable to read wallet*/ }

    // verify if allowed

    // take in sessionid to verify if allaowed too

    // Get the code and dir contruct
    long retTc = load_db_record( out, "SELECT * FROM payment_types WHERE type_code = '%s' ",in["what_purhcase"].c_str());
    if (retTc)
    {
       in["code"] = out["code"];  in["code"].set_valid( true );
       in["dir"] = out["dir"];  in["dir"].set_valid( true );
    }
    else  {   return -1; /* unable to get payment type*/ }

    CVars x;
    x["member_id"] = member_id; x["member_id"].set_valid( true ); //
    x["loc"] = in["loc"]; x["loc"].set_valid( true ); //
    x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true ); //
    x["amount"] = amount; x["amount"].set_valid( true );
    x["fee"] = "0"; x["fee"].set_valid( true );
    x["code"] = in["code"]; x["code"].set_valid( true );
    x["dir"] = in["dir"]; x["dir"].set_valid( true );
    x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
    x["currency"] = vw["currency"]; x["currency"].set_valid( true );

    payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
    // ALL STRIPE COMPATIBLE
    if ( card_id == 0 ){
       card_id = save_creditcard(in, out);
    }


    if (card_id && card_id> 0){
     pgsql_exec("UPDATE members_payments SET account_id = %lu WHERE id = %lu",card_id,payment_id );
    }
    else{
      return -1;
    }

    CVars yx;
    yx["member_id"] =  member_id; yx["member_id"].set_valid( true );
    yx["payment_id"] =  payment_id; yx["payment_id"].set_valid( true );
    long stripe_payment = stripe_charge_member_paymentid(yx, out);  // go for stripe now

		  if (stripe_payment==PHP_API_OK) {
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			//pgsql_exec("UPDATE members_wallet SET amount=amount + %lu,prev_amount=%lu WHERE member_id = %lu AND id=%lu",x["amount"].Long(),x["curr_balance"].Long(),x["member_id"].Long() , wallet_id);	// pay attention to who you pay here

			char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
			UpdateMemberWallet( member_id, wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount
			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
		    load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		    payment_return =  payment_id;
		} else {
			out["status"] = "Unable to create payment";
		}

      logfmt(FLOG_MAX, "/long WrenchNewCardPayment(CVars in, CVars &out)" );
return payment_return;
}



long  WrenchCardRechargePayment( CVars in, CVars &out )
{
        logfmt(FLOG_MAX, "long WrenchCardRechargePayment(CVars in, CVars &out)" );
         long ret = PHP_API_BAD_PARAM;

            try {
            long member_id = REQ_LONG( in, "member_id", 1, -1 );
            long amount = REQ_LONG( in, "amount", 1, -1 );
            REQ_STRING(in, "card_uid", 15, 45, "(.*)");
            REQ_STRING(in, "uid", 15, 45, "(.*)");
            REQ_STRING(in, "credit_reference", 15, 45, "(.*)");

            // Test tye credit reference
            //SELECT mc.amount, mc.currency  FROM members_credit mc LEFT JOIN members m ON m.id =mc.member_id  WHERE mc.uid = 'eb813f56-41b3-4123-b943-605d3ae6c813' AND mc.member_id = 1;;
            if (load_db_record(out, "SELECT mc.amount, mc.currency  FROM members_credit mc LEFT JOIN members m ON m.id =mc.member_id  "
                                    " WHERE mc.uid = '%s' AND m.uid = '%s'", in["credit_reference"].c_str(), in["uid"].c_str()) > 0)
                {
                  if ( in["amount"].Long() != out["amount"].Long() ){
                        out["status"] = "Invalid Amount";
                         return ret;
                  }
                }
                else{
                   out["status"] = "Invalid Call";
                   return ret;
                }


            if (load_db_record(out, "SELECT c.id as card_id FROM creditcard c LEFT JOIN members m ON m.id =c.member_id  "
                                    " WHERE c.uid = '%s' AND m.uid = '%s'", in["card_uid"].c_str(), in["uid"].c_str()) > 0)
                {
                  //  long card_id = REQ_LONG( in, "card_id", 1, -1 );
                    in["card_id"] = out["card_id"];  in["card_id"].set_valid( true );
                    in["WHAT_CHARGE_TYPE"] = "USE_CARD_ID"; in["WHAT_CHARGE_TYPE"].set_valid( true ); //
                    ret =  WrenchNewCardPayment( in, out );
                }

            } catch (bad_parameter) {
                out["status"] = "Invalid Parameters";
            }
        logfmt(FLOG_MAX, "/long WrenchCardRechargePayment(CVars in, CVars &out)" );
        return ret;
}

long  WrenchCanceContractPayment( CVars in, CVars &out )
{


/*
	y["member_id"] = in["member_id"]; // note we are actually paying the client_id
					y["contract_id"] = in["job_id"];
					y["code"] = "COPAY";
					y["dir"] = DIR_TARGET;
	*/
	long ret = PHP_API_BAD_PARAM;
	//ULONG payment_id = 0;
	
	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);	
	long member_id = REQ_LONG( in, "member_id", 1, -1 );
	long contract_id = REQ_LONG( in, "contract_id", 1, -1 );
	REQ_LONG( in, "dir", 1, -1 );
	REQ_STRING (in, "code",   4, 5, "(.*)");
	//long offer_id = REQ_LONG( in, "offer_id", 1, -1 );
	long payment_id = 0; //
	//long client_id = 0;
	long offer_id = 0;
	long amount = 0;
	//IS THIS JOB COMPLETED AND ACCEPTED YET
	
	if ( load_db_record( out, "SELECT * FROM members_jobs_contract WHERE status =%lu AND id=%lu AND member_id =%lu",in["job_status"].Long(),contract_id,in["member_id"].Long() ) )
	{
      member_id =  out["member_id"].Long(); // NOTE THAT WE ARE REFUNDING SO CLIENT IS SAME AS MEMBER FOR THIS REFUND
	}
	else{
		out["status_message"] = "Task is not in complete mode";
		return PHP_API_BAD_PARAM;
	}
    CVars y;
	if ( load_db_record( y, "SELECT * FROM members_payments WHERE code ='OFDPS' AND confirmation IS NOT NULL AND status=1 AND flags=4 AND what_contract= %lu AND member_id =%lu",contract_id,in["member_id"].Long() ) )
	{
      payment_id  = y["id"].Long();
	  offer_id =  y["what_offer"].Long();
	  amount = y["amount"].Long();
	}
	else{
		out["status_message"] = "Task payment not found";
		return PHP_API_BAD_PARAM;
	}
	
	
	if (member_id <=0 || payment_id<=0)
	{
	    out["status_message"] = "Client or Payment not properly determined";
		return PHP_API_BAD_PARAM;
	}
	
	
	// TEST FOR DUPLICATE 	
	long retDb = load_db_record( out, "SELECT balance AS curr_balance FROM members WHERE id = %lu", member_id);
	
	if (retDb>0)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
	}
	else
	{   out["status"] = "Unable to get client balance";
	    out["status_message"] = out["status"];
        return PHP_API_BAD_PARAM;	}
	
	
	
		CVars vw;
        vw["currency"] = y["currency"];  //"N-AI-RA";  // this might become a variable based on the country
        vw["currency"].set_valid( true );
        long wallet_id = CheckWallet(in["member_id"].Long(),vw);

	
	/*
	// TEST FOR DUPLICATE 	
	long retDb = load_db_record( out, "SELECT balance AS curr_balance FROM members WHERE id = %lu", in["member_id"].Long());
	
	if (retDb)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
	}
	else
	{   out["status"] = "Duplicate payment detetected";
        return PHP_API_BAD_PARAM;	}
	*/
	
		long retDb2 = load_db_record( out, "SELECT * FROM members_payments WHERE id =%lu AND what_offer = %lu AND member_id=%lu AND code = 'OFDPS' AND status = 1 AND flags = 4 AND confirmation IS NOT NULL",payment_id,offer_id,member_id);
		if (retDb2)
		{
			CVars x;
			x["member_id"] = member_id; x["member_id"].set_valid( true );
			x["code"] = in["code"]; x["code"].set_valid( true );	
			x["dir"] = in["dir"]; x["dir"].set_valid( true );	
			x["loc"] = in["loc"]; x["loc"].set_valid( true );		

			x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );	
			x["amount"] = amount; x["amount"].set_valid( true );	
			x["fee"] = "0"; x["fee"].set_valid( true );	

			x["what_offer"] = offer_id; x["what_offer"].set_valid( true );	
			x["what_contract"] = contract_id; x["what_contract"].set_valid( true );	
			
			
			x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
			payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
		
		  if (payment_id) {
		    ret = PHP_CREATED_OK;
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			// now generate the confirmation
			//- Retired this method pgsql_exec("UPDATE members SET balance=balance + %lu WHERE id = %lu",x["amount"].Long(),x["member_id"].Long() );	// pay attention to who you pay here
			char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call

			UpdateMemberWallet( x["member_id"].Long(), wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount

			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );		
			//pgsql_exec("UPDATE members_jobs_offer SET payment_id = %lu WHERE id = %lu",x["payment_id"].Long(),x["what_offer"].Long() );		
		  load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		} else {
			out["status"] = "Unable to create payment";
		}
		
		}
	return ret;	
	
}



long  WrenchOfferPayment( CVars in, CVars &out )
{
	
	/*
wrenchboard=> \d members_payments;
                                       Table "public.members_payments"
     Column     |            Type             |                           Modifiers                           
----------------+-----------------------------+---------------------------------------------------------------
 id             | integer                     | not null default nextval('members_payments_id_seq'::regclass)
 member_id      | integer                     | 
 code           | character varying(5)        | 
 dir            | integer                     | not null
 curr_balance   | integer                     | default 0
 amount         | integer                     | default 0
 fee            | integer                     | default 0
 confirmation   | character varying(15)       | 
 status         | integer                     | default 1
 flags          | integer                     | default 1
 added          | timestamp without time zone | default now()
 updated        | timestamp without time zone | default now()
 loc            | inet                        | 
 what_offer     | integer                     | 
 what_contract  | integer                     | 
 what_sendmoney | integer                     | 
Indexes:
    "members_payments_confirmation_key" UNIQUE CONSTRAINT, btree (confirmation)
    "members_payments_id_key" UNIQUE CONSTRAINT, btree (id)
Foreign-key constraints:
    "members_payments_code_fkey" FOREIGN KEY (code) REFERENCES payment_types(code)
    "members_payments_member_id_fkey" FOREIGN KEY (member_id) REFERENCES members(id)
    "members_payments_what_contract_fkey" FOREIGN KEY (what_contract) REFERENCES members_jobs_contract(id)
    "members_payments_what_offer_fkey" FOREIGN KEY (what_offer) REFERENCES members_jobs_offer(id)
    "members_payments_what_sendmoney_fkey" FOREIGN KEY (what_sendmoney) REFERENCES money_transfer(id)


	*/
	long ret = PHP_API_BAD_PARAM;
	logfmt( logINFO, "WrenchOfferPayment()" );
	ULONG payment_id = 0;
	
	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);
	
	REQ_LONG( in, "member_id", 1, -1 );
	REQ_STRING (in, "code",   4, 5, "(.*)");
	REQ_LONG( in, "dir", 1, -1 );
	REQ_LONG( in, "offer_id", 1, -1 );


    long retDb2 = load_db_record( out, "SELECT jj.price,0 as fee,c.code AS currency FROM members_jobs_offer j "
                                       " LEFT JOIN members_jobs jj ON jj.id=j.job_id LEFT JOIN currency c ON c.country=jj.country WHERE j.id =%lu ",in["offer_id"].Long());
    if (retDb2 > 0)
    { 	in["amount"] =out["price"];  in["amount"].set_valid( true ); // get this one LIVE
        in["fee"] =out["fee"];  in["fee"].set_valid( true ); // get this one LIVE
    }
    else
    {   out["status"] = "Invalid offer";
        return PHP_API_BAD_PARAM;
    }


	CVars vw;
    vw["currency"] = out["currency"]; //  // this might become a variable based on the country
    vw["currency"].set_valid( true );
    long wallet_id = CheckWallet(in["member_id"].Long(),vw);

	long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND id = %lu", in["member_id"].Long(),wallet_id);
	
	if (retDb)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
	}
	else
	{   out["status"] = "Invalid user";
        return PHP_API_BAD_PARAM;	
	}
	

	long totalAmount  =  in["amount"].Long() + in["fee"].Long();
	if ( in["curr_balance"] < in["amount"].Long() + in["fee"].Long())
	{
		out["status"] = "Insufficient balance for this offer";
        return PHP_API_BAD_PARAM;
	}
	
	// if you have enough money for this offer
	
	//	flags //

	
	CVars x;
	x["member_id"] = in["member_id"]; x["member_id"].set_valid( true );
	x["code"] = in["code"]; x["code"].set_valid( true );	
	x["dir"] = in["dir"]; x["dir"].set_valid( true );	
	x["loc"] = in["loc"]; x["loc"].set_valid( true );		

	x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );	
	x["amount"] = in["amount"]; x["amount"].set_valid( true );	
	x["fee"] = in["fee"]; x["fee"].set_valid( true );	

	x["what_offer"] = in["offer_id"]; x["what_offer"].set_valid( true );		
	x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
	
	x["currency"] =  vw["currency"]; x["currency"].set_valid( true );
	 
	payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
	out["payment_id"] = payment_id; out["payment_id"].set_valid( true );
	
		if (payment_id) {
		ret = PHP_CREATED_OK;
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			// now generate the confirmation
			//pgsql_exec("UPDATE members SET balance=balance - %lu WHERE id = %lu",in["amount"].Long() + in["fee"].Long(),in["member_id"].Long() );
			DeductMemberWallet(in["member_id"].Long(), wallet_id,in["amount"].Long(), payment_id);		
			char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call							
			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );		
			pgsql_exec("UPDATE members_jobs_offer SET payment_id = %lu WHERE id = %lu",x["payment_id"].Long(),x["what_offer"].Long() );		
		  load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		} else {
			out["status"] = "Uanble to create payment";
		}
			
	logfmt( logINFO, "/WrenchOfferPayment()" );	
	return ret;
}

long  WrenchZeroRefundOffer( CVars in, CVars &out )
{
	logfmt( logINFO, "WrenchZeroRefundOffer" );
	long ret = PHP_API_BAD_PARAM;
	//ULONG payment_id = 0;

	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);

	long member_id = REQ_LONG( in, "member_id", 1, -1 );
	REQ_STRING (in, "code",   4, 5, "(.*)");
	REQ_LONG( in, "dir", 1, -1 );
	long offer_id = REQ_LONG( in, "offer_id", 1, -1 );
	long payment_id = REQ_LONG( in, "payment_id", 1, -1 );


		long retDb2 = load_db_record( out, "SELECT id AS current_payment_id, * FROM members_payments WHERE id =%lu AND what_offer = %lu AND member_id=%lu AND code = 'OFDPS' AND status = 1 AND flags = 4 AND confirmation IS NOT NULL",payment_id,offer_id,member_id);
		if (retDb2)
		{
			long current_payment_id  = out["current_payment_id"].Long();


			    CVars vw;
                vw["currency"] = out["currency"];  // this might become a variable based on the country
                vw["currency"].set_valid( true );
                long wallet_id = CheckWallet(in["member_id"].Long(),vw);

            	long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND id = %lu", in["member_id"].Long(),wallet_id);

            	if (retDb > 0)
            	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
            	}
            	else
            	{   out["status"] = "Invalid user";
                    return PHP_API_BAD_PARAM;
            	}

			CVars x;
			x["member_id"] = in["member_id"]; x["member_id"].set_valid( true );
			x["code"] = in["code"]; x["code"].set_valid( true );
			x["dir"] = in["dir"]; x["dir"].set_valid( true );
			x["loc"] = in["loc"]; x["loc"].set_valid( true );

			x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
			x["amount"] = out["amount"]; x["amount"].set_valid( true );
			x["fee"] = out["fee"]; x["fee"].set_valid( true );

			x["what_offer"] = out["what_offer"]; x["what_offer"].set_valid( true );
			x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
			payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );

		  if (payment_id) {
		    ret = PHP_CREATED_OK;
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			// now generate the confirmation
			char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
			// DO NOT UPDATE WALLET UpdateMemberWallet( member_id, wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount
			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
            pgsql_exec("UPDATE members_payments SET flags = 7 WHERE id = %lu",current_payment_id );
			//pgsql_exec("UPDATE members_jobs_offer SET payment_id = %lu WHERE id = %lu",x["payment_id"].Long(),x["what_offer"].Long() );
		  load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		} else {
			out["status"] = "Unable to Refund Payment";
		}

		}

	logfmt( logINFO, "/WrenchZeroRefundOffer" );
	return ret;
}

long  WrenchRefundoffer( CVars in, CVars &out )
{
	logfmt( logINFO, "WrenchRefundoffer" );
	long ret = PHP_API_BAD_PARAM;
	//ULONG payment_id = 0;

	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);
	
	long member_id = REQ_LONG( in, "member_id", 1, -1 );
	REQ_STRING (in, "code",   4, 5, "(.*)");
	REQ_LONG( in, "dir", 1, -1 );
	long offer_id = REQ_LONG( in, "offer_id", 1, -1 );
	long payment_id = REQ_LONG( in, "payment_id", 1, -1 );

	
		long retDb2 = load_db_record( out, "SELECT id AS current_payment_id, * FROM members_payments WHERE id =%lu AND what_offer = %lu AND member_id=%lu AND code = 'OFDPS' AND status = 1 AND flags = 4 AND confirmation IS NOT NULL",payment_id,offer_id,member_id);
		if (retDb2)
		{
			long current_payment_id  = out["current_payment_id"].Long();


			    CVars vw;
                vw["currency"] = out["currency"];  // this might become a variable based on the country
                vw["currency"].set_valid( true );
                long wallet_id = CheckWallet(in["member_id"].Long(),vw);

            	long retDb = load_db_record( out, "SELECT amount AS curr_balance FROM members_wallet WHERE member_id = %lu AND id = %lu", in["member_id"].Long(),wallet_id);

            	if (retDb > 0)
            	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
            	}
            	else
            	{   out["status"] = "Invalid user";
                    return PHP_API_BAD_PARAM;
            	}

			CVars x;
			x["member_id"] = in["member_id"]; x["member_id"].set_valid( true );
			x["code"] = in["code"]; x["code"].set_valid( true );	
			x["dir"] = in["dir"]; x["dir"].set_valid( true );	
			x["loc"] = in["loc"]; x["loc"].set_valid( true );		

			x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );	
			x["amount"] = out["amount"]; x["amount"].set_valid( true );	
			x["fee"] = out["fee"]; x["fee"].set_valid( true );	

			x["what_offer"] = out["what_offer"]; x["what_offer"].set_valid( true );		
			x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
			payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
		
		  if (payment_id) {
		    ret = PHP_CREATED_OK;
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			// now generate the confirmation
			char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
			UpdateMemberWallet( member_id, wallet_id,x["amount"].Long(), payment_id); // correct this dont send amount
			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );	
            pgsql_exec("UPDATE members_payments SET flags = 7 WHERE id = %lu",current_payment_id );			
			//pgsql_exec("UPDATE members_jobs_offer SET payment_id = %lu WHERE id = %lu",x["payment_id"].Long(),x["what_offer"].Long() );		
		  load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		} else {
			out["status"] = "Unable to Refund Payment";
		}
		
		}	
	
	logfmt( logINFO, "/WrenchRefundoffer" );
	return ret;
}

long  WrenchContractPayment( CVars in, CVars &out )
{
	/*
	y["member_id"] = in["member_id"]; // note we are actually paying the client_id
					y["contract_id"] = in["job_id"];
					y["code"] = "COPAY";
					y["dir"] = DIR_TARGET;
	*/
	long ret = PHP_API_BAD_PARAM;
	//ULONG payment_id = 0;
	
	const char * loc = getenv("REMOTE_ADDR");
	in["loc"]  = loc; in["loc"].set_valid(true);	
	long member_id = REQ_LONG( in, "member_id", 1, -1 );
	long contract_id = REQ_LONG( in, "contract_id", 1, -1 );
	REQ_LONG( in, "dir", 1, -1 );
	REQ_STRING (in, "code",   4, 5, "(.*)");
	//long offer_id = REQ_LONG( in, "offer_id", 1, -1 );
	long payment_id = 0; //
	long final_payment_id = 0; //
	long client_id = 0;
	long offer_id = 0;
	long amount = 0;
	//IS THIS JOB COMPLETED AND ACCEPTED YET
	
	if ( load_db_record( out, "SELECT * FROM members_jobs_contract WHERE status = %lu  AND id=%lu AND member_id =%lu",CONTRACT_ACCEPT_COMPLETE,contract_id,in["member_id"].Long() ) )
	{
      client_id =  out["client_id"].Long();
	}
	else{
		out["status_message"] = "Task is not in complete mode";
		return PHP_API_BAD_PARAM;
	}
    CVars y;
	if ( load_db_record( y, "SELECT * FROM members_payments WHERE code ='OFDPS' AND confirmation IS NOT NULL AND status=1 AND flags=4 AND what_contract= %lu AND member_id =%lu",contract_id,in["member_id"].Long() ) > 0 )
	{
      payment_id  = y["id"].Long();
	  offer_id =  y["what_offer"].Long();
	  amount = y["amount"].Long();
	}
	else{
		out["status_message"] = "Task is not in complete mode";
		return PHP_API_BAD_PARAM;
	}
	
	
	if (client_id <=0 || payment_id<=0)
	{
	    out["status_message"] = "Client or Payment not properly determined";
		return PHP_API_BAD_PARAM;
	}
	
	CVars vw;
    vw["currency"] = y["currency"];  //"NA-IR-A";  // this might become a variable based on the country
    vw["currency"].set_valid( true );
    long wallet_id = CheckWallet(in["member_id"].Long(),vw);
//
    long client_wallet_id = CheckWallet(client_id,vw);
	// TEST FOR DUPLICATE 	
	long retDb = load_db_record( out, "SELECT balance AS curr_balance FROM members WHERE id = %lu", client_id);
	
	if (retDb)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
	}
	else
	{   out["status"] = "Unable to get client balance";
        return PHP_API_BAD_PARAM;	}
	
	
	

	
	/*
	// TEST FOR DUPLICATE 	
	long retDb = load_db_record( out, "SELECT balance AS curr_balance FROM members WHERE id = %lu", in["member_id"].Long());
	
	if (retDb)
	{ 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
	}
	else
	{   out["status"] = "Duplicate payment detetected";
        return PHP_API_BAD_PARAM;	}
	*/
	
		long retDb2 = load_db_record( out, "SELECT * FROM members_payments WHERE id =%lu AND what_offer = %lu AND member_id=%lu AND code = 'OFDPS' AND status = 1 AND flags = 4 AND confirmation IS NOT NULL",payment_id,offer_id,member_id);
		if (retDb2)
		{
			CVars x;
			x["member_id"] = client_id; x["member_id"].set_valid( true );
			x["code"] = in["code"]; x["code"].set_valid( true );	
			x["dir"] = in["dir"]; x["dir"].set_valid( true );	
			x["loc"] = in["loc"]; x["loc"].set_valid( true );		

			x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );	
			x["amount"] = amount; x["amount"].set_valid( true );	
			x["fee"] = "0"; x["fee"].set_valid( true );	

			x["what_offer"] = offer_id; x["what_offer"].set_valid( true );	
			x["what_contract"] = contract_id; x["what_contract"].set_valid( true );	
			x["currency"] = y["currency"]; x["currency"].set_valid( true );
			
			x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
			final_payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
		
		  if (final_payment_id) {
		    ret = PHP_CREATED_OK;
			x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
			// now generate the confirmation
			//pgsql_exec("UPDATE members SET balance=balance + %lu WHERE id = %lu",x["amount"].Long(),x["member_id"].Long() );	// pay attention to who you pay here
			char confirmation[15] = "";
			Confirmation(final_payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
            logfmt( logINFO, "paying for job completed, make sure you pay the correct person()" );
            UpdateMemberWallet( x["member_id"].Long(), client_wallet_id,x["amount"].Long(), final_payment_id); // correct this dont send amount

			x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
			x["payment_id"] = final_payment_id;  x["payment_id"].set_valid( true );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),final_payment_id );
		    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",FLAG_OK_PAID,payment_id ); // this is the holdings
			//pgsql_exec("UPDATE members_jobs_offer SET payment_id = %lu WHERE id = %lu",x["payment_id"].Long(),x["what_offer"].Long() );		
		  load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
		} else {
			out["status"] = "Unable to create payment";
		}
		
		}	
	
	
	return ret;
}
long  WrenchSendMoneyPayment( CVars in, CVars &out )
{

	long ret = PHP_API_BAD_PARAM;
	logfmt( logINFO, "WrenchSendMoneyPayment()************************************  ****" );
	ULONG payment_id = 0;
	
	try {
            const char * loc = getenv("REMOTE_ADDR");
            in["loc"]  = loc; in["loc"].set_valid(true);

            REQ_LONG( in, "member_id", 1, -1 );
            REQ_STRING (in, "code",   4, 5, "(.*)");
            REQ_LONG( in, "dir", 1, -1 );
            REQ_LONG( in, "sendmoney_id", 1, -1 );
            long wallet_id = REQ_LONG( in, "wallet_id", 1, -1 );

            long retDb = load_db_record( out, "SELECT amount AS curr_balance,currency FROM members_wallet WHERE id = %lu AND member_id = %lu",wallet_id, in["member_id"].Long());

            if (retDb > 0 )
            { 	in["curr_balance"] =out["curr_balance"];  in["curr_balance"].set_valid( true ); // get this one LIVE
            }
            else
            {   out["status"] = "Invalid user";
                return PHP_API_BAD_PARAM;	}

            long retDb2 = load_db_record( out, "SELECT id,initiatingamount AS amount,fee from money_transfer WHERE member_id= %lu AND id = %lu",in["member_id"].Long(), in["sendmoney_id"].Long());
            if (retDb2 > 0 )
            { 	in["amount"] =out["amount"];  in["amount"].set_valid( true ); // get this one LIVE
                in["fee"] =out["fee"];  in["fee"].set_valid( true ); // get this one LIVE
            }
            else
            {   out["status"] = "Invalid offer";
                return PHP_API_BAD_PARAM;
            }
            long totalAmount  =  in["amount"].Long() + in["fee"].Long();
            if ( in["curr_balance"] < in["amount"].Long() + in["fee"].Long())
            {
                out["status"] = "Insufficient balance for this offer";
                return PHP_API_BAD_PARAM;
            }


            CVars x;
            x["member_id"] = in["member_id"]; x["member_id"].set_valid( true );
            x["code"] = in["code"]; x["code"].set_valid( true );
            x["dir"] = in["dir"]; x["dir"].set_valid( true );
            x["loc"] = in["loc"]; x["loc"].set_valid( true );
            x["curr_balance"] = in["curr_balance"]; x["curr_balance"].set_valid( true );
            x["amount"] = in["amount"]; x["amount"].set_valid( true );
            x["fee"] = in["fee"]; x["fee"].set_valid( true );
            x["what_sendmoney"] = in["sendmoney_id"]; x["what_sendmoney"].set_valid( true );
            x["currency"] = out["currency"]; x["currency"].set_valid( true );
            x["flags"] =  FLAG_INIT; x["flags"].set_valid( true );	// starting the pprocess
            payment_id = insert_db_record( DBS_VALID, "members_payments", "members_payments_id_seq", x );
            logfmt(logINFO, "long WrenchSendMoneyPayment(CVars in, CVars &out) payment_id = %lu",payment_id);
            // return if not good
            if (payment_id <=0 ){
              logfmt(logINFO, "ERROR  WrenchSendMoneyPayment(CVars in, CVars &out) payment_id = %lu",payment_id);
            }

            const PGresult *res = pgsql_query("SELECT * FROM members_payments WHERE id=%lu AND member_id = %lu",payment_id, x["member_id"].Long() );
            if (res!=NULL && pgsql_num_rows(res)>0)
            {

            }
            else
            {
                out["status"] = "Failure to create";
                return PHP_API_BAD_PARAM;
            }

                out["payment_id"] = payment_id; out["payment_id"].set_valid( true );
                if (payment_id) {

                    x["flags"] =  FLAG_START; x["flags"].set_valid( true );	// done not completed yet
                    // now generate the confirmation
                    //pgsql_exec("UPDATE members SET balance=balance - %lu WHERE id = %lu",in["amount"].Long() + in["fee"].Long(),in["member_id"].Long() );
                    DeductMemberWallet(in["member_id"].Long(), wallet_id,in["amount"].Long() + in["fee"].Long(), payment_id);
                    char confirmation[15] = "";
                    Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the offer code directly in that call
                    x["flags"] =  FLAG_OK; x["flags"].set_valid( true );
                    x["payment_id"] = payment_id;  x["payment_id"].set_valid( true );
                    pgsql_exec("UPDATE members_payments SET flags = %lu WHERE id = %lu",x["flags"].Long(),payment_id );
                    load_db_record( out, "SELECT * FROM members_payments WHERE id = %lu ", payment_id );
                    ret = PHP_CREATED_OK;

                } else {
                    out["status"] = "Unable to create payment";
                }


	} catch (bad_parameter) {
		logfmt(logINFO, "ERROR CALL long WrenchSendMoneyPayment(CVars in, CVars &out)");
	}


	logfmt( logINFO, "/WrenchSendMoneyPayment()" );	
	return ret;
}

//******************************************************************************
