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


long jobs_calls(CVars in, CVars &out) {
    logfmt(logINFO, "jobs_calls()");
    out["result"] = "YES I GET TO BACK END";
    long action = REQ_LONG(in, "action", 0, -1);
    long job_mode = 0;
    logfmt(logINFO, "jobs_calls() action=%lu",action);
    switch (action) {
        case WRENCHBOARD_JOB_POSTAGREE:
            return WrenchJobPostAgree(in, out);
        break;
        case WRENCHBOARD_JOB_LISTJOBS:
            return WrenchJobManagerList(in, out);
            break;
        case WRENCHBOARD_JOB_JOBFILES:
             logfmt(logINFO, "jobs_calls() ~~WRENCHBOARD_JOB_JOBFILES~~ action=%lu",action);
              return WrenchJobListFiles(in, out);
            break;
        case WRENCHBOARD_JOB_OFFERS:
            return WrenchJobManagerOffers(in, out);
            break;
        case WRENCHBOARD_JOB_ACTIVE: //
            return WrenchJobManagerActiveTasksList(in, out);
            break;

        case WRENCHBOARD_JOB_USERACTIVE:
            in["recent_past_due"] ="0";  in["recent_past_due"].set_valid( true );
            return WrenchUsersActiveTasksList( in, out);
            break;
        case WRENCHBOARD_JOB_RECENTPASTDUE:
             in["recent_past_due"] ="100";  in["recent_past_due"].set_valid( true );
             return WrenchUsersActiveTasksList( in, out);
             break;
        case WRENCHBOARD_JOB_REPORT:
            return WrenchUsersTasksReportList( in, out);
            break;
        case WRENCHBOARD_JOB_CREATEJOB:
            job_mode = REQ_LONG(in, "job_mode", 1, -1);
             switch(job_mode){
                 case ADD_JOB:
                     return WrenchCreateJobs(in, out);
                 break;
                 case UPDATE_JOB:
                     return  WrenchEditJobs(in, out);
                 break;
         		}
            break;
        case WRENCHBOARD_JOB_DELETEJOB:
            return WrenchDeleteJobs(in, out);
            break;
        case WRENCHBOARD_JOB_GROUP_MEMBER:
            return WrenchAddJobsGroupMember(in, out);
            break;

        case WRENCHBOARD_JOB_CREATE_GROUP:
            return WrenchCreateJobsGroup(in, out);
            break;

        case WRENCHBOARD_JOB_DELETE_GROUP:
            return WrenchDeleteJobsGroup(in, out);
            break;

        case WRENCHBOARD_JOB_DELETE_GROUPMEMBER:
            return WrenchDeleteJobsGroupMember(in, out);
            break;

        case WRENCHBOARD_JOB_OFFER_SYSTEM:
             return WrenchJobOfferSystems(in, out);
        break;

        case WRENCHBOARD_JOB_OFFER_FAMILY:

        break;

        case WRENCHBOARD_JOB_OFFER_INDVI:
              return WrenchSendJobsOfferIndividual(in, out);
            break;

        case WRENCHBOARD_JOB_OFFER_GROUP:
            return WrenchSendJobsOfferGroup(in, out);
            break;

        case WRENCHBOARD_JOB_OFFER_PUBLIC:
            return WrenchSendJobsOfferPublic(in, out);
            break;

        case WRENCHBOARD_JOB_OFFER_CONCLUDE:
            return WrenchConcludeJobsOffer(in, out);
            break;

        case WRENCHBOARD_JOB_OFFER_INTLIST:
            return  WrenchJobsOfferInterestList(in, out);  // people looking at your job
            break;

        case WRENCHBOARD_JOB_WAITING_INT: // waiting interest
            return  WrenchUserJobsInterestList(in, out);  // me looking at your job
            break;

        case WRENCHBOARD_JOB_SEND_INTEREST:
            return WrenchJobsOfferInterest(in, out);
            break;

        case WRENCHBOARD_JOB_STATS_INTEREST:
             return  WrenchJobsInterestStats(in, out);
        break;

        case WRENCHBOARD_JOB_PROC_INTEREST:
            return WrenchJobsProcessInterest(in, out);
            break;

        case WRENCHBOARD_JOB_SEND_QUESTION:
            return WrenchJobsQuestion(in, out);
            break;

        case WRENCHBOARD_JOB_MRKTINT_QUEST:
            return WrenchMarketInterestQuestion(in, out);
            break;

        case WRENCHBOARD_JOB_INT_QUESTLST:
             return WrenchMarketInterestQuestionList(in, out);
             break;

        case WRENCHBOARD_JOB_REPLY_QUESTION:
            return WrenchReplyMessage(in, out);
            break;

        case WRENCHBOARD_JOB_EXTEND_EXPIRE:
            return WrenchJobPostExtendTime(in, out);
            break;

        case WRENCHBOARD_JOB_RESEND_MESSAGE:
            return WrenchJobPostNotifyOffer(in, out);
            break;

        case WRENCHBOARD_JOB_CANCEL_OFFER:
            return WrenchJobPostCancelOffer(in, out);
           break;

        case  WRENCHBOARD_JOB_JOBGROUPS:   //       13045
            return WrenchJobsGroupList(in, out);
           break;

        case  WRENCHBOARD_JOB_JOBGROUPADD:

           break;

    }
    logfmt(logINFO, "/jobs_calls()");
    return 0;
}

long WrenchJobOfferSystems(CVars in, CVars &out){
  long ret = PHP_API_BAD_PARAM;
    try {
        long assign_mode = REQ_LONG(in, "assign_mode", 1, -1);

            switch(assign_mode){
                case ASSIGN_MODE_MEDIA_FAMILY:
                   logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_MEDIA_FAMILY");
                   return WrenchSendMediaOfferFamily(in, out);
                break;
                case ASSIGN_MODE_FAMILY:
                   logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_FAMILY");
                   return WrenchSendJobsOfferFamily(in, out);
                break;
                case ASSIGN_MODE_CREATEASSIGN:
                  logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_CREATEASSIGN");
                  return WrenchSendJobsOfferCreateAssign(in, out);
                break;
                case ASSIGN_MODE_INDIVIDUAL:
                   logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_INDIVIDUAL");
                  return WrenchSendJobsOfferPublic(in, out);
                break;
                case ASSIGN_MODE_EMAIL:
                    logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_EMAIL");
                    return WrenchSendJobsOfferIndividual(in, out);
                break;
                case ASSIGN_MODE_GROUP:
                   logfmt(logINFO, "WrenchJobOfferSystems()->ASSIGN_MODE_GROUP");
                   return WrenchSendJobsOfferGroup(in, out);
                break;
            }
    } catch (bad_parameter) {
        out["log_status"] = "error...";
    }
    return ret;
}

long WrenchSendJobsOfferCreateAssign(CVars in, CVars &out){
    logfmt(logINFO, "******* ~~~~ WrenchSendJobsOfferCreateAssign()");
    long ret = PHP_API_BAD_PARAM;
    try {
        CVars xx;
        long member_id  = REQ_LONG(in, "member_id", 1, -1);
       // REQ_LONG(in, "job_id", 1, -1);
       // REQ_STRING(in, "job_uid", 1, 59, "(.*)");
        REQ_STRING(in, "family_uid", 1, 59, "(.*)");
       // REQ_STRING(in, "job_description", 1, 5500, "(.*)");
        if ( WrenchCreateJobs(in, xx) ==  PHP_CREATED_OK ){
            in["job_id"] = xx["job_id"];  xx["job_id"].set_valid( true );
            in["job_uid"] = xx["job_uid"];  xx["job_uid"].set_valid( true );
            in["job_description"] = xx["job_detail"]; xx["job_description"].set_valid( true );

            // UPDATE THE JOB TO FAMILY MODE - This is a family job
            pgsql_exec("UPDATE members_jobs SET job_mode = 'FAMILY' WHERE id = %lu AND uid = '%s' ",in["job_id"].Long(), in["job_uid"].c_str());

            ret =  WrenchSendJobsOfferFamily(in, out);
        }
    } catch (bad_parameter) {
        out["log_status"] = "error...";
    }
    logfmt(logINFO, "/******* ~~~~ WrenchSendJobsOfferCreateAssign()");
    return ret;
}

long WrenchJobPostExtendTime(CVars in, CVars &out){
    long ret = PHP_API_BAD_PARAM;
    try {
        out["status"] = "Started";
        long member_id = REQ_LONG(in, "member_id", 1, -1);
        long extend_days = REQ_LONG(in, "extend_days", 1, -1);
        REQ_STRING(in, "job_uid", 1, 55, "(.*)"); //offer_code
        REQ_STRING(in, "offer_code", 1, 15, "(.*)"); //offer_code

        const PGresult *res = pgsql_query("SELECT id AS offer_id FROM members_jobs_offer WHERE offer_code = '%s' AND member_id=%lu AND status =1", in["offer_code"].c_str(),member_id);
        if (res != NULL && pgsql_num_rows(res) > 0) {
            map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
            if (!f.empty()) {
                CVars rec;
                map_to_cvars(f, rec);
                pgsql_exec("UPDATE members_jobs_offer SET expire = now() + '%lu days()' WHERE offer_code = '%s' AND member_id=%lu AND status =1",extend_days, in["offer_code"].c_str(),member_id);
                out["status"] = "Completed";
                out["status_msg"] = "offer_expiration_data_extended";
                load_db_record(out, "SELECT expire, uid AS job_uid FROM members_jobs_offer WHERE offer_code = '%s' ", in["offer_code"].c_str());
                ret = PHP_UPDATED_OK;
            }
        }
    } catch (bad_parameter) {
        out["log_status"] = "error...";
    }
    return ret;
}

long WrenchJobPostNotifyOffer(CVars in, CVars &out){
    long ret = PHP_API_BAD_PARAM;
    try {
        out["status"] = "Started";
        long member_id = REQ_LONG(in, "member_id", 1, -1);
        long mode = REQ_LONG(in, "mode", 1, -1);
        REQ_STRING(in, "job_uid", 1, 55, "(.*)"); //offer_code
        REQ_STRING(in, "offer_code", 1, 15, "(.*)"); //offer_code

        const PGresult *res = pgsql_query("SELECT id AS offer_id FROM members_jobs_offer WHERE offer_code = '%s' AND member_id=%lu AND status =1", in["offer_code"].c_str(),member_id);
        if (res != NULL && pgsql_num_rows(res) > 0) {
            map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
            if (!f.empty()) {
              logfmt(logINFO, "******* ~~~~ WrenchJobPostNotifyOffer()");
              job_email(JOBS_OFFER_SENDTOME_MAIL, in, out); // the email will come from
              out["status"] = "Completed";
              out["status_msg"] = "offer_notification_resent";
              ret = PHP_UPDATED_OK;
            }
        }
    } catch (bad_parameter) {
        out["log_status"] = "error...";
    }
    return ret;
}

long WrenchJobPostCancelOffer(CVars in, CVars &out){
// case OFFER_CANCEL: // note status 4
 logfmt(logINFO, "WrenchJobPostCancelOffer()");
    long ret = PHP_API_BAD_PARAM;
    try {

            REQ_LONG(in, "member_id", 1, -1);
            //long offer_result = REQ_LONG(in, "offer_result", 1, -1);
            REQ_STRING(in, "offer_code", 1, 15, "(.*)");
            long job_id = 0;
            long owner_member_id = 0;
            long offer_id = 0;

            long rc = 0;
    		CVars outx;
            //  rc = 0 + load_db_record( out, "SELECT * FROM members_jobs_offer WHERE offer_code='%s' AND status = 1", in["offer_code"].c_str() );
            const PGresult *res = pgsql_query("SELECT *,member_id AS owner_member_id, id AS offer_id "
                                               " FROM members_jobs_offer WHERE offer_code='%s' AND status = 1 AND member_id = %lu", in["offer_code"].c_str(), in["member_id"].Long());
       if (res != NULL && pgsql_num_rows(res) > 0) {

            // now job is valid
            // good to continue
                map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
                if (!f.empty()) {
                    CVars rec;
                    map_to_cvars(f, rec);
                    job_id = rec["job_id"];
                    offer_id =  rec["offer_id"];
                    owner_member_id = rec["owner_member_id"];
                }

               logfmt(logINFO, "WrenchConcludeJobsOffer() rc=OFFER_CANCEL");
               if (load_db_record(out, " SELECT id AS offer_id,*,(CASE WHEN payment_id IS NULL THEN 0 ELSE payment_id END ) AS payment_id_val"
                                        " FROM members_jobs_offer WHERE offer_code ='%s' AND status = 1", in["offer_code"].c_str())) {
                   // valid load of offer needed
                   CVars y;
                   y["member_id"] = out["member_id"];
                   y["member_id"].set_valid(true);
                   y["offer_id"] = out["offer_id"];
                   y["offer_id"].set_valid(true);
                   y["code"] = "OFRFD";
                   y["code"].set_valid(true);
                   y["dir"] = DIR_SOURCE;
                   y["dir"].set_valid(true);
                   y["payment_id"] = out["payment_id_val"];
                   y["payment_id"].set_valid(true);

                  // if (WrenchRefundoffer(y, out) == PHP_CREATED_OK) {
                       pgsql_exec("UPDATE members_jobs_offer SET status = 4 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                       // REFUND THE MONEY
                       ret = PHP_CREATED_OK;
                       job_email(JOBS_OFFER_CANCEL_MAIL, y, out); // the email will come from offer table
                  // }
               }
       }
    } catch (bad_parameter) {
        out["log_status"] = "Error WrenchJobPostCancelOffer";
    }
    logfmt(logINFO, "/WrenchJobPostCancelOffer()");
    return ret;



}

long WrenchJobPostAgree(CVars in, CVars &out) {
 logfmt(logINFO, "WrenchJobPostAgree()");
    long ret = PHP_API_BAD_PARAM;
    try {
            long member_id = REQ_LONG(in, "member_id", 1, -1);
            REQ_STRING(in, "uid", 1, 500, "(.*)"); //uid
            if (load_db_record(out, "SELECT id AS member_id, * FROM members WHERE id  = %lu AND uid='%s' AND post_jobs IS NULL", in["member_id"].Long(), in["uid"].c_str()) ){
                if ( out["member_id"].Long() >   0 )
                {
                    pgsql_exec("UPDATE members SET post_jobs = now() WHERE id  = %lu AND uid='%s'", member_id, in["uid"].c_str());
                    load_db_record(out, "SELECT * FROM members WHERE id  = %lu AND uid='%s' AND post_jobs IS NOT NULL", in["member_id"].Long(), in["uid"].c_str());
                    out["status"] = "Completed";
                    out["advise"] = "Refresh Session Profile";
                    ret = PHP_CREATED_OK;
                }
                else{
                    load_db_record(out, "SELECT * FROM members WHERE id  = %lu AND uid='%s' AND post_jobs IS NOT NULL", in["member_id"].Long(), in["uid"].c_str());
                    out["advise"] = "Probably Already Set";
                    out["status"] = "Invalid Update";
                }
            }

    } catch (bad_parameter) {
        out["log_status"] = "Error WrenchJobPostAgree";
    }
    logfmt(logINFO, "/WrenchJobPostAgree()");
    return ret;
}

long WrenchUserJobsInterestList(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[30];
    out = in;
    try {
         long member_id = REQ_LONG(in, "member_id", 1, -1);
         long offset = REQ_LONG(in, "offset", 1, -1);
         long limit = REQ_LONG(in, "limit", 1, -1);

            const PGresult *res = pgsql_query("SELECT mm.id AS client_id, mm.uid AS client_uid,j.uid AS job_uid, "
            " mm.firstname AS client_name, m.offer_code, m.uid AS offer_uid, "
            " mo.member_id, mm.added::date AS client_added,  to_char(mo.added, 'Dy Mon dd, yyyy HH:MI AM') AS sent, "
            " j.title,j.description,m.job_id,to_char( m.expire, 'Dy Mon dd, yyyy HH:MI AM') AS  expire,j.price AS job_price,mo.uid AS interest_uid, "
            " c.code AS currency_code, c.description AS currency_description,j.country "
            " FROM  members_offer_interest mo  "
            " LEFT JOIN  members_jobs_offer m ON m.id = mo.offer_id "
            " LEFT JOIN members_jobs j ON j.id=m.job_id "
            " LEFT JOIN members mm ON mm.id = mo.member_id "
            " LEFT JOIN currency c ON c.country=j.country "
            " WHERE m.status = 1 AND m.client_id=0  AND mo.status = 1 "
            " AND m.expire IS NOT NULL AND m.expire> now() "
            " AND mo.member_id  = %lu AND j.status = 1  "
            " ORDER BY mo.added DESC LIMIT %lu OFFSET %lu",member_id, limit, offset);
                if (res != NULL && pgsql_num_rows(res) > 0) {

                            out["total_record"] = pgsql_num_rows(res);

                            for (int i = 0, n = pgsql_num_rows(res); i < n; i++) {
                                map<const char*, const char*>f = pgsql_fetch_assoc(res, i);
                                if (f.empty()) continue;
                                CVars rec;
                                map_to_cvars(f, rec);


                                snprintf(vname, sizeof (vname), "interest_uid_%05d", i);
                                out[vname] = rec["interest_uid"];

                                snprintf(vname, sizeof (vname), "client_id_%05d", i);
                                out[vname] = rec["client_id"];

                                snprintf(vname, sizeof (vname), "client_uid_%05d", i);
                                out[vname] = rec["client_uid"];

                                snprintf(vname, sizeof (vname), "client_name_%05d", i);
                                out[vname] = rec["client_name"];

                                snprintf(vname, sizeof (vname), "client_added_%05d", i);
                                out[vname] = rec["client_added"];

                                snprintf(vname, sizeof (vname), "client_jobs_completed_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_jobs_active_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_addedclient_jobs_missed_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_offers_pending_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_percent_completion_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_ratings_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "offer_code_%05d", i);
                                out[vname] = rec["offer_code"];

                                snprintf(vname, sizeof (vname), "offer_uid_%05d", i);
                                out[vname] = rec["offer_uid"];

                                snprintf(vname, sizeof (vname), "sent_%05d", i);
                                out[vname] = rec["sent"];

                                snprintf(vname, sizeof (vname), "title_%05d", i);
                                out[vname] = rec["title"];

                                snprintf(vname, sizeof (vname), "description_%05d", i);
                                out[vname] = rec["description"];

                                snprintf(vname, sizeof (vname), "job_id_%05d", i);
                                out[vname] = rec["job_id"];

                                snprintf(vname, sizeof (vname), "job_uid_%05d", i);
                                out[vname] = rec["job_uid"];

                                snprintf(vname, sizeof (vname), "expire_%05d", i);
                                out[vname] = rec["expire"];

                                snprintf(vname, sizeof (vname), "price_%05d", i);
                                out[vname] = rec["job_price"];

                                snprintf(vname, sizeof (vname), "job_country_%05d", i);
                                out[vname] = rec["country"];
                                snprintf(vname, sizeof (vname), "currency_%05d", i);
                                out[vname] = rec["currency_description"];
                                snprintf(vname, sizeof (vname), "currency_code_%05d", i);
                                out[vname] = rec["currency_code"];
                            }

                }
            ret = PHP_CREATED_OK;

        } catch (bad_parameter) {
            out["log_status"] = "Error WrenchJobsOfferInterestList";
        }
        return ret;

    }

long WrenchJobsInterestStats(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[30];
    float pcnt = 0;
    //out = in;

    float x = 0.61;
    char buf[10];

    try {
           out["job_completed"]        = "0";
           out["job_active"]           = "0";
           out["job_percent_complete"] = "0.0 %";
           out["job_uncompleted"]      = "0";
           out["job_rejected"]         = "0";
           out["job_pending"]          = "0";
           out["job_last_date"]          = "0000-00-00";

            REQ_STRING(in, "uid", 1, 95, "(.*)"); //uid
            REQ_STRING(in, "interest_uid", 1, 95, "(.*)"); //interest_uid
            REQ_STRING(in, "client_uid", 1, 95, "(.*)"); //client_uid

             if (load_db_record(out, "SELECT id as client_id FROM members WHERE uid::text = '%s' ", in["client_uid"].c_str())) {

                load_db_record(out, "SELECT count(id) AS job_pending FROM members_jobs_offer WHERE client_id = %lu AND expire > now()", out["client_id"].Long());  //pending jobs
                load_db_record(out, "SELECT count(id) job_active  FROM members_jobs_contract WHERE client_id = %lu AND delivery_date> now() AND status  = 1", out["client_id"].Long());  //job_active
                load_db_record(out, "SELECT delivery_date::date AS job_last_date  FROM members_jobs_contract WHERE client_id = %lu AND status =7 ORDER BY delivery_date DESC LIMIT 1", out["client_id"].Long());  //job_active

                load_db_record(out, "SELECT count(id) AS job_completed  FROM members_jobs_contract WHERE client_id = %lu AND status =7", out["client_id"].Long());  //pending jobs
                if ( out["job_completed"].Long() > 0 ){
                    load_db_record(out, "SELECT count(id) AS total_jobs  FROM members_jobs_contract WHERE client_id = %lu AND  status IN (7,4,5)", out["client_id"].Long());  //pendi

                    logfmt(logINFO, "~~~~~~~~~~~~~ *********** DIR ******************** %d", 100* out["job_completed"].Long() / out["total_jobs"].Long());

                    sprintf(buf, "%d %", 100* out["job_completed"].Long() / out["total_jobs"].Long());

                    logfmt(logINFO, "~~~~~~~~~~~~~ *********** Buf ******************** %s", buf);

                    out["job_percent_complete"] = buf;
                }

             }
           //  SELECT id as client_id FROM members WHERE uid::text = 'dfc9d601-780f-4d78-839f-422f0928f911';
           //  SELECT count(id), status FROM members_jobs_contract WHERE client_id  = 2 GROUP BY status;
            ret = PHP_CREATED_OK;
            } catch (bad_parameter) {
                out["log_status"] = "Error WrenchJobsInterestStats";
                 logfmt(logINFO, "/Error WrenchJobsInterestStats ");
            }

    return ret;
   }

long WrenchJobsOfferInterestList(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[30];
    out = in;
    try {
         long member_id = REQ_LONG(in, "member_id", 1, -1);
         long offset = REQ_LONG(in, "offset", 1, -1);
         long limit = REQ_LONG(in, "limit", 1, -1);

            const PGresult *res = pgsql_query("SELECT mm.id AS client_id, mm.uid AS client_uid, j.timeline_days, "
            " mm.firstname AS client_name, m.offer_code, m.uid AS offer_uid,j.uid AS job_uid, "
            " mo.member_id, mm.added::date AS client_added,  to_char(mo.added, 'Dy Mon dd, yyyy HH:MI AM') AS sent, "
            " j.title,j.description,m.job_id,to_char( m.expire, 'Dy Mon dd, yyyy HH:MI AM') AS  expire,j.price AS job_price,mo.uid AS interest_uid ,"
            " c.code AS currency_code, c.description AS currency_description,j.country "
            " FROM  members_offer_interest mo  "
            " LEFT JOIN members_jobs_offer m ON m.id = mo.offer_id "
            " LEFT JOIN members_jobs j ON j.id=m.job_id "
            " LEFT JOIN members mm ON mm.id = mo.member_id "
            " LEFT JOIN currency c ON c.country=j.country "
            " WHERE m.status = 1 AND m.client_id=0  AND mo.status = 1 "
            " AND m.expire IS NOT NULL AND m.expire> now() "
            " AND m.member_id  = %lu  AND j.status = 1 "
            " ORDER BY mo.added DESC LIMIT %lu OFFSET %lu",member_id, limit, offset);

                if (res != NULL && pgsql_num_rows(res) > 0) {

                            out["total_record"] = pgsql_num_rows(res);

                            for (int i = 0, n = pgsql_num_rows(res); i < n; i++) {
                                map<const char*, const char*>f = pgsql_fetch_assoc(res, i);
                                if (f.empty()) continue;
                                CVars rec;
                                map_to_cvars(f, rec);

                                snprintf(vname, sizeof (vname), "interest_uid_%05d", i);
                                out[vname] = rec["interest_uid"];

                                snprintf(vname, sizeof (vname), "timeline_days_%05d", i);
                                out[vname] = rec["timeline_days"];

                                snprintf(vname, sizeof (vname), "client_id_%05d", i);
                                out[vname] = rec["client_id"];

                                snprintf(vname, sizeof (vname), "client_uid_%05d", i);
                                out[vname] = rec["client_uid"];

                                snprintf(vname, sizeof (vname), "job_uid_%05d", i);
                                out[vname] = rec["job_uid"];

                                snprintf(vname, sizeof (vname), "client_name_%05d", i);
                                out[vname] = rec["client_name"];

                                snprintf(vname, sizeof (vname), "client_added_%05d", i);
                                out[vname] = rec["client_added"];

                                snprintf(vname, sizeof (vname), "client_jobs_completed_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_jobs_active_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_addedclient_jobs_missed_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_offers_pending_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_percent_completion_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "client_ratings_%05d", i);
                                out[vname] = "0";

                                snprintf(vname, sizeof (vname), "offer_code_%05d", i);
                                out[vname] = rec["offer_code"];

                                snprintf(vname, sizeof (vname), "offer_uid_%05d", i);
                                out[vname] = rec["offer_uid"];

                                snprintf(vname, sizeof (vname), "sent_%05d", i);
                                out[vname] = rec["sent"];

                                snprintf(vname, sizeof (vname), "title_%05d", i);
                                out[vname] = rec["title"];

                                snprintf(vname, sizeof (vname), "description_%05d", i);
                                out[vname] = rec["description"];

                                snprintf(vname, sizeof (vname), "job_id_%05d", i);
                                out[vname] = rec["job_id"];

                                snprintf(vname, sizeof (vname), "expire_%05d", i);
                                out[vname] = rec["expire"];

                                snprintf(vname, sizeof (vname), "price_%05d", i);
                                out[vname] = rec["job_price"];

                                snprintf(vname, sizeof (vname), "job_country_%05d", i);
                                out[vname] = rec["country"];
                                snprintf(vname, sizeof (vname), "currency_%05d", i);
                                out[vname] = rec["currency_description"];
                                snprintf(vname, sizeof (vname), "currency_code_%05d", i);
                                out[vname] = rec["currency_code"];

                            }

                }
            ret = PHP_CREATED_OK;

        } catch (bad_parameter) {
            out["log_status"] = "Error WrenchJobsOfferInterestList";
             logfmt(logINFO, "/Error WrenchJobsOfferInterestList");
        }
        return ret;

    }



long WrenchReplyMessage(CVars in, CVars &out) {
    long member_id = REQ_LONG(in, "member_id", 1, -1);
    long message_id = REQ_LONG(in, "message_id", 1, -1);

    REQ_STRING(in, "yourmessage", 1, 500, "(.*)"); //offer_code
    REQ_STRING(in, "memo", 1, 15, "(.*)"); //offer_code

    // read current message
    if (load_db_record(out, "SELECT * FROM members_messages WHERE id  = %lu", in["message_id"].Long())) {

        CVars x;
        x["senders_id"] = out["member_id"];
        x["senders_id"].set_valid(true);
        x["member_id"] = out["senders_id"];
        x["member_id"].set_valid(true); // note the swap - you are relying		
        x["msg"] = in["yourmessage"];
        x["msg"].set_valid(true);
        x["msg_type"] = out["msg_type"];
        x["msg_type"].set_valid(true);
        x["memo"] = out["memo"];
        x["memo"].set_valid(true);

        long msg_id = insert_db_record(DBS_VALID, "members_messages", "members_messages_id_seq", x);
        if (msg_id > 0) {
            pgsql_exec("UPDATE members_messages SET reply = now() WHERE id  = %lu", message_id);
            x["reply_id"] = msg_id;
            x["reply_id"].set_valid(true);
            job_email(WRENCHBOARD_JOB_REPLY_QUESTION, x, out);
        }
    }

    logfmt(logINFO, "/WrenchReplyMessage()");
    return 0;
}

/*

wrenchboard=> SELECT * FROM members_messages ORDER BY id DESC LIMIT 3;
 id  | member_id |           added            |                           msg                            | status | senders_id | msg_type |    memo    | reply |                 uid
-----+-----------+----------------------------+----------------------------------------------------------+--------+------------+----------+------------+-------+--------------------------------------
 172 |         4 | 2023-06-23 15:15:36.499482 | YES YES YES YES 1 2 3 4 5 6 67 7 7  5 5 5 5 5 5 76 7 7 7 |      1 |          1 | MRKTINT  | R17BX6RW87 |       | b30d993f-c92f-42c6-b272-d76c86e5789b
 171 |         4 | 2023-06-23 15:12:53.640241 | I am testing today again                                 |      1 |          1 | MRKTINT  | R17BX6RW87 |       | c7da1200-489c-47ac-923c-adfd6136dc4f
 170 |         4 | 2023-06-21 12:09:38.378594 | Testing this                                             |      1 |          1 | MRKTINT  | R17BX6RW87 |       | 342e13b7-809d-4d1a-882d-8db6e35a8703
(3 rows)

wrenchboard=>

*/
long WrenchMarketInterestQuestionList(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    char vname[30];
    out = in;
    try {
        out["status"] = "0";
        long member_id = REQ_LONG(in, "member_id", 1, -1);
        REQ_STRING(in, "offer_uid", 1, 55, "(.*)");
        REQ_STRING(in, "interest_uid", 1, 55, "(.*)");


     const PGresult *res = pgsql_query("SELECT moi.offer_id,mjo.offer_code,mm.* "
                                        "FROM members_offer_interest moi "
                                        "LEFT JOIN members_jobs_offer mjo ON mjo.id=moi.offer_id "
                                        "LEFT JOIN members_messages mm ON mm.memo=mjo.offer_code "
                                        "WHERE moi.uid  = '%s' ", in["interest_uid"].c_str());

        if (res != NULL && pgsql_num_rows(res) > 0) {
            out["total_record"] = pgsql_num_rows(res);

            for (int i = 0, n = pgsql_num_rows(res); i < n; i++) {
                map<const char*, const char*>f = pgsql_fetch_assoc(res, i);
                if (f.empty()) continue;
                CVars rec;
                map_to_cvars(f, rec);

				snprintf(vname, sizeof (vname), "msg_uid_%05d", i);
                out[vname] = rec["uid"];

                snprintf(vname, sizeof (vname), "added_%05d", i);
                out[vname] = rec["added"];

				snprintf(vname, sizeof (vname), "msg_%05d", i);
                out[vname] = rec["msg"];

            }
        }
        ret = PHP_API_OK;
        out["status"] = "OK";

    } catch (bad_parameter) {
        out["log_status"] = "Error WrenchMarketInterestQuestionList";
    }
    return ret;
}


long WrenchMarketInterestQuestion(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    out = in;
    try {
        out["status"] = "0";
        long member_id = REQ_LONG(in, "member_id", 1, -1);
        //long interest_id = REQ_LONG(in, "interest_id", 1, -1);
        REQ_STRING(in, "offer_uid", 1, 55, "(.*)");
        REQ_STRING(in, "interest_uid", 1, 55, "(.*)");
        REQ_STRING(in, "yourmessage", 1, 500, "(.*)"); //offer_code
        //REQ_STRING(in, "offer_code", 1, 15, "(.*)"); //offer_code
        REQ_STRING(in, "msg_type", 1, 15, "(.*)"); //msg_type

        const PGresult *res = pgsql_query("SELECT o.*,o.member_id AS client_id,jo.offer_code  "
                                          " FROM members_offer_interest o "
                                          " LEFT JOIN members_jobs_offer jo ON jo.id=o.offer_id WHERE jo.uid='%s' AND o.uid='%s'", in["offer_uid"].c_str(), in["interest_uid"].c_str());
        if (res != NULL && pgsql_num_rows(res) > 0) {
            map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
            if (!f.empty()) {
                CVars rec;
                map_to_cvars(f, rec);
                out = rec;

                CVars x;

                x["senders_id"] = in["member_id"];
                x["member_id"].set_valid(true);
                x["msg"] = in["yourmessage"];
                x["msg"].set_valid(true);
                x["msg_type"] = "MRKTINT";
                x["msg_type"].set_valid(true);
                x["member_id"] = out["member_id"];
                x["member_id"].set_valid(true);
                x["memo"] = rec["offer_code"];
                x["memo"].set_valid(true);
                long msg_id = insert_db_record(DBS_VALID, "members_messages", "members_messages_id_seq", x);
                if (msg_id > 0) {
                    x["msg_id"] = msg_id;
                    x["msg_id"].set_valid(true);
                    x["offer_id"] = out["offer_id"];
                    x["offer_id"].set_valid(true);
                    job_email(WRENCHBOARD_JOB_MRKTINT_QUEST, x, out);
                }
                //  out["client_id"] = 	x["member_id"]; 


            }
        }

        ret = PHP_CREATED_OK;

    } catch (bad_parameter) {
        out["log_status"] = "Error WrenchMarketInterestQuestion";
    }
    return ret;
}

long WrenchJobsQuestion(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    //out = in;
    try {
        out["status"] = "Started";
        long member_id = REQ_LONG(in, "member_id", 1, -1);
        REQ_STRING(in, "yourmessage", 1, 500, "(.*)"); //offer_code
        REQ_STRING(in, "offer_code", 1, 15, "(.*)"); //offer_code
        REQ_STRING(in, "msg_type", 1, 15, "(.*)"); //msg_type

        const PGresult *res = pgsql_query("SELECT * FROM members_jobs_offer WHERE offer_code = '%s'", in["offer_code"].c_str());
        if (res != NULL && pgsql_num_rows(res) > 0) {
            map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
            if (!f.empty()) {
                CVars rec;
                map_to_cvars(f, rec);
                out = rec;

                CVars x;
                x["senders_id"] = in["member_id"];
                x["member_id"].set_valid(true);
                x["msg"] = in["yourmessage"];
                x["msg"].set_valid(true);
                x["msg_type"] = "JOB";
                x["msg_type"].set_valid(true);
                x["member_id"] = out["member_id"];
                x["member_id"].set_valid(true);
                x["memo"] = in["offer_code"];
                x["memo"].set_valid(true);
                long msg_id = insert_db_record(DBS_VALID, "members_messages", "members_messages_id_seq", x);
                if (msg_id > 0) {
					x["status"] = "Sent";
                    x["msg_id"] = msg_id;
                    x["msg_id"].set_valid(true);
                    //x["offer_id"] = out["offer_id"];
                    //x["offer_id"].set_valid(true);
                  job_email(WRENCHBOARD_JOB_SEND_QUESTION, x, out);
                }
				else{
				x["status"] = "Error";
				}
                out = x;
                //out["status"] = "";

            }
        }

        ret = PHP_CREATED_OK;

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

/*
 id         | integer                     | not null default nextval('members_messages_id_seq'::regclass)
 member_id  | integer                     | 
 added      | timestamp without time zone | default now()
 msg        | text                        | 
 status     | integer                     | default 1
 senders_id | integer                     | 
Indexes:
    "members_messages_id_key"


    action
    :
    13034
    client_uid
    :
    "43c766d9-403d-4125-9983-63c21960b187"
    member_id
    :
    "1"
    offer_code
    :
    "XWT8B7W377"
    offer_uid
    :
    "10088dc3-c1ed-4782-808c-ae64940d3405"
    proc
    :
    "ACCEPT"
    sessionid
    :
    "800EDEE8AECA96EDAE0380537F5DE4546032B0709CD8FDA1BBAF5CAC0BF2ED1E"
    uid
    :
    "3119b744-42ad-4834-bb83-b737588754ca"

 */

long WrenchJobsProcessInterest(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    out = in;
    out["status"] = "Recieved";
    REQ_LONG(in, "member_id", 1, -1);
    REQ_STRING(in, "client_uid", 1, 55, "(.*)");
    REQ_STRING(in, "offer_uid", 1, 55, "(.*)");
    long interest = REQ_LONG(in, "interest", 1, -1);

    const PGresult *res0 = pgsql_query("SELECT mo.id AS interest_id, mo.*,mm.uid,jo.uid "
                                  " FROM members_offer_interest mo "
                                  " LEFT JOIN members mm ON mm.id= mo.member_id "
                                  " LEFT JOIN members_jobs_offer jo ON jo.id=mo.offer_id "
                                  " WHERE mm.uid = '%s' AND jo.uid='%s' ",in["client_uid"].c_str(),in["offer_uid"].c_str() );
              if (res0 != NULL && pgsql_num_rows(res0) > 0) {
                  map<const char*, const char*>f = pgsql_fetch_assoc(res0, 0);
                  if (!f.empty()) {
                      CVars rec1;
                      map_to_cvars(f, rec1);
                      in = rec1;
                      }
                 }else {
                out["status"] = "Not found.";
                return ret;
              }


    long interest_id = REQ_LONG(in, "interest_id", 1, -1);

    //REQ_STRING (in, "offer_code",   1, 15, "(.*)");	//offer_code
    if (interest == JOB_INTEREST_ACCEPT || interest == JOB_INTEREST_REJECT || interest == JOB_INTEREST_CANCEL) {
        // is job still valid 
        const PGresult *res = pgsql_query("SELECT mi.id,mi.member_id AS job_interest_client_id, mo.*,mo.id AS offer_id "
                                           " FROM members_offer_interest mi LEFT JOIN members_jobs_offer mo ON mo.id=mi.offer_id "
                                           " WHERE mo.status IN (1,4) AND mi.status=1 AND mi.id  = %lu", in["interest_id"].Long());
        if (res != NULL && pgsql_num_rows(res) > 0) {
            map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
            if (!f.empty()) {
                CVars rec;
                map_to_cvars(f, rec);
                out = rec;

                load_db_record(out, "SELECT email FROM members WHERE id  = %lu", rec["job_interest_client_id"].Long());

                if (interest == JOB_INTEREST_ACCEPT) {
                    /*
                    $in["job_id"] = $jobID;
                    $in["email"] = $email;
                    $in["job_description"] = $descr;
                    $in['member_id'] = $_SESSION['member_id'];
                    //  var_dump($in);

                    $in['action'] = WRENCHBOARD_JOB_OFFER_INDVI;
                     */
                    CVars x;
                    x["job_id"] = rec["job_id"];
                    x["job_id"].set_valid(true);
                    x["email"] = out["email"];
                    x["email"].set_valid(true);
                    x["job_description"] = out["job_description"];
                    x["job_description"].set_valid(true);
                    x["member_id"] = out["member_id"];
                    x["member_id"].set_valid(true);

                    ret = WrenchSendJobsOfferIndividual(x, out);
                    if (ret == PHP_CREATED_OK) {
                        pgsql_exec("UPDATE members_offer_interest SET status = 5 WHERE status=1 AND id  = %lu", interest_id);
                    }
                }

                if (interest == JOB_INTEREST_REJECT) {
                    pgsql_exec("UPDATE members_offer_interest SET status = 3 WHERE status=1 AND id  = %lu", interest_id);
                    // Implement emails latter
                    ret = PHP_CREATED_OK;
                }

                if (interest == JOB_INTEREST_CANCEL) {
                    pgsql_exec("UPDATE members_offer_interest SET status = 3 WHERE status=1 AND id  = %lu", interest_id);
                    // Implement emails latter							
                    pgsql_exec("UPDATE members_jobs_offer SET status = 3 WHERE status = 1 AND payment_id IS NULL AND id = %lu", rec["offer_id"].Long());
                    ret = PHP_CREATED_OK;
                }
            }
        } else {
            out["status"] = "Invalid Task Status";
        }

    }

    return ret;
}

long WrenchJobsOfferInterest(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    out = in;
    REQ_LONG(in, "member_id", 1, -1);
    REQ_STRING(in, "offer_code", 1, 15, "(.*)"); //offer_code

    const PGresult *res = pgsql_query("SELECT *,id as offer_id FROM members_jobs_offer WHERE offer_code ='%s' AND expire>= now() AND status = 1 AND public_view > 0", in["offer_code"].c_str());
    if (res != NULL && pgsql_num_rows(res) > 0) {
        map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
        if (!f.empty()) {
            CVars rec;
            map_to_cvars(f, rec);
            out = rec;

            if (rec["member_id"] == in["member_id"]) {
                out["status"] = "You cannot accept your job";
                return ret;
            }

            const PGresult *res1 = pgsql_query("SELECT * FROM members_offer_interest WHERE offer_id =%lu AND member_id = %lu AND status IN(1,5)", rec["offer_id"].Long(), in["member_id"].Long());
            if (res1 != NULL && pgsql_num_rows(res1) > 0) {
                out["status"] = "You have sent or completed a request for this task already.";
                return ret;
            }


            CVars x;
            x["member_id"] = in["member_id"];
            x["member_id"].set_valid(true);
            x["offer_id"] = rec["offer_id"];
            x["offer_id"].set_valid(true);
            long interest_id = insert_db_record(DBS_VALID, "members_offer_interest", "members_offer_interest_id_seq", x);
            if (interest_id > 0) {
                out["status"] = "Offer interest sent";
                ret = PHP_CREATED_OK;
                x["interest_id"] = interest_id;
                x["interest_id"].set_valid(true);
                job_email(JOBS_OFFER_INTEREST_MAIL, x, out); // note I need interest_id to
            }
        }
    }


    //out["status"] = "Yes from backend";
    return ret;
}

long WrenchConcludeJobsOffer(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    try {
        REQ_LONG(in, "member_id", 1, -1);
        long offer_result = REQ_LONG(in, "offer_result", 1, -1);
        REQ_STRING(in, "offer_code", 1, 15, "(.*)");
        long job_id = 0;
        long owner_member_id = 0;
        long offer_id = 0;

        long rc = 0;
		CVars outx;
        //  rc = 0 + load_db_record( out, "SELECT * FROM members_jobs_offer WHERE offer_code='%s' AND status = 1", in["offer_code"].c_str() );



        const PGresult *res = pgsql_query("SELECT *,member_id AS owner_member_id, id AS offer_id FROM members_jobs_offer WHERE offer_code='%s' AND status = 1", in["offer_code"].c_str());
        if (res != NULL && pgsql_num_rows(res) > 0) {

            // now job is valid
            // good to continue
                map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
                if (!f.empty()) {
                    CVars rec;
                    map_to_cvars(f, rec);
                    job_id = rec["job_id"];
                    offer_id =  rec["offer_id"];
                    owner_member_id = rec["owner_member_id"];
                }

			if( offer_result == OFFER_RESEND){
					if (load_db_record(outx, "SELECT o.id AS offer_id, o.*,to_char(o.expire, 'Day Mon dd, yyyy HH:MI AM') AS expire2,j.title,j.description,j.timeline_days,j.price FROM members_jobs_offer o LEFT JOIN members_jobs j ON j.id =o.job_id WHERE o.offer_code='%s' AND o.email IS NOT NULL", in["offer_code"].c_str())) {
					job_email(JOBS_INDIVIDUAL_OFFER_MAIL, outx, out); // make sure job went to individual
					out["result"] = "OK"; 
					}
					    
	             return PHP_CREATED_OK;
			}
			
			
            load_db_record(out, "SELECT jo.promo, jo.strict_timeline, jo.member_id AS owner_member_id,jo.id AS offer_id, "
                                " j.id AS job_id,jo.added::date AS added_date,j.title,j.description,"
                                " j.timeline_days, j.price,jo.offer_code,jo.job_description,jo.expire "
                                " FROM members_jobs_offer jo LEFT JOIN members_jobs j ON j.id = jo.job_id "
                                " WHERE jo.expire > now() AND jo.status = 1 "
                                " AND jo.client_id = %lu  AND jo.offer_code='%s'", in["member_id"].Long(), in["offer_code"].c_str());

          
            in["offer_id"] = out["offer_id"];
            in["offer_id"].set_valid(true);

            CVars x;
            const char * loc = getenv("REMOTE_ADDR");
            long contract_id = 0;

            switch (offer_result) {
				case OFFER_EXTEND:
				logfmt(logINFO, "WrenchConcludeJobsOffer() rc=OFFER_EXTEND");
				// You can only extend your jobs only
				if( load_db_record(outx, "SELECT id AS offer_id,* FROM members_jobs_offer WHERE offer_code='%s' AND status = 1 AND member_id=%lu", in["offer_code"].c_str(),in["member_id"].Long()) ){
				   pgsql_exec("UPDATE members_jobs_offer SET expire = expire +'7 days' WHERE id  = %lu AND offer_code='%s' ", outx["offer_id"].Long(), outx["offer_code"].c_str());
				}

				break;


					
                case OFFER_SENDTOME:
                    job_email(JOBS_OFFER_SENDTOME_MAIL, in, out); // the email will come from
                    break;

                case OFFER_ACCEPT:
                    x["job_id"] = job_id;
                    x["job_id"].set_valid(true);
                    x["contract"] = in["offer_code"];
                    x["contract"].set_valid(true);
                    x["member_id"] = owner_member_id; //out["owner_member_id"];
                    x["member_id"].set_valid(true); // this is the owner of the job - from job database read
                    x["client_id"] = in["member_id"];
                    x["client_id"].set_valid(true); // be care full, you are the client accepting job
                    x["title"] = out["title"];
                    x["title"].set_valid(true);
                    x["description"] = out["description"];
                    x["description"].set_valid(true);
                    x["job_detail"] = out["job_description"];
                    x["job_detail"].set_valid(true);
                    x["price"] = out["price"];
                    x["price"].set_valid(true);
                    x["timeline_days"] = out["timeline_days"];
                    x["timeline_days"].set_valid(true);

                    x["strict_timeline"] = out["strict_timeline"];
                    x["strict_timeline"].set_valid(true);

                    x["promo"] = out["promo"];
                    x["promo"].set_valid(true);

                    x["loc"] = loc;
                    x["loc"].set_valid(true);
                    //x[""]   = out[""]; x[""].set_valid( true );
                    contract_id = insert_db_record(DBS_VALID, "members_jobs_contract", "members_jobs_contract_id_seq", x);
                    if (contract_id > 0) {
                        in["contract_id"] = contract_id;
                        in["contract_id"].set_valid(true);
                        pgsql_exec("UPDATE members_jobs_contract SET delivery_date = now() +'%lu days' WHERE id  = %lu", x["timeline_days"].Long(), contract_id);
                        pgsql_exec("UPDATE members_jobs_offer SET status = 5 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                        pgsql_exec("UPDATE members_payments SET what_contract = %lu WHERE what_offer  = %lu ", contract_id, offer_id);
                        job_email(JOBS_OFFER_ACCEPT_MAIL, in, out); // note the email will come from contract table now
                        /*
                        READ OUT THE CONTRACT

                                 load_db_record(out, "SELECT mc.id AS contract_id, mc.job_id AS job_id, mc.price, mc.timeline_days,mc.contract, "
                                        "  mj.title, mj.description AS description,mc.job_detail AS job_description,mc.uid AS contract_uid, mj.job_type AS job_type, mj.media_uid AS media_uid, "
                                        "  mj.banner AS banner, c.code AS currency_code, c.description AS currency_description, mj.uid AS job_uid, "
                                        " (CASE WHEN mc.status=4 THEN 'REVIEW' "
                                        "  WHEN mc.status = 1 AND mc.delivery_date > now() THEN 'ACTIVE' "
                                        "  WHEN mc.status = 1 AND mc.delivery_date <now() THEN 'PASTDUE' "
                                        "  ELSE 'Others' END)  AS status_description,mc.delivery_date,  "
                                        "  'WORKER' AS owner_status, mc.ext_request AS ext_request "
                                        "  FROM members_jobs_contract mc "
                                        "  LEFT JOIN members_jobs mj ON mj.id = mc.job_id "
                                        "  LEFT JOIN members m ON m.id=mc.client_id  "
                                        "  LEFT JOIN currency c ON c.country=mj.country "
                                        "  WHERE mc.id =%lu", contract_id);
                        */
//                        load_db_record(out, "SELECT c.id AS contact_id, c.uid as contract_uid, c.contract,j.description AS job_description, j.timeline_days,j.price,cc.description AS currency "
//                                            " FROM members_jobs_contract c "
//                                            " LEFT JOIN members_jobs j ON j.id = c.job_id "
//                                            " LEFT JOIN currency cc ON cc.country = j.country "
//                                            " WHERE c.id = %lu", contract_id);

                     load_db_record(out, "SELECT mc.id AS contract_id, mc.job_id AS job_id, mc.price, mc.timeline_days,mc.contract, "
                            "  mj.title, mj.description AS description,mc.job_detail AS job_description,mc.uid AS contract_uid, mj.job_type AS job_type, mj.media_uid AS media_uid, "
                            "  mj.banner AS banner, c.code AS currency_code, c.description AS currency_description, mj.uid AS job_uid, "
                            " (CASE WHEN mc.status=4 THEN 'REVIEW' "
                            "  WHEN mc.status = 1 AND mc.delivery_date > now() THEN 'ACTIVE' "
                            "  WHEN mc.status = 1 AND mc.delivery_date <now() THEN 'PASTDUE' "
                            "  ELSE 'Others' END)  AS status_description,mc.delivery_date,  "
                            "  'WORKER' AS owner_status, mc.ext_request AS ext_request "
                            "  FROM members_jobs_contract mc "
                            "  LEFT JOIN members_jobs mj ON mj.id = mc.job_id "
                            "  LEFT JOIN members m ON m.id=mc.client_id  "
                            "  LEFT JOIN currency c ON c.country=mj.country "
                            "  WHERE mc.id =%lu", contract_id);
                    }

                    break;

                case OFFER_REJECT: // note status= 3
                    logfmt(logINFO, "WrenchConcludeJobsOffer() rc=OFFER_REJECT");
                    if (load_db_record(out, " SELECT id AS offer_id,* FROM members_jobs_offer WHERE offer_code ='%s' AND status = 1", in["offer_code"].c_str())) {
                        // valid load of offer needed
                        CVars y;
                        y["member_id"] = out["member_id"];
                        y["member_id"].set_valid(true);
                        y["offer_id"] = out["offer_id"];
                        y["offer_id"].set_valid(true);
                        y["code"] = "OFRFD";
                        y["code"].set_valid(true);
                        y["dir"] = DIR_SOURCE;
                        y["dir"].set_valid(true);
                        y["payment_id"] = out["payment_id"];
                        y["payment_id"].set_valid(true);

                        if (WrenchRefundoffer(y, out) == PHP_CREATED_OK) {
                            pgsql_exec("UPDATE members_jobs_offer SET status = 3 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                            // REFUND THE MONEY					
                            job_email(JOBS_OFFER_REJECT_MAIL, in, out); // the email will come from offer table						  
                        }
                    }
                    break;

                case OFFER_CANCEL: // note status 4
                    logfmt(logINFO, "WrenchConcludeJobsOffer() rc=OFFER_CANCEL");
                    if (load_db_record(out, " SELECT id AS offer_id,*,(CASE WHEN payment_id IS NULL THEN 0 ELSE payment_id END ) AS payment_id_val FROM members_jobs_offer WHERE offer_code ='%s' AND status = 1", in["offer_code"].c_str())) {
                        // valid load of offer needed
                        CVars y;
                        y["member_id"] = out["member_id"];
                        y["member_id"].set_valid(true);
                        y["offer_id"] = out["offer_id"];
                        y["offer_id"].set_valid(true);
                        y["code"] = "OFRFD";
                        y["code"].set_valid(true);
                        y["dir"] = DIR_SOURCE;
                        y["dir"].set_valid(true);
                        y["payment_id"] = out["payment_id_val"];
                        y["payment_id"].set_valid(true);

                        if (WrenchRefundoffer(y, out) == PHP_CREATED_OK) {
                            pgsql_exec("UPDATE members_jobs_offer SET status = 4 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                            // REFUND THE MONEY					
                            job_email(JOBS_OFFER_CANCEL_MAIL, y, out); // the email will come from offer table						  
                        }
                    }
                    break;

                case OFFER_EXPIRE: // note status 4
                case OFFER_NOREFU:

                    logfmt(logINFO, "WrenchConcludeJobsOffer() rc=OFFER_EXPIRE");
                    if (load_db_record(out, "SELECT id AS offer_id,* FROM members_jobs_offer WHERE offer_code ='%s' AND status = 1", in["offer_code"].c_str())) {
												// valid load of offer needed
                        CVars y;
                        y["member_id"] = out["member_id"];
                        y["member_id"].set_valid(true);
                        y["offer_id"] = out["offer_id"];
                        y["offer_id"].set_valid(true);
                        y["code"] = "OFRFD";
                        y["code"].set_valid(true);
                        y["dir"] = DIR_SOURCE;
                        y["dir"].set_valid(true);
                        y["payment_id"] = out["payment_id"];
                        y["payment_id"].set_valid(true);

                        if ( offer_result == OFFER_EXPIRE){
                            if (WrenchRefundoffer(y, out) == PHP_CREATED_OK) {
                                pgsql_exec("UPDATE members_jobs_offer SET status = 4 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                                // REFUND THE MONEY
                                //job_email(JOBS_OFFER_CANCEL_MAIL, in, out); // the email will come from offer table
                            }
                        }
                        if ( offer_result == OFFER_NOREFU){

                           if (WrenchZeroRefundOffer(y, out) == PHP_CREATED_OK) {
                                logfmt(logINFO, "*********  NO REFUND ************* NO REFUND    WrenchConcludeJobsOffer() rc=FOUND");
                                pgsql_exec("UPDATE members_jobs_offer SET status = 4 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
                           }
                        }


//                        if (WrenchRefundoffer(y, out) == PHP_CREATED_OK) {
//                            pgsql_exec("UPDATE members_jobs_offer SET status = 4 WHERE id  = %lu AND offer_code='%s' ", offer_id, in["offer_code"].c_str());
//                            // REFUND THE MONEY
//                            //job_email(JOBS_OFFER_CANCEL_MAIL, in, out); // the email will come from offer table
//                        }

                    }
                    break;
            }

            logfmt(logINFO, "WrenchConcludeJobsOffer() rc=FOUND");
            out["result"] = "OK";
        } else {
            out["result"] = "Invalid Offer...";
            logfmt(logINFO, "WrenchConcludeJobsOffer() rc=NOT FOUND");
        }

        // check if the offer is still valid

        // set up the work as active

        // if work is rejected, refund the member balance 

        // send message to client_id

        // send message to the member 

        // alert wrench board of work



        //pgsql_exec("UPDATE members_job_group SET status = 0 WHERE status = 1 AND member_id = %lu AND id = %lu",in["member_id"].Long(),in["group_id"].Long());
        ret = PHP_CREATED_OK;

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

long WrenchSendMediaOfferFamily(CVars in, CVars &out) {
 logfmt(logINFO, "ENTER WrenchJobOfferSystems()->WrenchSendMediaOfferFamily");

    long ret = PHP_API_BAD_PARAM;
   // logfmt(logINFO, "WrenchSendMediaOfferFamily()");
    long member_id  = REQ_LONG(in, "member_id", 1, -1);
    REQ_STRING(in, "uid", 1, 59, "(.*)");
    REQ_STRING(in, "media_uid", 1, 59, "(.*)");
    REQ_STRING(in, "family_uid", 1, 59, "(.*)");
    REQ_STRING(in, "job_description", 1, 5500, "(.*)");
    long amount  = REQ_LONG(in, "amount", 1, -1);
    REQ_LONG(in, "timeline_days", 1, -1);

    REQ_STRING(in, "currency", 2, 4, "(.*)");
    long job_id = 0;
    srand((unsigned) time(NULL));
    int r = rand();
    in["offer_code"] = 10000000 * r*r;
    in["offer_code"].set_valid(true);

    long offer_id = 0;
    out = in;
    in["client_id"] = "0";
    CVars x;
    CVars y;
	CVars u;
    CVars z;
    CVars kx;
    CVars xy;
    CVars xout;

    bool family_found =  false;

    try {
        // let us use this email to see if this already a user on the system
        if (load_db_record(out, "SELECT family_member_id AS client_id FROM members_family WHERE member_id = %lu AND uid='%s';",member_id, in["family_uid"].c_str())) {
            in["client_id"] = out["client_id"]; // overidding if account is found
            if (out["client_id"].length() > 0) {
                x["client_id"] = in["client_id"];
                x["client_id"].set_valid(true);
                family_found = true;
            }
        }

        if (family_found == false){
            out["status"] = "Family not Found....";
            return ret;
        }

        // we need this job id
        if (load_db_record(y, " SELECT * FROM common_media WHERE uid ='%s'", in["media_uid"].c_str())) {
            // valid load of job needed
        } else {
            out["status"] = "Unable to create offer";
            return ret;
        }

		load_db_record(u,"SELECT code AS currency FROM currency WHERE country = '%s'", in["currency"].c_str() );
		logfmt(logINFO, " The Currency code = %s", u["currency"].c_str());
		long wallet_id =  CheckWallet( in["member_id"].Long() , u);
		logfmt(logINFO, " The wallet_id = %lu", wallet_id);

        if (in["client_id"].Long() == in["member_id"].Long()) {
            out["status"] = "Unable to create offer";
            return ret;
        } // same client and member not allowed

        if (in["amount"].Long() > 0) {
        } else {
            out["status"] = "Unable to create offer";
            return ret;
        } // no price zero for job on this path

		// Now do you have money to do this ....
		z["balance"] = "0";
		z["balance"].set_valid(true); // just initialize it
		if (load_db_record(z, " SELECT * FROM members_wallet WHERE id =%lu AND member_id =%lu AND amount >= %lu",wallet_id, in["member_id"].Long(), in["amount"].Long())) {

		} else {
			out["status"] = "Insufficient balance to create this offer";
			logfmt(logINFO, "Price2 = %lu Balance = %lu", in["amount"].Long(), z["amount"].Long());
		}

//***************************************
    const char * loc = getenv("REMOTE_ADDR");
    logfmt(logINFO, "ENTER WrenchJobOfferSystems()->DATA for hidden Job");
    kx["member_id"] = in["member_id"];
    kx["member_id"].set_valid(true);
    kx["title"] = y["title"];
    kx["title"].set_valid(true);
    kx["price"] = in["amount"];
    kx["price"].set_valid(true);
    kx["timeline_days"] = in["timeline_days"];
    kx["timeline_days"].set_valid(true);
    kx["description"] = y["description"];
    kx["description"].set_valid(true);
    kx["loc"] = loc;
    kx["loc"].set_valid(true);
    kx["job_detail"] = in["job_description"];
    kx["job_detail"].set_valid(true);
    //country added
    kx["country"] = in["currency"];  // currency in the input data
    kx["country"].set_valid(true);
    kx["job_type"] = "MEDIA";
    kx["job_type"].set_valid(true);
    kx["media_uid"] = in["media_uid"];
    kx["media_uid"].set_valid(true);
    kx["status"] ="77";    // need the job to be hidden , data needed for payment systems
    kx["status"].set_valid(true);
   logfmt(logINFO, "ENTER WrenchJobOfferSystems()->DATA for hidden Job -- Ready");

    job_id = insert_db_record(DBS_VALID, "members_jobs", "members_jobs_id_seq", kx);
     logfmt(logINFO, "ENTER WrenchJobOfferSystems()->DATA for hidden Job Inserted job_id = %lu",job_id);
    if (job_id) {

    }
//***************************************

        // we re ready to create the offer now
        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["job_id"] = job_id;
        x["job_id"].set_valid(true);
        x["media_uid"] = in["media_uid"];
        x["media_uid"].set_valid(true);
        x["job_description"] = in["job_description"];
        x["job_description"].set_valid(true);
        x["offer_code"] = in["offer_code"];
        x["offer_code"].set_valid(true);


        x["loc"] = loc;
        x["loc"].set_valid(true);
        offer_id = insert_db_record(DBS_VALID, "members_jobs_offer", "members_jobs_offer_id_seq", x);

        if (offer_id > 0) {
            CVars y;
            y["member_id"] = x["member_id"];
            y["offer_id"] = offer_id;
            y["code"] = "OFDPS";
            y["dir"] = DIR_TARGET;
            if (WrenchOfferPayment(y, out) == PHP_CREATED_OK) { // if you reserve pauments
                char offer_code[15] = "";
                GetOfferCode(offer_id, offer_code, sizeof (offer_code)); // this stamp the offer code directly in that call

                pgsql_exec("UPDATE members_jobs_offer SET expire = now() + '2 day',payment_id=%lu WHERE id = %lu", out["payment_id"].Long(), offer_id); // date of expiration will be dynamic latter

                ret = PHP_CREATED_OK;
                x["offer_id"] = offer_id;
                x["offer_id"].set_valid(true);
                job_email(JOBS_INDIVIDUAL_OFFER_MAIL, x, out);
                load_db_record(out, "SELECT *,id AS offer_id FROM members_jobs_offer WHERE id = %lu ", offer_id);
                out["status"] = "Offer sent to recipient";
                recommendation_engine(RECOMMEND_OFFERS , y, out); // trigger the card interaction in apps

                  if ( load_db_record(xy, "SELECT mj.client_id AS member_id, m.uid AS member_uid "
                                          " FROM members_jobs_offer mj "
                                          " LEFT JOIN members m ON m.id = mj.client_id "
                                          " WHERE mj.id  =  %lu ",offer_id ) > 0 ){
                               xy["msg"] = "You have a task to start !";
                               xy["msg"].set_valid(true);
                               plan_notification(xy, xout);
                   }


            } else {
                out["error_msg"] = "error_unable_to_create_fund_for_task";
                out["status"] = "Unable to create this offer";
            }
        } else {
            out["status"] = "Unable to create offer";
        }

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }

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



long WrenchSendJobsOfferFamily(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    logfmt(logINFO, "WrenchSendJobsOfferFamily()");
    long member_id  = REQ_LONG(in, "member_id", 1, -1);
    REQ_LONG(in, "job_id", 1, -1);
    REQ_STRING(in, "job_uid", 1, 59, "(.*)");
    REQ_STRING(in, "family_uid", 1, 59, "(.*)");
    REQ_STRING(in, "job_description", 1, 5500, "(.*)");

    srand((unsigned) time(NULL));
    int r = rand();
    in["offer_code"] = 10000000 * r*r;
    in["offer_code"].set_valid(true);

    long offer_id = 0;
    out = in;
    /*
'member_id' => int 1
  'sessionid' => string 'DFD8812B9A3ABE7FCF920B71A22AA3E93BB9F9C33AE22E90AAC47537367B2E2B' (length=64)
  'uid' => string '3119b744-42ad-4834-bb83-b737588754ca' (length=36)
  'job_id' => string '98' (length=2)
  'job_uid' => string '473d3239-ecd7-4eb5-859c-78261720cb8e' (length=36)
  'family_uid' => string 'a24f1193-7885-4c26-afac-3e5ad744ef40' (length=36)
  'job_description' => string 'Nitetronic Z6 Anti Snoring Pillow, Best Snore Stopper Device, Clinically Proven Snoring Solution for Snorers, Smart Stop Snoring Technology Suitable for All Sleepers' (length=165)
  'action' => int 13025
  'assign_mode' => int 110011


    CREATE TABLE members_jobs_offer (
    id SERIAL,
    offer_code varchar(15) UNIQUE NOT NULL,
    member_id INT REFERENCES members(id),
    client_id INT DEFAULT 0,
    group_id INT DEFAULT 0,
    job_id INT REFERENCES members_jobs(id),
    email varchar(50),
    job_description varchar(500),
    status integer DEFAULT 1,
    sent_count integer DEFAULT 0,
    added timestamp without time zone DEFAULT now()
    );

     */
    in["client_id"] = "0";
    CVars x;
    CVars y;
	CVars u;
    CVars z;

    CVars xy;
    CVars xout;

    bool family_found =  false;

    try {
        // let us use this email to see if this already a user on the system
        if (load_db_record(out, "SELECT family_member_id AS client_id FROM members_family WHERE member_id = %lu AND uid='%s';",member_id, in["family_uid"].c_str())) {
            in["client_id"] = out["client_id"]; // overidding if account is found
            if (out["client_id"].length() > 0) {
                x["client_id"] = in["client_id"];
                x["client_id"].set_valid(true);
                family_found = true;
            }
        }

        if (family_found == false){
            out["status"] = "Family not Found....";
            return ret;
        }

        // we need this job id
        if (load_db_record(y, " SELECT * FROM members_jobs WHERE id =%lu", in["job_id"].Long())) {
            // valid load of job needed
        } else {
            out["status"] = "Unable to create offer";
            return ret;
        }

		load_db_record(u,"SELECT code AS currency FROM currency WHERE country = '%s'", y["country"].c_str() );
		logfmt(logINFO, " The Currency code = %s", u["currency"].c_str());
		long wallet_id =  CheckWallet( in["member_id"].Long() , u);
		logfmt(logINFO, " The wallet_id = %lu", wallet_id);

        if (in["client_id"].Long() == in["member_id"].Long()) {
            out["status"] = "Unable to create offer";
            return ret;
        } // same client and member not allowed

        if (y["price"].Long() > 0) {
        } else {
            out["status"] = "Unable to create offer";
            return ret;
        } // no price zero for job on this path

		// Now do you have money to do this ....
		z["balance"] = "0";
		z["balance"].set_valid(true); // just initialize it
		if (load_db_record(z, " SELECT * FROM members_wallet WHERE id =%lu AND member_id =%lu AND amount >= %lu",wallet_id, in["member_id"].Long(), y["price"].Long())) {

		} else {
			out["status"] = "Insufficient balance to create this offer";
			logfmt(logINFO, "Price2 = %lu Balance = %lu", y["price"].Long(), z["amount"].Long());
		}


        // we re ready to create the offer now
        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["job_id"] = in["job_id"];
        x["job_id"].set_valid(true);
        x["email"] = in["email"];
        x["email"].set_valid(true);
        x["job_description"] = in["job_description"];
        x["job_description"].set_valid(true);
        x["offer_code"] = in["offer_code"];
        x["offer_code"].set_valid(true);

        const char * loc = getenv("REMOTE_ADDR");
        x["loc"] = loc;
        x["loc"].set_valid(true);
        offer_id = insert_db_record(DBS_VALID, "members_jobs_offer", "members_jobs_offer_id_seq", x);

        if (offer_id > 0) {
            CVars y;
            y["member_id"] = x["member_id"];
            y["offer_id"] = offer_id;
            y["code"] = "OFDPS";
            y["dir"] = DIR_TARGET;
            if (WrenchOfferPayment(y, out) == PHP_CREATED_OK) { // if you reserve pauments
                char offer_code[15] = "";
                GetOfferCode(offer_id, offer_code, sizeof (offer_code)); // this stamp the offer code directly in that call

                pgsql_exec("UPDATE members_jobs_offer SET expire = now() + '1 day',payment_id=%lu WHERE id = %lu", out["payment_id"].Long(), offer_id); // date of expiration will be dynamic latter

                ret = PHP_CREATED_OK;
                x["offer_id"] = offer_id;
                x["offer_id"].set_valid(true);
                job_email(JOBS_INDIVIDUAL_OFFER_MAIL, x, out);
                load_db_record(out, "SELECT *,id AS offer_id FROM members_jobs_offer WHERE id = %lu ", offer_id);
                out["status"] = "Offer sent to recipient";
                recommendation_engine(RECOMMEND_OFFERS , y, out); // trigger the card interaction in apps

                  if ( load_db_record(xy, "SELECT mj.client_id AS member_id, m.uid AS member_uid "
                                          " FROM members_jobs_offer mj "
                                          " LEFT JOIN members m ON m.id = mj.client_id "
                                          " WHERE mj.id  =  %lu ",offer_id ) > 0 ){
                               xy["msg"] = "You have a task to start !";
                               xy["msg"].set_valid(true);
                               plan_notification(xy, xout);
                   }


            } else {
                out["error_msg"] = "error_unable_to_create_fund_for_task";
                out["status"] = "Unable to create this offer";
            }
        } else {
            out["status"] = "Unable to create offer";
        }

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }

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


long WrenchSendJobsOfferIndividual(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    logfmt(logINFO, "WrenchSendJobsOfferIndividual()");
    REQ_LONG(in, "member_id", 1, -1);
    REQ_LONG(in, "job_id", 1, -1);
    REQ_STRING(in, "email", 1, 59, "(.*)");
    REQ_STRING(in, "job_description", 1, 5500, "(.*)");

    srand((unsigned) time(NULL));
    int r = rand();
    in["offer_code"] = 10000000 * r*r;
    in["offer_code"].set_valid(true);
  
    long offer_id = 0;
    out = in;

    in["client_id"] = "0";
    CVars x;
    CVars y;
	CVars u;
    CVars z;

    try {

        if ( in["strict_timeline"] =="" ){
             in["strict_timeline"] = "0";  in["strict_timeline"].set_valid(true);
        }

        // let us use this email to see if this already a user on the system
        if (load_db_record(out, " SELECT username,id AS client_id FROM  members WHERE LOWER(username) =LOWER(TRIM('%s'));", in["email"].c_str())) {
            in["client_id"] = out["client_id"]; // overiddind if account is found
            if (out["client_id"].length() > 0) {
                x["client_id"] = in["client_id"];
                x["client_id"].set_valid(true);
            }
        }
        // we need this job id
        if (load_db_record(y, " SELECT * FROM members_jobs WHERE id =%lu", in["job_id"].Long())) {
            // valid load of job needed
        } else {
            out["status_msg"] = "Job not found";
            out["status"] = "Unable to create offer";
            return ret;
        }

		load_db_record(u,"SELECT code AS currency FROM currency WHERE country = '%s'", y["country"].c_str() );
		logfmt(logINFO, " The Currency code = %s", u["currency"].c_str());
		long wallet_id =  CheckWallet( in["member_id"].Long() , u);
		logfmt(logINFO, " The wallet_id = %lu", wallet_id);
	
        if (in["client_id"].Long() == in["member_id"].Long()) {
            out["status_msg"] = "You cannot send job to yourself";
            out["status"] = "Unable to create offer";
            return ret;
        } // same client and member not allowed

        if (y["price"].Long() > 0) {
        } else {
            out["status_msg"] = "Price cannot be zero";
            out["status"] = "Unable to create offer";
            return ret;
        } // no price zero for job on this path

		// Now do you have money to do this ....
		z["balance"] = "0";
		z["balance"].set_valid(true); // just initialize it
		if (load_db_record(z, " SELECT * FROM members_wallet WHERE id =%lu AND member_id =%lu AND amount >= %lu",wallet_id, in["member_id"].Long(), y["price"].Long())) {

		} else {
			out["status"] = "Insufficient balance to create this offer";
			logfmt(logINFO, "Price2 = %lu Balance = %lu", y["price"].Long(), z["amount"].Long());
			return ret;
		}
	

        // we re ready to create the offer now		   
        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["job_id"] = in["job_id"];
        x["job_id"].set_valid(true);
        x["email"] = in["email"];
        x["email"].set_valid(true);
        x["job_description"] = in["job_description"];
        x["job_description"].set_valid(true);
        x["offer_code"] = in["offer_code"];
        x["offer_code"].set_valid(true);

        x["strict_timeline"] = in["strict_timeline"];
        x["strict_timeline"].set_valid(true);

        x["promo"] = in["promo"];
        x["promo"].set_valid(true);

        const char * loc = getenv("REMOTE_ADDR");
        x["loc"] = loc;
        x["loc"].set_valid(true);
        offer_id = insert_db_record(DBS_VALID, "members_jobs_offer", "members_jobs_offer_id_seq", x);

        if (offer_id > 0) {
            CVars y;
            y["member_id"] = x["member_id"];
            y["offer_id"] = offer_id;
            y["code"] = "OFDPS";
            y["dir"] = DIR_TARGET;
            if (WrenchOfferPayment(y, out) == PHP_CREATED_OK) { // if you reserve pauments
                char offer_code[15] = "";
                GetOfferCode(offer_id, offer_code, sizeof (offer_code)); // this stamp the offer code directly in that call					

                pgsql_exec("UPDATE members_jobs_offer SET expire = now() + '1 day',payment_id=%lu WHERE id = %lu", out["payment_id"].Long(), offer_id); // date of expiration will be dynamic latter 

                ret = PHP_CREATED_OK;
                x["offer_id"] = offer_id;
                x["offer_id"].set_valid(true);
                job_email(JOBS_INDIVIDUAL_OFFER_MAIL, x, out);
                load_db_record(out, "SELECT *,id AS offer_id FROM members_jobs_offer WHERE id = %lu ", offer_id);
                out["status"] = "Offer sent to recipient";
                recommendation_engine(RECOMMEND_OFFERS , y, out); // trigger the card interaction in apps
                CVars xy;
                if ( load_db_record(xy, "SELECT id AS member_id, uid AS member_uid, 'alert.svg' AS icon  "
                                        " FROM members WHERE LOWER(username) = LOWER('%s') ",in["email"].c_str()) > 0 ){
                             xy["msg"] = "You have received a new offer !!!";
                             xy["msg"].set_valid(true);
                             plan_notification(xy, out);
                 }
            } else {
                out["error_msg"] = "error_unable_to_create_fund_for_task";
                out["status"] = "Unable to create this offer";
            }

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

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }

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

long WrenchSendJobsOfferPublic(CVars in, CVars &out) {
    logfmt(logINFO, "WrenchSendJobsOfferPublic()");

    long ret = PHP_API_BAD_PARAM;
    REQ_LONG(in, "member_id", 1, -1);
    REQ_LONG(in, "job_id", 1, -1);
    REQ_LONG(in, "duration", 1, -1);
    //REQ_STRING (in, "email",   1, 59, "(.*)");	
    REQ_STRING(in, "job_description", 1, 5500, "(.*)");

    srand((unsigned) time(NULL));
    int r = rand();
    in["offer_code"] = 10000000 * r*r;

    long offer_id = 0;
    out = in;

    CVars x;
    CVars y;
    CVars z;
    CVars u;


    // we need this job id
    if (load_db_record(y, " SELECT * FROM members_jobs WHERE id =%lu", in["job_id"].Long())) {
        // valid load of job needed
    } else {
        out["status"] = "Unable to create offer";
        return ret;
    }

    load_db_record(u,"SELECT code AS currency FROM currency WHERE country = '%s'", y["country"].c_str() );
    logfmt(logINFO, " The Currency code = %s", u["currency"].c_str());
    long wallet_id =  CheckWallet( in["member_id"].Long() , u);
    logfmt(logINFO, " The wallet_id = %lu", wallet_id);

    if (y["price"].Long() > 0) {
    } else {
        out["status"] = "Unable to create offer";
        return ret;
    } // no price zero for job on this path

    // Now do you have money to do this ....
    z["balance"] = "0";
    z["balance"].set_valid(true); // just initialize it
    if (load_db_record(z, " SELECT * FROM members_wallet WHERE id =%lu AND member_id =%lu AND amount >= %lu",wallet_id, in["member_id"].Long(), y["price"].Long())) {

    } else {
        out["status"] = "Insufficient balance to create this offer";
        logfmt(logINFO, "Price2 = %lu Balance = %lu", y["price"].Long(), z["amount"].Long());
    }

    if (y["price"].Long() >= z["amount"].Long()) {
        out["status"] = "Insufficient balance to create this offer";
        logfmt(logINFO, "Price = %lu Balance = %lu", y["price"].Long(), z["amount"].Long());
        return ret;
    }

    logfmt(logINFO, "Price = %lu Balance = %lu", y["price"].Long(), z["amount"].Long());

    try {
        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["job_id"] = in["job_id"];
        x["job_id"].set_valid(true);
        x["group_id"] = "0";
        x["group_id"].set_valid(true);
        x["client_id"] = "0";
        x["client_id"].set_valid(true);
        x["job_description"] = in["job_description"];
        x["job_description"].set_valid(true);
        x["offer_code"] = in["offer_code"];
        x["offer_code"].set_valid(true);

        x["depend_uid"] = in["depend_uid"];
        x["depend_uid"].set_valid(true);

        x["strict_timeline"] = in["strict_timeline"];
        x["strict_timeline"].set_valid(true);


        if ( x["depend_uid"] != ""){
             logfmt(logINFO, "****** Let us confirm this job is in the market === >  %s", x["depend_uid"].c_str());

             const PGresult *resF = pgsql_query(" SELECT c.public_view,c.expire,c.job_id "
                            " FROM members_jobs_offer c "
                            " LEFT JOIN members_jobs j ON j.id = c.job_id "
                            " WHERE c.public_view = 1 and c.expire> now() AND j.uid::text ='%s' ", x["depend_uid"].c_str());
                            if (resF != NULL && pgsql_num_rows(resF) > 0) {
                              logfmt(logINFO, "ALL Good ****** Let us confirm this job is in the market === >  %s", x["depend_uid"].c_str());
                            }
                            else{
                                out["status"] = "Depended task must be active in the market";
                                return ret;
                            }
        }


        const char * loc = getenv("REMOTE_ADDR");
        x["loc"] = loc;
        x["loc"].set_valid(true);
        offer_id = insert_db_record(DBS_VALID, "members_jobs_offer", "members_jobs_offer_id_seq", x);

        if (offer_id > 0) {

            char offer_code[15] = "";
            GetOfferCode(offer_id, offer_code, sizeof (offer_code)); // this stamp the offer code directly in that call									

            pgsql_exec("UPDATE members_jobs_offer SET expire = now() + '%lu day',public_view=1 WHERE id = %lu", in["duration"].Long(), offer_id);

            ret = PHP_CREATED_OK;
            x["offer_id"] = offer_id;
            x["offer_id"].set_valid(true);
            job_email(JOBS_GROUP_OFFER_PUBLIC, x, out);
            load_db_record(out, "SELECT *,id AS offer_id FROM members_jobs_offer WHERE id = %lu ", offer_id);
            out["status"] = "Offer sent to recipient";
        } else {
            out["status"] = "Unanble to create offer";
        }

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }

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

long WrenchSendJobsOfferGroup(CVars in, CVars &out) {
    logfmt(logINFO, "WrenchSendJobsOfferGroup()");

    long ret = PHP_API_BAD_PARAM;
    long sum_ret = 0;

    REQ_LONG(in, "member_id", 1, -1);
    REQ_LONG(in, "job_id", 1, -1);
    REQ_LONG(in, "group_id", 1, -1);
    //REQ_STRING (in, "email",   1, 59, "(.*)");	
    REQ_STRING(in, "job_description", 1, 5000, "(.*)");
    long bypass = REQ_LONG(in, "bypass", 1, -1);

    srand((unsigned) time(NULL));
    int r = rand();
    in["offer_code"] = 10000000 * r*r;

    long offer_id = 0;
    out = in;
    CVars x;
    CVars y;
    CVars z;
    CVars u;

    long total_member = 0;
    load_db_record(out, "SELECT count(id) AS m_count  "
                        " FROM members_job_groupmember "
                        " WHERE group_id = %lu  AND member_id= %lu", in["group_id"].Long(), in["member_id"].Long());

    // valid load of job needed
    total_member = out["m_count"].Long() + 0;
    if (total_member == 0) {
        out["status"] = "Empty members in group";
        out["status_message"] = "cannot_send_offer_to_empty_group";
        return ret;
    }

    // we need this job id
    // make sure job is valid
    if (load_db_record(y, " SELECT * FROM members_jobs "
                          " WHERE id =%lu AND status = 1", in["job_id"].Long())) {
        // valid load of job needed
    } else {
        out["status"] = "Unable to create offer";
        out["status_message"] = "cannot_find_valid_offer";
        return ret;
    }

    load_db_record(u,"SELECT code AS currency FROM currency WHERE country = '%s'", y["country"].c_str() );
    logfmt(logINFO, " The Currency code = %s", u["currency"].c_str());
    long wallet_id =  CheckWallet( in["member_id"].Long() , u);
    logfmt(logINFO, " The wallet_id = %lu", wallet_id);

    if (y["price"].Long() > 0) {
    } else {
        out["status"] = "Unable to create offer";
        return ret;
    } // no price zero for job on this path

    // Now do you have money to do this ....
    z["balance"] = "0";
    z["balance"].set_valid(true); // just initialize it
    if (load_db_record(z, " SELECT * FROM members_wallet WHERE id =%lu "
                          " AND member_id =%lu AND amount >= %lu",wallet_id, in["member_id"].Long(), y["price"].Long())) {

    } else {
        out["status"] = "Insufficient balance to create this offer";
        logfmt(logINFO, "Price2 = %lu Balance = %lu", y["price"].Long(), z["balance"].Long());
    }

    if (y["price"].Long() >= z["amount"].Long()) {
        out["status"] = "Insufficient balance to create this offer";
        logfmt(logINFO, "Price = %lu Balance = %lu", y["price"].Long(), z["balance"].Long());
        return ret;
    }

    logfmt(logINFO, "Price = %lu Balance = %lu", y["price"].Long() * total_member, z["amount"].Long());

    if (total_member > 2 && bypass == 0 ){
//        REQ_LONG(in, "member_id", 1, -1);
//        REQ_LONG(in, "job_id", 1, -1);
//        REQ_LONG(in, "group_id", 1, -1);
//        //REQ_STRING (in, "email",   1, 59, "(.*)");
//        REQ_STRING(in, "job_description", 1, 5000, "(.*)");
            CVars jj;
            jj["member_id"] = in["member_id"]; jj["member_id"].set_valid( true );
            jj["job_id"] = in["job_id"]; jj["job_id"].set_valid( true );
            jj["group_id"] = in["group_id"]; jj["group_id"].set_valid( true );
            jj["job_description"] = in["job_description"]; jj["job_description"].set_valid( true );
            jj["total_member"] = total_member; jj["total_member"].set_valid( true );
            out["planned_offer_id"] = insert_db_record(DBS_VALID, "group_offer_schedule", "group_offer_schedule_id_seq", jj);

            out["status_msg"] = "Offer is scheduled to be sent in few minutes";
            ret = PHP_CREATED_OK;
            return ret;
    }


    try {
        const PGresult *res = pgsql_query("SELECT email FROM members_job_groupmember "
                                          " WHERE group_id = %lu  "
                                          " AND member_id = %lu "
                                          " AND status=1", in["group_id"].Long(), in["member_id"].Long());
        if (res != NULL && pgsql_num_rows(res) > 0) {
            for (int i = 0, n = pgsql_num_rows(res); i < n; i++) {
                map<const char*, const char*>f = pgsql_fetch_assoc(res, i);
                if (f.empty()) continue;
                CVars rec;
                map_to_cvars(f, rec);

                rec["job_id"] = in["job_id"];
                rec["job_id"].set_valid(true);
                rec["job_description"] = in["job_description"];
                rec["job_description"].set_valid(true);
                rec["member_id"] = in["member_id"];
                rec["member_id"].set_valid(true);
                long call_ret = WrenchSendJobsOfferIndividual(rec, out);
                sum_ret = sum_ret + call_ret; // a way to know all came back positive
                if (call_ret == PHP_CREATED_OK) {
                    ret = PHP_CREATED_OK;
                }
            }

            if (ret == PHP_CREATED_OK && sum_ret == 0 ) {
                out["status_msg"] = "Completed";
                ret = PHP_CREATED_OK;
            }
            else{
               out["status_msg"] = "Completed";
               ret = sum_ret;
            }

        }
    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }

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

long WrenchJobsGroupList(CVars in, CVars &out) {
        long ret = PHP_API_BAD_PARAM;
        char vname[30];
        CVars rec;
        out = in;
        try {
             long member_id = REQ_LONG(in, "member_id", 1, -1);
            // long offset = REQ_LONG(in, "offset", 1, -1);
            // long limit = REQ_LONG(in, "limit", 1, -1);

             const PGresult *res = pgsql_query("SELECT * FROM members_job_group "
                                               " WHERE member_id= %lu AND status = 1 "
                                               " ORDER BY group_name ASC",member_id);
                    if (res != NULL && pgsql_num_rows(res) > 0) {
                                out["total_record"] = pgsql_num_rows(res);
                            for (int i = 0, n = pgsql_num_rows(res); i < n; i++) {
                                map<const char*, const char*>f = pgsql_fetch_assoc(res, i);
                                if (f.empty()) continue;
                                map_to_cvars(f, rec);
                                snprintf(vname, sizeof (vname), "group_uid_%05d", i);
                                out[vname] = rec["uid"];

                                snprintf(vname, sizeof (vname), "group_id_%05d", i);
                                out[vname] = rec["id"];

                                snprintf(vname, sizeof (vname), "group_name_%05d", i);
                                out[vname] = rec["group_name"];
                            }

                    }

                   const PGresult *res1 = pgsql_query("SELECT * FROM  members_job_groupmember "
                                                      " WHERE member_id= %lu AND status =1",member_id);
                          if (res1 != NULL && pgsql_num_rows(res1) > 0) {
                              out["gm_total_record"] = pgsql_num_rows(res1);
                              for (int i = 0, n = pgsql_num_rows(res1); i < n; i++) {
                                  map<const char*, const char*>f = pgsql_fetch_assoc(res1, i);
                                  if (f.empty()) continue;
                                  map_to_cvars(f, rec);
                                  snprintf(vname, sizeof (vname), "gm_uid_%05d", i);
                                  out[vname] = rec["uid"];

                                  snprintf(vname, sizeof (vname), "gm_group_id_%05d", i);
                                  out[vname] = rec["group_id"];

                                  snprintf(vname, sizeof (vname), "gm_firstname_%05d", i);
                                  out[vname] = rec["firstname"];

                                  snprintf(vname, sizeof (vname), "gm_lastname_%05d", i);
                                  out[vname] = rec["lastname"];

                                  snprintf(vname, sizeof (vname), "gm_email_%05d", i);
                                  out[vname] = rec["email"];
                              }
                          }


/*
wrenchboard=> SELECT group_id,count(id) FROM members_job_groupmember WHERE member_id = 1 GROUP BY group_id;
 group_id | count
----------+-------
       10 |     1
        1 |     1
        4 |     1
(3 rows)

wrenchboard=>
*/

                   const PGresult *res2 = pgsql_query("SELECT group_id,count(id) AS group_count "
                                                       " FROM members_job_groupmember WHERE member_id = %lu GROUP BY group_id",member_id);
                          if (res2 != NULL && pgsql_num_rows(res2) > 0) {
                              for (int i = 0, n = pgsql_num_rows(res2); i < n; i++) {
                                  map<const char*, const char*>f = pgsql_fetch_assoc(res2, i);
                                  if (f.empty()) continue;
                                  map_to_cvars(f, rec);

                                  snprintf(vname, sizeof (vname), "group_count_id_%d", rec["group_id"].Long());
                                  out[vname] = rec["group_count"];
                              }
                          }

                ret = PHP_API_OK;

            } catch (bad_parameter) {
                out["log_status"] = "Error WrenchJobsGroupList";
            }
            return ret;
}



long WrenchDeleteJobsGroup(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    try {
        REQ_LONG(in, "member_id", 1, -1);
        REQ_LONG(in, "group_id", 1, -1);
        pgsql_exec("UPDATE members_job_group SET status = 0 WHERE status = 1 AND member_id = %lu AND id = %lu", in["member_id"].Long(), in["group_id"].Long());
        ret = PHP_CREATED_OK;
        out["result"] = "OK";

        //#include "common_tool.h"
        CVars xx, yy;
        xx["member_id"] = in["member_id"]; xx["member_id"].set_valid( true );
        xx["title"] =  "A job was deleted"; xx["title"].set_valid( true );
        xx["description"] =   "A job was deleted"; xx["description"].set_valid( true );
        WrenchLogRecent(xx, yy);

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

long WrenchDeleteJobsGroupMember(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    try {
        REQ_LONG(in, "member_id", 1, -1);
        REQ_LONG(in, "group_id", 1, -1);
        REQ_LONG(in, "group_member_id", 1, -1);

        pgsql_exec("UPDATE members_job_groupmember SET status = 0 WHERE status = 1 AND member_id = %lu AND group_id = %lu AND id = %lu", in["member_id"].Long(), in["group_id"].Long(), in["group_member_id"].Long());
        ret = PHP_CREATED_OK;
        out["result"] = "OK";
    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

long WrenchCreateJobsGroup(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    logfmt(logINFO, "WrenchCreateJobsGroup()");
    ULONG group_id = 0;
    REQ_LONG(in, "member_id", 1, -1);
    REQ_STRING(in, "group_name", 1, 29, "(.*)");

    CVars x;

    try {
        if (load_db_record(out, "SELECT count(id) AS duplicate_name FROM members_job_group WHERE LOWER(group_name)=LOWER('%s') AND member_id =%lu AND status = 1", in["group_name"].c_str(), in["member_id"].Long())) {
            if (out["duplicate_name"].Long() > 0) {
            out["error_status_message"] = "Duplicate Name";
                return PHP_API_BAD_PARAM;
            } // return no duplicate on any active name
        } // this action blocks out duplicate 

        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["group_name"] = in["group_name"];
        x["group_name"].set_valid(true);
        const char * loc = getenv("REMOTE_ADDR");
        x["loc"] = loc;
        x["loc"].set_valid(true);
        group_id = insert_db_record(DBS_VALID, "members_job_group", "members_job_group_id_seq", x);

        if (group_id > 0) {
            ret = PHP_CREATED_OK;
            x["group_id"] = group_id;
            x["group_id"].set_valid(true);
            //JobAddedMail(x);
            load_db_record(out, "SELECT *,id AS group_id FROM members_job_group WHERE id = %lu ", group_id);
        } else {
            out["status"] = "Unable to create job group";
        }

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

long WrenchAddJobsGroupMember(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    logfmt(logINFO, "WrenchAddJobsGroupMember()");
    ULONG group_member_id = 0;
    REQ_LONG(in, "group_id", 1, -1);
    REQ_LONG(in, "member_id", 1, -1);
    REQ_STRING(in, "firstname", 1, 29, "(.*)");
    REQ_STRING(in, "lastname", 1, 29, "(.*)");
    REQ_STRING(in, "email", 1, 149, "(.*)");

    CVars x;

    try {
        x["member_id"] = in["member_id"];
        x["member_id"].set_valid(true);
        x["group_id"] = in["group_id"];
        x["group_id"].set_valid(true);
        x["firstname"] = in["firstname"];
        x["firstname"].set_valid(true);
        x["lastname"] = in["lastname"];
        x["lastname"].set_valid(true);
        x["email"] = in["email"];
        x["email"].set_valid(true);

        const char * loc = getenv("REMOTE_ADDR");
        x["loc"] = loc;
        x["loc"].set_valid(true);
        group_member_id = insert_db_record(DBS_VALID, "members_job_groupmember", "members_job_groupmember_id_seq", x);

        if (group_member_id > 0) {
            ret = PHP_CREATED_OK;
            x["group_member_id"] = group_member_id;
            x["group_member_id"].set_valid(true);
            //JobAddedMail(x);
            load_db_record(out, "SELECT *,id AS group_member_id FROM members_job_groupmember WHERE id = %lu AND member_id = %lu ", group_member_id, in["member_id"].Long());
        } else {
            out["status"] = "Uanble to create job group member";
        }

    } catch (bad_parameter) {
        out["log_status"] = "Invalid Log Action";
    }
    return ret;
}

long WrenchDeleteJobs(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    long member_id = REQ_LONG(in, "member_id", 1, -1);
    long job_id = REQ_LONG(in, "job_id", 1, -1);
    REQ_STRING(in, "job_uid", 15, 149, "(.*)");

    const PGresult *res = pgsql_query("SELECT *,id AS job_id FROM members_jobs WHERE id = %lu AND member_id = %lu  AND uid='%s'", job_id, member_id,in["job_uid"].c_str());
    if (res != NULL && pgsql_num_rows(res) > 0) {
        pgsql_exec("UPDATE members_jobs SET status = 0 WHERE status = 1 AND id = %lu AND member_id = %lu  AND uid='%s'", job_id, member_id,in["job_uid"].c_str());
        ret = PHP_CREATED_OK;
        out["status"] = "Job/Task Deleted";
    } else {
        out["status"] = "Valid Job/Task Not Found";
    }
    return ret;
}

long WrenchCreateJobs(CVars in, CVars &out) {
    long ret = PHP_API_BAD_PARAM;
    logfmt(logINFO, "WrenchCreateJobs()");
    ULONG job_id = 0;

    REQ_LONG(in, "member_id", 1, -1);
    REQ_LONG(in, "price", 1, -1);
    REQ_LONG(in, "timeline_days", 1, -1);
    REQ_STRING(in, "title", 5, 149, "(.*)");
    REQ_STRING(in, "country", 2, 3, "(.*)");
    REQ_STRING(in, "description", 5, 299, "(.*)");
    REQ_STRING (in, "job_detail",  4, 1440, "(.*)");
    const char * loc = getenv("REMOTE_ADDR");
    in["loc"] = loc;
    in["loc"].set_valid(true);

    if (in["price"].Long()<=0){
        out["status"] = "Unable to create job, price cannot be zero";
        return ret;
    }

    CVars x;
    x["member_id"] = in["member_id"];
    x["member_id"].set_valid(true);
    x["title"] = in["title"];
    x["title"].set_valid(true);
    x["price"] = in["price"];
    x["price"].set_valid(true);
    x["timeline_days"] = in["timeline_days"];
    x["timeline_days"].set_valid(true);
    x["description"] = in["description"];
    x["description"].set_valid(true);
    x["loc"] = in["loc"];
    x["loc"].set_valid(true);
    x["job_detail"] = in["job_detail"];
    x["job_detail"].set_valid(true);
    //country added
    x["country"] = in["country"];
    x["country"].set_valid(true);

    x["category"] = in["category"];
    x["category"].set_valid(true);

    x["banner"] = in["banner"];
    x["banner"].set_valid(true);

    x["depend_uid"] = in["depend_uid"];
    x["depend_uid"].set_valid(true);

    job_id = insert_db_record(DBS_VALID, "members_jobs", "members_jobs_id_seq", x);

    if (job_id) {
        ret = PHP_CREATED_OK;
        x["job_id"] = job_id;
        x["job_id"].set_valid(true);
        JobAddedMail(x);
        load_db_record(out, "SELECT *,id AS job_id, uid AS job_uid FROM members_jobs WHERE id = %lu ", job_id);

        CVars xxx, yy;
        xxx["member_id"] = in["member_id"]; xxx["member_id"].set_valid( true );
        xxx["title"] =  "A job was created"; xxx["title"].set_valid( true );
        xxx["description"] =   "Added a new job"; xxx["description"].set_valid( true );
        WrenchLogRecent(xxx, yy);

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

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

long WrenchEditJobs(CVars in, CVars &out) {
    logfmt(logINFO, "WrenchEditJobs()");

    long ret = PHP_API_BAD_PARAM;
      ULONG job_id = 0;

     long member_id = REQ_LONG(in, "member_id", 1, -1);
      job_id = REQ_LONG(in, "job_id", 1, -1);
      REQ_STRING(in, "job_uid", 15, 149, "(.*)");
      REQ_LONG(in, "timeline_days", 1, -1);
      REQ_STRING(in, "title", 5, 149, "(.*)");
      REQ_STRING(in, "description", 5, 299, "(.*)");
      REQ_STRING (in, "job_detail",  4, 1440, "(.*)");
      const char * loc = getenv("REMOTE_ADDR");
      in["loc"] = loc;
      in["loc"].set_valid(true);

      if (in["price"].Long()<=0){
          out["status"] = "Unable to update job, price cannot be zero";
          return ret;
      }

        const PGresult *res = pgsql_query("SELECT *,id AS job_id FROM members_jobs WHERE id = %lu AND member_id = %lu AND uid='%s'", job_id, member_id,in["job_uid"].c_str());
        if (res != NULL && pgsql_num_rows(res) > 0) {
            // good to continue
                map<const char*, const char*>f = pgsql_fetch_assoc(res, 0);
                if (!f.empty()) {
                    CVars rec;
                    map_to_cvars(f, rec);
                    job_id = rec["job_id"];
                }
        } else {
            out["status"] = "Valid Job/Task Not Found";
            return ret;
        }


      CVars x;
      x["title"] = in["title"];
      x["title"].set_valid(true);
      x["price"] = in["price"];
      x["price"].set_valid(true);
      x["timeline_days"] = in["timeline_days"];
      x["timeline_days"].set_valid(true);
      x["description"] = in["description"];
      x["description"].set_valid(true);
      x["loc"] = in["loc"];
      x["loc"].set_valid(true);
      x["job_detail"] = in["job_detail"];
      x["job_detail"].set_valid(true);

      x["category"] = in["category"];
      x["category"].set_valid(true);

        if ( in["banner"] != ""){
            x["banner"] = in["banner"];
            x["banner"].set_valid(true);
        }

     // job_id = insert_db_record(DBS_VALID, "members_jobs", "members_jobs_id_seq", x);

      if (job_id> 0) {
                update_db_record(DBS_VALID, "members_jobs", x, job_id) ;
                load_db_record(out, "SELECT *,id AS job_id FROM members_jobs WHERE id = %lu ", job_id);
                ret = PHP_UPDATED_OK;

                CVars xxx, yy;
                xxx["member_id"] = in["member_id"]; xxx["member_id"].set_valid( true );
                xxx["title"] =  "A job was updated"; xxx["title"].set_valid( true );
                xxx["description"] =   "A job was updated"; xxx["description"].set_valid( true );
                WrenchLogRecent(xxx, yy);

      } else {
          out["status"] = "Unable to create job";
      }
    logfmt(logINFO, "/WrenchEditJobs()");
    return ret;
}

//******************************************************************************
/*
vi:ts=2
 */

