/*
General Header
ChiefSoft September 2017
 */
#include "clog.h"
#include "cgi.h"
#include "input.h"
#include "jubabox_api.h"
#include "safestring.h"
#include <string>
#include "pgsql.h"
#include "pgsql_wrapper.h"
#include "cfg.h"
#include <curl/curl.h>
/*
Other Headers
 */
#include "stripe.h"
#include "payments.h"
#include "medTEmails.h"

long stripe_save_card(CVars in, CVars &out) {
    logfmt(logINFO, "stripe_save_card()");
    long res, card_id = 0;
    char token[64], customer[64], card[64];
    const char *stripe_key = CfgReadChar("stripe.secret_key");
    if (load_db_record(out, "SELECT stripe_customer_id,email FROM members WHERE id = %lu ", in["member_id"].Long()) && out["stripe_customer_id"].length() > 0) {
        // Existing stripe account
        logfmt(logINFO, "stripe_customer_id=%s", out["stripe_customer_id"].c_str());
        snprintf(customer, sizeof (customer), "%s", out["stripe_customer_id"].c_str());
        // Tokenize card
        bzero(token, sizeof (token));
        res = stripe_tokenize_card(
                stripe_key,
                in["card"].c_str(),
                in["expiration_month"].c_str(),
                in["expiration_year"].c_str(),
                in["cvv2"].c_str(),
                token,
                sizeof (token)
                );
        remove_all_chars(token, '"');
        logfmt(logINFO, "stripe_tokenize_card(%ld)=%s\n", res, token);
        // Create a card
        if (res == 0L) {
            bzero(card, sizeof (card));
            res = stripe_create_card(
                    stripe_key,
                    customer,
                    token,
                    card,
                    sizeof (card));
            remove_all_chars(card, '"');
            logfmt(logINFO, "stripe_create_card(%ld)=%s\n", res, card);
            if (res == 0L) {
                // Save card into our DB
                in["stripe_card_id"] = card;
                in["stripe_card_id"].set_valid();
                in["card"].set_valid(false);
                in["cvv2"].set_valid(false);
                in["description"] = stripe_get_card_type(in["card"].c_str());
                in["description"].set_valid();
                card_id = insert_db_record(DBS_VALID, "creditcard", "creditcard_id_seq", in);
                if (card_id > 0) {
                    out["card_id"]=card_id;
                    out["result"] = "Card was saved successfully";
                    member_email_calls(JUBABOX_BKO_ADDCARD, out, out);
                } else {
                     out["card_id"]="0";
                    out["result"] = "Failed to save card";
                    member_email_calls(JUBABOX_BKO_ADDCARD, out, out);
                }
            } else {
                out["result"] = "Failed to create card with stripe";
            }
        } else {
            out["result"] = "Failed to tokenize card";
            logfmt(FLOG_MAX, out["result"].c_str());
        }
    } else if (out["email"].length() > 0) {
        // Tokenize card
        bzero(token, sizeof (token));
        res = stripe_tokenize_card(
                stripe_key,
                in["card"].c_str(),
                in["expiration_month"].c_str(),
                in["expiration_year"].c_str(),
                in["cvv2"].c_str(),
                token,
                sizeof (token)
                );
        remove_all_chars(token, '"');
        logfmt(logINFO, "stripe_tokenize_card(%ld)=%s\n", res, token);
        // Create customer
        if (res == 0L) {
            bzero(customer, sizeof (customer));
            res = stripe_create_customer(
                    stripe_key,
                    token,
                    out["email"].c_str(),
                    in["description"].c_str(),
                    in["member_id"].c_str(),
                    customer,
                    sizeof (customer));
            remove_all_chars(customer, '"');
            logfmt(logINFO, "stripe_create_customer(%ld)=%s\n", res, customer);
            if (res == 0L) {
                out["customer"] = customer;
                if (pgsql_exec("UPDATE members SET stripe_customer_id='%s' WHERE id=%ld", customer, in["member_id"].Long()) > 0) {
                    // Get card ID
                    bzero(card, sizeof (card));
                    res = stripe_get_card(
                            stripe_key,
                            customer,
                            in["digits"].c_str(),
                            in["expiration_month"].c_str(),
                            in["expiration_year"].c_str(),
                            card,
                            sizeof (card));
                    remove_all_chars(card, '"');
                    logfmt(logINFO, "@here stripe_get_card(%ld)=%s\n", res, card);
                    if (res == 0L) {
                        // Save card into our DB
                        in["stripe_card_id"] = card;
                        in["stripe_card_id"].set_valid();
                        in["card"].set_valid(false);
                        in["cvv2"].set_valid(false);
                        in["description"] = stripe_get_card_type(in["card"].c_str());
                        in["description"].set_valid();
                        card_id = insert_db_record(DBS_VALID, "creditcard", "creditcard_id_seq", in);
                        if (card_id > 0) {
                            out["card_id"] = card_id;
                            out["result"] = "Card was saved successfully";
                            member_email_calls(JUBABOX_BKO_ADDCARD, out, out);
                        } else {
                            out["card_id"] = "0";
                            out["result"] = "Failed to save card";
                            member_email_calls(JUBABOX_BKO_ADDCARD, out, out);
                        }
                    } else {
                        out["result"] = "Failed to get card stripe ID";
                    }
                } else {
                    out["result"] = "Failed to save customer stripe ID";
                }
            } else {
                out["result"] = "Failed to create stripe customer";
            }
        } else {
            out["result"] = "Failed to tokenize card";
        }
    } else {
        out["result"] = "Failed to load customer";
    }
    logfmt(logINFO, "/stripe_save_card()");
    return card_id;
}

long stripe_one_time_charge(CVars in, CVars &out) {
    logfmt(logINFO, "stripe_charge()");
    out["result"] = "stripe_charge() call in progress...";
    long res, ret = PHP_API_BAD_PARAM;
    char token[256], id[256];
    const char *stripe_key = CfgReadChar("stripe.secret_key");
    //logfmt( logINFO, "stripe_key=%s", stripe_key );
    try {
        REQ_STRING(in, "ccnum", 12, 16, "(.*)");
        REQ_STRING(in, "ccexpm", 2, 2, "(.*)");
        REQ_STRING(in, "ccexpy", 2, 2, "(.*)");
        REQ_STRING(in, "cccvc", 3, 5, "(.*)");
        long amount = REQ_LONG(in, "amount", 1, -1);
        const char * loc = getenv("REMOTE_ADDR");

        res = stripe_tokenize_card(
                stripe_key,
                in["ccnum"].c_str(),
                in["ccexpm"].c_str(),
                in["ccexpy"].c_str(),
                in["cccvc"].c_str(),
                token,
                sizeof (token));

        remove_all_chars(token, '"');

        logfmt(logINFO, "stripe_tokenize_card(%ld)=%s\n", res, token);
        if (res == 0L) {
            char *currency = "usd";
            char *description = "Example charge";
            char *metadata = "6735";
            bzero(id, sizeof (id));
            res = stripe_charge_token(
                    stripe_key,
                    token,
                    amount,
                    currency,
                    description,
                    metadata,
                    id, sizeof (id));
            remove_all_chars(id, '"');
            logfmt(logINFO, "stripe_charge_token(%ld)=%s\n", res, id);
            if (res == 0L) {
                logfmt(logINFO, "Processed charge: %s\n", token);
                ret = PHP_API_OK;
                out["result"] = "Charge success";
                out["id"] = id;
            } else {
                out["result"] = "Charge failed";
                out["id"] = "";
            }
        } else {
            out["result"] = "Failed to tokenize card";
        }
    } catch (bad_parameter) {
        out["result"] = "Bad parameter";
        logfmt(logINFO, "ERROR CALL long strip_charge(CVars in, CVars &out)");
    }
    
    out["payment_return"] = ret;
    logfmt(logINFO, "/stripe_charge()");
    return ret;
}

long stripe_new_customer_charge(CVars in, CVars &out) {
    logfmt(logINFO, "stripe_new_customer_charge()");
    out["result"] = "stripe_new_customer_charge() call in progress...";
    long res, ret = PHP_API_BAD_PARAM;
    char token[64], customer[64], id[64];
    const char *stripe_key = CfgReadChar("stripe.secret_key");
    //logfmt( logINFO, "stripe_key=%s", stripe_key );
    try {
        REQ_STRING(in, "ccnum", 12, 16, "(.*)");
        REQ_STRING(in, "ccexpm", 2, 2, "(.*)");
        REQ_STRING(in, "ccexpy", 2, 2, "(.*)");
        REQ_STRING(in, "cccvc", 3, 5, "(.*)");
        long amount = REQ_LONG(in, "amount", 1, -1);
        long customer_id = REQ_LONG(in, "customer_id", 1, -1);
        REQ_STRING(in, "email", 6, 64, "(.*)");
        REQ_STRING(in, "description", 1, 64, "(.*)");
        const char * loc = getenv("REMOTE_ADDR");

        bzero(token, sizeof (token));
        res = stripe_tokenize_card(
                stripe_key,
                in["ccnum"].c_str(),
                in["ccexpm"].c_str(),
                in["ccexpy"].c_str(),
                in["cccvc"].c_str(),
                token,
                sizeof (token));
        remove_all_chars(token, '"');
        logfmt(logINFO, "stripe_tokenize_card(%ld)=%s\n", res, token);
        if (res == 0L) {
            bzero(customer, sizeof (customer));
            res = stripe_create_customer(
                    stripe_key,
                    token,
                    in["email"].c_str(),
                    in["description"].c_str(),
                    in["customer_id"].c_str(),
                    customer,
                    sizeof (customer));
            remove_all_chars(customer, '"');
            logfmt(logINFO, "stripe_create_customer(%ld)=%s\n", res, customer);
            if (res == 0L) {
                out["customer"] = customer;
                char *currency = "usd";
                char *description = "Example charge";
                char *metadata = "6735";
                bzero(id, sizeof (id));
                res = stripe_charge_customer(
                        stripe_key,
                        customer,
                        amount,
                        currency,
                        description,
                        metadata,
                        id,
                        sizeof (id));
                remove_all_chars(id, '"');
                logfmt(logINFO, "stripe_charge_customer(%ld)=%s\n", res, id);
                if (res == 0L) {
                    logfmt(logINFO, "Processed charge: %s\n", id);
                    ret = PHP_API_OK;
                    out["id"] = id;
                    out["result"] = "Charge success";
                } else {
                    out["result"] = "Charge failed";
                }
            } else {
                out["result"] = "Create customer failed";
            }
        } else {
            out["result"] = "Failed to tokenize card";
        }
    } catch (bad_parameter) {
        out["result"] = "Bad parameter";
        logfmt(logINFO, "ERROR CALL long strip_charge(CVars in, CVars &out)");
    }
    
    out["payment_return"] = ret;
    logfmt(logINFO, "/stripe_charge()");
    return ret;
}

long stripe_charge_member_paymentid(CVars in, CVars &out) {
    logfmt(logINFO, "stripe_charge_member_paymentid()");
    out["result"] = "stripe_charge_member_paymentid() call in progress...";
    long res, ret = PHP_API_BAD_PARAM;


    try {
        REQ_LONG(in, "service_id", 0, -1);
        REQ_LONG(in, "member_id", 0, -1);
        long payment_id  = REQ_LONG(in, "payment_id", 0, -1);


        char id[64], customer[64], data[64];
        const char *stripe_key = CfgReadChar("stripe.secret_key");

        if (load_db_record(in, "SELECT *,account_id AS card_id , id AS payment_id FROM payment WHERE id = %lu", in["payment_id"].Long()) > 0) {

        } else {

        }

        if (load_db_record(in, "SELECT *,id AS service_id  FROM members_service_request WHERE id = %lu AND dt_confirmed IS NULL", in["service_id"].Long()) > 0) {

        } else {
             out["result"] = "Failed : Duplicate Detected";
            return ret;
        }
        in["description"] = "Laundry Pickup";
        in["invoice_id"] = in["payment_id"];


        if (load_db_record(out, "SELECT stripe_customer_id FROM members WHERE id=%lu AND stripe_customer_id IS NOT NULL", in["member_id"].Long()) > 0) {
            if (load_db_record(out, "SELECT stripe_card_id,currency FROM creditcard WHERE id=%lu AND member_id=%lu AND stripe_card_id IS NOT NULL", in["card_id"].Long(), in["member_id"].Long()) > 0) {
                // Set card as a default funding source
                const char *entity = "default_source";
                snprintf(customer, sizeof (customer), "%s", out["stripe_customer_id"].c_str());
                bzero(data, sizeof (data));
                res = stripe_update_customer(stripe_key, customer, entity, out["stripe_card_id"].c_str(), entity, data, sizeof (data));
                remove_all_chars(data, '"');
                if (res == 0L && out["stripe_card_id"].compare(data) == 0) {
                    // charge customer
                    char *metadata = "6735";
                    bzero(id, sizeof (id));
                    res = stripe_charge_customer(
                            stripe_key,
                            customer,
                            in["amount"].Long(),
                            out["currency"].c_str(),
                            in["description"].c_str(),
                            in["invoice_id"].c_str(),
                            id,
                            sizeof (id));
                    remove_all_chars(id, '"');
                    logfmt(logINFO, "stripe_charge_member_paymentid(%ld)=%s\n", res, id);
                    if (res == 0L) {
                        logfmt(logINFO, "Processed charge: %s\n", id);
                         char confirmation[15] = "";
			Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the payment confirmation
                        
                        ret = PHP_API_OK;
                        out["id"] = id;                        
                        pgsql_exec("UPDATE payment SET stripe_confirm='%s',dt_confirmed=now() WHERE id = %lu", id, payment_id);
                        pgsql_exec("UPDATE members_service_request SET payment_id=%lu,dt_confirmed=now(),flags=%lu WHERE id = %lu",payment_id, CONFIRMED , in["service_id"].Long());

                        out["result"] = "Charge success";
                    } else {
                        out["result"] = "Charge failed";
                    }
                } else {
                    out["result"] = "Failed to set customer default funding source";
                }
            } else {
                out["result"] = "Failed to load stripe card ID";
            }
        } else {
            out["result"] = "Failed to load stripe customer ID";
        }

    }    catch (bad_parameter) {
        logfmt(logINFO, "ERROR CALL long stripe_charge_member_paymentid(CVars in, CVars &out)");
    }
    
    out["payment_return"] = ret;

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


long stripe_charge_member(CVars in, CVars &out) {
    logfmt(logINFO, "stripe_charge_member()");
    out["result"] = "stripe_charge_member() call in progress...";
    long res, ret = PHP_API_BAD_PARAM;
    char id[64], customer[64], data[64];
    const char *stripe_key = CfgReadChar("stripe.secret_key");

    if (load_db_record(out, "SELECT stripe_customer_id FROM members WHERE id=%lu AND stripe_customer_id IS NOT NULL", in["member_id"].Long()) > 0) {
        if (load_db_record(out, "SELECT stripe_card_id FROM creditcard WHERE id=%lu AND member_id=%lu AND stripe_card_id IS NOT NULL", in["card_id"].Long(), in["member_id"].Long()) > 0) {
            // Set card as a default funding source
            const char *entity = "default_source";
            snprintf(customer, sizeof (customer), "%s", out["stripe_customer_id"].c_str());
            bzero(data, sizeof (data));
            res = stripe_update_customer(stripe_key, customer, entity, out["stripe_card_id"].c_str(), entity, data, sizeof (data));
            remove_all_chars(data, '"');
            if (res == 0L && out["stripe_card_id"].compare(data) == 0) {
                // charge customer
                char *metadata = "6735";
                bzero(id, sizeof (id));
                res = stripe_charge_customer(
                        stripe_key,
                        customer,
                        in["amount"].Long(),
                        in["currency"].c_str(),
                        in["description"].c_str(),
                        in["invoice_id"].c_str(),
                        id,
                        sizeof (id));
                remove_all_chars(id, '"');
                logfmt(logINFO, "stripe_charge_customer(%ld)=%s\n", res, id);
                if (res == 0L) {
                    logfmt(logINFO, "Processed charge: %s\n", id);
                   //  char confirmation[15] = "";
	          //   Confirmation(payment_id, confirmation, sizeof (confirmation)); // this stamp the payment confirmation
                    
                    
                    ret = PHP_API_OK;
                    out["id"] = id;
                    out["result"] = "Charge success";
                } else {
                    out["result"] = "Charge failed";
                }
            } else {
                out["result"] = "Failed to set customer default funding source";
            }
        } else {
            out["result"] = "Failed to load stripe card ID";
        }
    } else {
        out["result"] = "Failed to load stripe customer ID";
    }
    
    out["payment_return"] = ret;
    logfmt(logINFO, "/stripe_charge_member()");
    return ret;
}

/*
vi:ts=2
 */

