// Topup management toosl
#include "clog.h"
#include "cgi.h"
#include "input.h"
#include "mermsemr_api.h"
#include "safestring.h"
#include <string>
#include "pgsql.h"
#include "pgsql_wrapper.h"
#include <curl/curl.h>
#include "medTEmails.h"

/* -- */
#include "function_members.h"
#include "payments.h"
#include "creditcards.h"
#include "stripe_charge.h"
#include "function_members.h"

long PaymentData(CVars in, CVars &out);

long kleenConfirmPickup(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    try {

        REQ_LONG(in, "member_id", 0, -1);
        REQ_STRING(in, "sessionid", 2, 100, "(.*)");
        REQ_LONG(in, "service_id", 0, -1);
        REQ_LONG(in, "paymentid", 0, -1);
        
      
      
        CVars x, y, z;
        in["what"] = WHAT_PICKUP_INITIALPAYMENT;
        long payment_id = PaymentData(in, out);

        logfmt(logINFO, "***~~~~kleenConfirmPickup(CVars in, CVars &out) = %lu", payment_id);

        if (payment_id > 0) {
            in["payment_id"] = payment_id;
            in["payment_id"].set_valid(true);
            long chgret = stripe_charge_member_paymentid(in, out);

            if (chgret == PHP_API_OK) {
                ret = PHP_API_OK;
                logfmt(logINFO, "***~~~~REQUEST-CONFIRMED-EMAIL START******");
                in["payment_return"] = ret;
                member_email_calls(in["action"].Long(), in, out);
                alert_email_calls(in["action"].Long(), in, out);
                load_db_record(out, "SELECT s.id AS service_id,s.*,p.*,a.agent_name FROM members_service_request s "
                        " LEFT JOIN payment p ON p.id=s.payment_id LEFT JOIN agents a ON a.id = s.agent_id"
                        " WHERE p.id  = %lu", payment_id);

                medTrMemberServiceById(out, out); // needed more information in the out 

            } else {
                in["payment_return"] = ret;
                member_email_calls(in["action"].Long(), in, out);
                alert_email_calls(in["action"].Long(), in, out);
            }

        }


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

long medTVerifyPaymentType(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[20];
    try {
        REQ_LONG(in, "paymenttype", 0, -1);
        REQ_LONG(in, "member_id", 0, -1);

        switch (in["paymenttype"].Long()) {

            case NEW_CARD:

                REQ_STRING(in, "cardnumber", 10, 17, "(.*)");
                REQ_LONG(in, "exp_month", 0, -1);
                REQ_LONG(in, "exp_year", 0, -1);
                REQ_LONG(in, "cvc", 0, -1);

                ret = PHP_API_OK;
                break;

            case EXISTING_CARD:
                REQ_LONG(in, "paymentid", 0, -1); // now we have to make sure the payment id is valid for this customer

                break;

            case ACH1:
                out["error_status"] = "Not Implemented yet";

                break;

            case ACH2:
                out["error_status"] = "Not Implemented yet";

                break;

            case BALANCE:
                out["error_status"] = "Not Implemented yet";

                break;

            case INSURANCE:
                out["error_status"] = "Not Implemented yet";
                break;

            case INVOICED:
                const PGresult *res = pgsql_query("SELECT * FROM members WHERE invoiced =1 AND id=%lu", in["member_id"].Long());
                if (res != NULL && pgsql_num_rows(res) > 0) {
                    ret = PHP_API_OK;
                } else {
                    out["error_status"] = "user not authorized to use invoice";
                }
                break;

        }

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

long medTConductInitialPayment(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[20];
    try {
        REQ_LONG(in, "paymenttype", 0, -1);
        REQ_LONG(in, "member_id", 0, -1);

        switch (in["paymenttype"].Long()) {

            case NEW_CARD:
                // this is new card - add card to table  - note active = 1 but status = 3
                REQ_STRING(in, "cardnumber", 10, 17, "(.*)");
                REQ_LONG(in, "exp_month", 0, -1);
                REQ_LONG(in, "exp_year", 0, -1);
                REQ_LONG(in, "cvc", 0, -1);
                // load othr paramameters with member id on memabers 

                save_creditcard(in, out);



                ret = PHP_API_OK;
                break;

            case EXISTING_CARD:
                REQ_LONG(in, "paymentid", 0, -1); // now we have to make sure the payment id is valid for this customer

                break;

            case ACH1:
                out["error_status"] = "Not Implemented yet";

                break;

            case ACH2:
                out["error_status"] = "Not Implemented yet";

                break;

            case BALANCE:
                out["error_status"] = "Not Implemented yet";

                break;

            case INSURANCE:
                out["error_status"] = "Not Implemented yet";
                break;

            case INVOICED:
                const PGresult *res = pgsql_query("SELECT * FROM members WHERE invoiced =1 AND id= %lu", in["member_id"].Long());
                if (res != NULL && pgsql_num_rows(res) > 0) {
                    ret = PHP_API_OK;
                } else {
                    out["error_status"] = "user not authorized to use invoice";
                }
                break;

        }

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

long PaymentData(CVars in, CVars &out) {
    logfmt(FLOG_MAX, "long PaymentData(CVars in, CVars &out)");
    long payment_id = 0;

    //  pgsql_exec("INSERT INTO payment ( uid,what,location,amount,fee,status,flags,pid,account_id,partner_id, approval_code) VALUES (%lu,%d,'%s',%lu,%lu,%d,%d,%lu,%lu,%lu, %lu)",
    //        uid, what, getenv("REMOTE_ADDR"), amount, fee, CORE_INIT, initial_flags, pid,
    //       account_id, pid_verisign, in["approval_code"].Long());
    try {
        REQ_LONG(in, "member_id", 0, -1);
        REQ_LONG(in, "service_id", 0, -1);
        long what = REQ_LONG(in, "what", 0, -1);
        if (load_db_record(out, "SELECT b.member_id,a.firstname,a.lastname,b.street1,b.street2,b.city,b.zipcode AS postal,b.state,b.country FROM members a, members_profile b WHERE a.id=%lu AND b.member_id=a.id", in["member_id"].Long()) > 0) {

            if (load_db_record(out, "SELECT member_id,est_cost AS amount FROM members_service_request WHERE id = %lu", in["service_id"].Long()) > 0) {


                CVars v;

                v["member_id"] = in["member_id"];
                v["what"] = what;
                v["location"] = getenv("REMOTE_ADDR");
                v["amount"] = out["amount"];
                v["fee"] = "0";
                v["status"] = CORE_INIT;
                v["account_id"] = in["paymentid"];
                v["member_id"] = in["member_id"];
                v["partner_id"] = PARTNER_STRIPE;
                v["pid"] = "100";



                v["member_id"].set_valid(true);
                v["what"].set_valid(true);
                v["location"].set_valid(true);
                v["amount"].set_valid(true);
                v["fee"].set_valid(true);
                v["status"].set_valid(true);
                v["pid"].set_valid(true);
                v["account_id"].set_valid(true);
                v["partner_id"].set_valid(true);
                //  v["approval_code"].set_valid(true);



                out["payment_id"] = insert_db_record(DBS_VALID, "payment", "payment_id_seq", v);
                payment_id = out["payment_id"].Long();

            }




        } else {
            logfmt(FLOG_MAX, "No member data loaded!");
            throw bad_parameter(in, "member_id");
        }
    } catch (bad_parameter) {
        payment_id = PHP_API_BAD_PARAM;
    }
    return payment_id;
}
void GenerateConfirmationSeed(char * number, int sz, int seed);

void GenerateConfirmationSeed(char * number, int sz, int seed) {
    char chars[] = "WRB01234WRB56789WRB";
    int n = sizeof (chars);
    int i;
    /*
            time_t t;
            time( &t );
            pid_t pid = getpid();

            srand(t+pid);
     */
    srand((unsigned int) time((time_t *) NULL));

    for (i = 0; i < 10 && i < sz - 1; i++) {
        int k = seed % n;
        if (seed > 1 && k == i) {
            number[i] = chars[n - k];
        } else {
            number[i] = chars[ (int) ((n - 1.0) * rand() / (RAND_MAX + 1.0)) ];
        }
    }
    number[i] = 0;
}

void Confirmation(unsigned long payment_id, char * number, int sz) {
    SQLINTEGER rows;
    char confirmation[11];

    // Lock table to prevent generation of two identical confirmation numbers
    pgsql_exec("BEGIN; LOCK TABLE payment;");
    int i = 0;
    do {
        GenerateConfirmationSeed(confirmation, sizeof (confirmation), i++);

        //st.CloseCursor();
        rows = 0;
        const PGresult *res = pgsql_query("SELECT id FROM payment WHERE confirmation='%s'", confirmation);
        if (res != NULL) {
            rows = pgsql_num_rows(res);
        }
    } while (rows > 0 && i < 100);

    pgsql_exec("UPDATE payment SET confirmation='%s', dt_confirmed=now() WHERE id=%lu", confirmation, payment_id);
    pgsql_exec("COMMIT"); // Unlock table 'data'
    strsafecpy(number, confirmation, sz);
}

/*
 * 
 * 
 utransport=> \d payment
payment                            payment_agents_concierge_id_key    payment_agents_translators         payment_agents_translators_id_seq  payment_agents_transport_id_key    payment_data                       payment_data_pkey                  payment_pkey                       
payment_agents_concierge           payment_agents_concierge_id_seq    payment_agents_translators_id_key  payment_agents_transport           payment_agents_transport_id_seq    payment_data_id_seq                payment_id_seq                     
utransport=> \d payment
                                      Table "public.payment"
    Column     |            Type             |                      Modifiers                       
----------------+-----------------------------+------------------------------------------------------
id             | integer                     | not null default nextval('payment_id_seq'::regclass)
member_id      | integer                     | 
what           | integer                     | 
location       | inet                        | 
time           | timestamp with time zone    | default now()
amount         | integer                     | 
fee            | integer                     | default 0
status         | integer                     | 
flags          | integer                     | 
confirmation   | character varying(10)       | 
pid            | integer                     | 
random         | integer                     | 
account_id     | integer                     | 
partner_id     | integer                     | 
dt_cancelled   | timestamp without time zone | 
dt_confirmed   | timestamp with time zone    | 
approval_code  | integer                     | default 0
target_partner | integer                     | default 0
bal_prev       | integer                     | default 0
bal_final      | integer                     | default 0
Indexes:
   "payment_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
   "payment_member_id_fkey" FOREIGN KEY (member_id) REFERENCES members(id)
Referenced by:
   TABLE "payment_data" CONSTRAINT "payment_data_payment_id_fkey" FOREIGN KEY (payment_id) REFERENCES payment(id)

utransport=> 
utransport=> 
utransport=> 

 */
