/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vas.webservices;

import com.vas.sicbosubncom.wsfw.obj.PointTotalObj;
import com.vas.sicbosubncom.wsfw.obj.UserInfo;
import com.vas.sicbosubncom.wsfw.obj.ChargeLog;
import com.vas.sicbosubncom.wsfw.obj.RankingObj;
import com.vas.sicbosubncom.wsfw.obj.Request;
import com.vas.sicbosubncom.wsfw.obj.ProductInfo;
import com.vas.sicbosubncom.wsfw.obj.TransactionLog;
import com.vas.sicbosubncom.wsfw.obj.SmsMtObj;
import com.vas.sicbosubncom.wsfw.obj.AccountInfo;
import com.vas.sicbosubncom.wsfw.obj.Response;
import com.vas.sicbosubncom.wsfw.obj.SpinGift;
import com.vas.sicbosubncom.wsfw.obj.RegisterInfo;
import com.vas.sicbosubnc.wsfw.common.Common;
import com.vas.sicbosubnc.wsfw.common.Encrypt;
import com.vas.sicbosubnc.wsfw.common.MessageResponse;
import com.vas.sicbosubnc.wsfw.common.WebserviceAbstract;
import com.vas.sicbosubnc.wsfw.common.WebserviceManager;
import com.vas.sicbosubnc.wsfw.database.WsProcessUtils;
import com.vas.sicbosubnc.wsfw.obj.draw.LuckySprin;
import com.vas.sicbosubnc.wsfw.obj.draw.PrizeObj;
import com.vas.sicbosubnc.wsfw.obj.draw.PrizeWinner;
import com.vas.sicbosubnc.wsfw.obj.draw.SpinResultObj;

import com.vas.sicbosubnc.wsfw.services.WSProcessor;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.WebServiceContext;

import org.apache.log4j.Logger;
import sun.misc.BASE64Encoder;

/**
 * @author Sungroup
 */
@WebService
public class SicboSubWs extends WebserviceAbstract {

    public WsProcessUtils db;
    private StringBuilder br = new StringBuilder();
    //private Exchange exchange;
    private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
    private SimpleDateFormat fullDf = new SimpleDateFormat("yyyyMMddHHmmss");
    private SimpleDateFormat reqDf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    public WSProcessor ws;
    
    @Resource
    protected WebServiceContext ctx;
    
    public SicboSubWs() throws Exception {
        super("SicboSubWs");
        db = new WsProcessUtils("dbProcess", logger);
        ws = new WSProcessor(logger, "../etc/webservice.cfg", "../etc/database.xml");
        if (Common.iLoadConfig) {
            Common.listConfig = db.getConfig("PROCESS");
            MessageResponse.setMessage(Common.listConfig);
            logger.info("LIST CONFIG:\n" + Common.listConfig);
            Common.listProduct = db.iLoadPackage();
            //Common.mapPrize = db.loadPrize();
            Common.mapMpsConfig = db.loadMpsConfig();
            Common.loadConfig();
        }
    }

    //
    // FOR MPS
    //
    public Response renewMps(String msisdn, ProductInfo product) {
        Response response = new Response();
        response.setErrorCode(SUCCESS);
        try {
            msisdn = formatMsisdn(msisdn);
            // after this, only one package returned
            List<RegisterInfo> listReg = db.getRegisterNotCheckStatusInfo(msisdn, product.getProductName());
            if (listReg == null || listReg.isEmpty()) {
                logger.error("Renew but not registered: " + msisdn + " package: " + product.getProductName());
//                response.setErrorCode(Common.ErrorCode.NOT_REGISTERED);
                response.setErrorCode(Common.ErrorCode.SUCCESS);
                response.setContent(MessageResponse.getDefaultMessage(Common.Message.NOT_REGISTERED, logger));
                return response;
            }
            // remove all package buy_code, just only packages daily
            RegisterInfo regInfo = listReg.get(0);

            ProductInfo productInfo = getProductByName(regInfo.getProductName());
            if (productInfo == null || productInfo.getProductName() == null) {
                logger.error("Error product info is not existed: " + regInfo.getProductName());
                response.setErrorCode(Common.ErrorCode.SYSTEM_ERROR);
                response.setContent(MessageResponse.getDefaultMessage(Common.Message.SYSTEM_FAIL, logger));
                return response;
            }
            double fee = productInfo.getFee();
            logger.info("Renew pending success " + msisdn + ", fee " + fee + ", account " + msisdn + ", package: " + product.getProductName());

            // insert register
            Timestamp expire = getExpireTime(productInfo);
            regInfo.setExpireTime(expire);
            regInfo = updateRegRenew(regInfo, productInfo);
            db.updateRenewReg(regInfo);

            //insert chargelog
            if (fee > 0) {
                ChargeLog chargeLog = new ChargeLog();
                chargeLog.setFee(fee);
                chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                chargeLog.setMsisdn(msisdn);
                chargeLog.setDescription("Renew " + regInfo.getProductName());
                chargeLog.setStatus(Common.Constant.RENEW_STATUS);
                db.iInsertChargeLog(chargeLog);
            }
            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
            // send message
            String message;
            message = MessageResponse.get(Common.Message.RENEW_SUCCESS,
                    Common.Message.RENEW_SUCCESS + "_" + regInfo.getProductName(), logger);
            message = message.replace("%fee%", String.valueOf(fee));
            message = message.replaceAll("%expire%", sdf.format(expire));
//                        SmsMtObj mt = new SmsMtObj();
//                        mt.setMsisdn(msisdn);
//                        mt.setChannel(Common.CHANNEL);
//                        mt.setMessage(message);
//                        db.insertMt(mt);
            response.setErrorCode(Common.ErrorCode.SUCCESS);
            response.setContent(message);
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }
        response.setErrorCode(Common.ErrorCode.SUCCESS);
        return response;
    }

    public Response registerByMps(String msisdn, ProductInfo productInfo, int fee, String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);
//        Timestamp reqTime = new Timestamp(System.currentTimeMillis());

        try {
            // check existed
            AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, productInfo.getProductName());
//            UserProfile userProfile = db.iGetUserProfileByMsisdn(msisdn);
            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                accountInfo = db.iGetAccount(msisdn);
            }
            if (accountInfo == null) {
                logger.error("Error check exist account: " + msisdn);
                response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
//                response.setErrorCode(Common.ErrorCode.SUCCESS);
                String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
                response.setContent(message);
                return response;
            }
            List<RegisterInfo> listReg = db.getRegisterInfo(msisdn, productInfo.getProductName());
            if (listReg != null && !listReg.isEmpty()) {
                logger.info("Already registered: " + msisdn + " -> cancel service");
                db.disableAutoExtend(listReg.get(0).getRegisterId());
            }
            List<RegisterInfo> listRegInday = null;
            boolean registered = false;
            listRegInday = db.getRegisterInday(msisdn, productInfo.getProductName());
            if (listRegInday != null && listRegInday.size() > 0) {
                registered = true;
                db.addTurnSpin(msisdn,productInfo.getNumberSpin());
            }

            logger.info("Register success " + msisdn + ", fee " + fee + ", account " + accountInfo.getMsisdn() + ", pack = " + productInfo.getProductName());

            boolean isCreated = true;
            // create account
            String password = generateValidateCode(4);
            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                isCreated = false;
                String encyptedPassword = Encrypt.getHashCode(msisdn, password, logger);
                db.insertAccountUser(msisdn, password, "USSD", productInfo.getProductName());
            }

            RegisterInfo reg;
            if (!registered) {
                // insert register
                logger.info("create new reg_info " + msisdn);
                reg = new RegisterInfo();
                reg.setMsisdn(msisdn);
                reg.setProductName(productInfo.getProductName());
                reg.setExpireTime(getExpireTime(productInfo));
                reg.setServiceId(Integer.parseInt("1"));
                reg.setChannel("MPS");
                reg = updateRegRenew(reg, productInfo);
                db.iInsertRegisterInfo(reg);
                
            } else {
                logger.info("register again reg_info " + msisdn);
                reg = listRegInday.get(0);
                reg.setExpireTime(getExpireTime(productInfo));
                db.iInsertRegisterInfo(reg);
            }

            //insert chargelog
            if (fee > 0) {
                ChargeLog chargeLog = new ChargeLog();
                chargeLog.setFee(productInfo.getFee());
                chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                chargeLog.setMsisdn(msisdn);
                chargeLog.setDescription("Register " + productInfo.getProductName());
                chargeLog.setStatus(Common.Constant.REGISTER_STATUS);
                db.iInsertChargeLog(chargeLog);
            }
                        

            // send message
            String message = "";
            if (!isCreated) {
                message = MessageResponse.get(Common.Message.CREATE_ACCOUNT_SUCCESS, logger);
                message = message.replaceAll("%password%", password);
                SmsMtObj mt = new SmsMtObj();
                mt.setMsisdn(msisdn);
                mt.setChannel(Common.CHANNEL);
                mt.setMessage(message);
                db.insertMt(mt);
            }
            message = MessageResponse.get(Common.Message.REGISTER_SUCCESS,
                    Common.Message.REGISTER_SUCCESS, logger);
            message = message.replaceAll("%fee%", String.valueOf(productInfo.getFee()));
            message = message.replaceAll("%spin%", String.valueOf(productInfo.getNumberSpin()));

            if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_HEALTH)) {
                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_HEALTH);
                message = message.replaceAll("%package%", Common.Constant.REGISTER_DAILY_HEALTH + "");
                message = message.replaceAll("%describer%", Common.Constant.DESCRIBER_NEWS + "");

            } else if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_LOT)) {
                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_LOT);
                message = message.replaceAll("%package%", Common.Constant.REGISTER_DAILY_LOT + "");
                message = message.replaceAll("%describer%", Common.Constant.DESCRIBER_LOT + "");

            } else if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_NEWS)) {
                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_NEWS);
                message = message.replaceAll("%package%", Common.Constant.REGISTER_DAILY_NEWS + "");
                message = message.replaceAll("%describer%", Common.Constant.DESCRIBER_HEALTH + "");
            }

            response.setErrorCode(Common.ErrorCode.SUCCESS);
            response.setContent(message);

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }
        response.setErrorCode(Common.ErrorCode.SUCCESS);
        return response;
    }

    public Response cancelServiceMps(String msisdn, ProductInfo productInfo, String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            // check existed
            msisdn = formatMsisdn(msisdn);
            List<RegisterInfo> listReg = db.getRegisterInfo(msisdn, productInfo.getProductName());
            if (listReg == null) {
                logger.error("Error check exist account: " + msisdn);
                response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
                response.setContent("Error database!");
                return response;
            } else if (listReg.isEmpty()) {
                logger.info("Not registered: " + msisdn + " -> success");
//                response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_REGISTERED);
//                response.setContent("Not registered");
                String message = MessageResponse.get(Common.Message.DESTROY_ACCOUNT_SUCCESS, logger);
                response.setErrorCode(Common.ErrorCode.SUCCESS);
                response.setContent(message);
                return response;
            }
            boolean res = db.disableAutoExtend(listReg.get(0).getRegisterId());

            if (res) {
                ChargeLog chargeLog = new ChargeLog();
                chargeLog.setFee(productInfo.getFee());
                chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                chargeLog.setMsisdn(msisdn);
                chargeLog.setDescription("Cancel " + productInfo.getProductName());
                chargeLog.setStatus(Common.Constant.CANCEL_STATUS);
                db.iInsertChargeLog(chargeLog);
                // send message
                String message = MessageResponse.get(Common.Message.DESTROY_ACCOUNT_SUCCESS, logger);
                response.setContent(message);

                // return
                response.setErrorCode(Common.ErrorCode.SUCCESS);
                logger.info("Cancel success" + msisdn + ", account " + msisdn + ", pack = " + productInfo.getProductName());
            } else {
                // return
                response.setErrorCode(Common.ErrorCode.FAILURE);
                logger.info("Cancel failure " + msisdn + ", account " + msisdn + ", pack = " + productInfo.getProductName());
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }
        response.setErrorCode(Common.ErrorCode.SUCCESS);
        return response;
    }

    @WebMethod(operationName = "heartbeat")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public String heartBeat() {
        Response response = new Response();
        response.setErrorCode(Common.ErrorCode.SUCCESS);
        return response.getErrorCode();
    }
    
    @WebMethod(operationName = "subRequest")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public String subRequest(
            @WebParam(name = "username") String wsUser,
            @WebParam(name = "password") String wsPass,
            @WebParam(name = "serviceid") String serviceid,
            @WebParam(name = "msisdn") String msisdn,
            @WebParam(name = "chargetime") String chargetime,
            @WebParam(name = "params") String params,
            @WebParam(name = "mode") String mode,
            //            @WebParam(name = "subServiceName") String subServiceName,
            @WebParam(name = "amount") String fee,
            @WebParam(name = "transid") String transid) {

        Response response = new Response();

        response.setErrorCode(SUCCESS);
        // translog
        Timestamp reqTime = new Timestamp(System.currentTimeMillis());
        TransactionLog transLog = new TransactionLog();
        transLog.setTransactionId(transid);
        transLog.setCommand(params);
        transLog.setMsisdn(msisdn);
        transLog.setRequestTime(reqTime);
        transLog.setRequest(serviceid + "|" + msisdn + "|" + chargetime + "|" + params + "|" + fee);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("subRequest Params:").
                    append("\nserviceid:").append(serviceid).
                    append("\nmsisdn:").append(msisdn).
                    append("\nchargetime:").append(chargetime).
                    append("\namount:").append(fee).
                    append("\nparams:").append(params).
                    append("\nmode:").append(mode).
                    append("\ntransactionId:").append(transid);
            logger.info(br);

            Request request = new Request();
            request.setUser(msisdn);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (params == null || params.length() == 0) {
                logger.info("params is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("params is null");
            } 
            else if (transid == null || transid.length() == 0) {
                logger.info("params is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("transactionId is null");
            }
            if (!Objects.equals(mode, "REAL")) {
                    response.setErrorCode(Common.ErrorCode.SUCCESS);
                    return response.getErrorCode();
            }
            if (SUCCESS.equals(response.getErrorCode())) {
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                    return response.getErrorCode() + "|" + response.getContent();
                } else {
                    msisdn = formatMsisdn(msisdn);
                    ProductInfo productInfo = getProductByName(serviceid);
                    if (productInfo == null || productInfo.getProductName() == null) {
                        logger.info("serviceid is wrong: " + serviceid);
                        response.setErrorCode(PARAM_NOT_VALID);
                        response.setContent("subServiceName is wrong");
                    } else {
                        if (params.equals("0")) {
                            int amount = Integer.parseInt(fee);
                            // register
//                        ProductInfo product = db.iLoadPackageByName(subServiceName);
                            response = registerByMps(msisdn, productInfo, amount, "1");
                            logger.info("params: " + params +"registerByMps:SubRequest");
                        } else if (params.equals("1")) {
                            // unsub
                            response = cancelServiceMps(msisdn, productInfo, "1");
                            logger.info("params: " + params +"cancelServiceMps:SubRequest");

                        } else {
                            logger.info("Unknown params: " + params);
                            response.setErrorCode(PARAM_NOT_VALID);
                            response.setContent("Unknown params: " + params);
                        }
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        } finally {
            try {
                transLog.setErrorCode(response.getErrorCode());
                transLog.setResponse(response.toString());
                transLog.setResponseTime(new Timestamp(System.currentTimeMillis()));
                db.insertTransLog1(transLog);
            } catch (Exception ex) {
                logger.error("Error insert log", ex);
            } finally {
            }
        }

        return response.getErrorCode();
    }

    @WebMethod(operationName = "receiveresult")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public String receiveresult(
            @WebParam(name = "username") String wsUser,
            @WebParam(name = "password") String wsPass,
            @WebParam(name = "serviceid") String serviceid,
            @WebParam(name = "msisdn") String msisdn,
            @WebParam(name = "chargetime") String chargetime,
            @WebParam(name = "params") String params,
            @WebParam(name = "mode") String mode,
            @WebParam(name = "amount") String fee,
            @WebParam(name = "transid") String transid) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);
        // translog
        Timestamp reqTime = new Timestamp(System.currentTimeMillis());
        TransactionLog transLog = new TransactionLog();
        transLog.setTransactionId(transid);
        transLog.setCommand(params);
        transLog.setMsisdn(msisdn);
        transLog.setRequestTime(reqTime);
        transLog.setRequest(serviceid + "|" + msisdn + "|" + chargetime + "|" + params + "|" + fee);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("receiveresult Params:").
                    append("\nmsisdn:").append(msisdn).
                    append("\nparams:").append(params).
                    append("\nchargetime:").append(chargetime).
                    append("\nserviceid:").append(serviceid).
                    append("\ntransid:").append(transid).
                    append("\nmode:").append(mode).
                            append("\namount:").append(fee);
            logger.info(br);

            Request request = new Request();
            request.setUser(msisdn);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (params == null || params.length() == 0) {
                logger.info("params is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("params is null");
            } 
            else if (fee == null || fee.length() == 0) {
                logger.info("amount is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("amount is null");
            } else if (transid == null || transid.length() == 0) {
                logger.info("transactionId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("transactionId is null");
            }
            if (!Objects.equals(mode, "REAL")) {
                            response.setErrorCode(Common.ErrorCode.SUCCESS);
                            return response.getErrorCode();
            }
            if (SUCCESS.equals(response.getErrorCode())) {
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                    return response.getErrorCode() + "|" + response.getContent();
                } else {
                    msisdn = formatMsisdn(msisdn);
                    if (params.equals("0")) {
                        ProductInfo productInfo = getProductByName(serviceid);
                        response = renewMps(msisdn, productInfo);
                    } else if (params.equals("1")) {
                        logger.info("Renew fail not enough money: " + msisdn);
                        logger.info("Unknown params: " + params);
                        response.setErrorCode(SUCCESS);
                        response.setContent("Unknown params: " + params);
                    } else {
                        logger.info("Renew fail: " + msisdn);
                        logger.info("Unknown params: " + params);
                        response.setErrorCode(PARAM_NOT_VALID);
                        response.setContent("Unknown params: " + params);
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        } finally {
            try {
                transLog.setErrorCode(response.getErrorCode());
                transLog.setResponse(response.toString());
                transLog.setResponseTime(new Timestamp(System.currentTimeMillis()));
                db.insertTransLog1(transLog);
            } catch (Exception ex) {
                logger.error("Error insert log", ex);
            } finally {
            }
        }

        return response.getErrorCode();
    }

    public void processAfterCharge(String msisdn, int fee) {
        List<RegisterInfo> listReg = db.getRegisterInfoAll(msisdn);
        if (listReg == null || listReg.isEmpty()) {
            // unsub
            int spinNum = (int) (fee / Common.SPIN_FEE);
            // update spin_gift
            List<SpinGift> listSg = db.getSpinGift(msisdn);
            if (listSg != null && listSg.size() > 0) {
                // update spin gift
                SpinGift sg = listSg.get(0);
                sg.setGiftMsisdn(msisdn);
                sg.setNumberSpin(sg.getNumberSpin() + (int) spinNum);
                db.iUpdateSpinGift(sg);
            } else {
                // insert new spin gift
                SpinGift sg = new SpinGift();
                sg.setMsisdn(msisdn);
                sg.setGiftMsisdn(msisdn);
                sg.setNumberSpin(spinNum);
                db.iInsertSpinGift(sg);
            }

            String message = MessageResponse.get(Common.Message.BUY_SPIN_UNSUB_SUCCESS, logger);
            message = message.replace("%fee%", fee + "");
            message = message.replace("%spin%", spinNum + "");
//            SmsMtObj mt = new SmsMtObj();
//            mt.setMsisdn(msisdn);
//            mt.setChannel(Common.CHANNEL);
//            mt.setMessage(message);
//            db.insertMt(mt);

            // update ranking
            updateRanking(msisdn, Common.SubType.UNSUB, spinNum, Common.RankType.BOUGHT, Common.PeriodPrize.WEEKLY);
            updateRanking(msisdn, Common.SubType.UNSUB, spinNum, Common.RankType.BOUGHT, Common.PeriodPrize.MONTHLY);
        } else {
            // for sub
            int spinInt = fee * Common.ADD_SPIN_TIMES / Common.ADD_SPIN_FEE;
            // update spin
            db.updateAddMoreTimes(listReg.get(0).getRegisterId(), spinInt);

            // send message
            String message = MessageResponse.get(Common.Message.BUY_SPIN_SUB_SUCCESS, logger);
            message = message.replaceAll("%fee%", fee + "");
            message = message.replaceAll("%spin%", spinInt + "");
//            SmsMtObj mt = new SmsMtObj();
//            mt.setMsisdn(msisdn);
//            mt.setChannel(Common.CHANNEL);
//            mt.setMessage(message);
//            db.insertMt(mt);

            // update ranking
            updateRanking(msisdn, Common.SubType.SUB, spinInt, Common.RankType.BOUGHT, Common.PeriodPrize.WEEKLY);
            updateRanking(msisdn, Common.SubType.SUB, spinInt, Common.RankType.BOUGHT, Common.PeriodPrize.MONTHLY);
        }
    }

    //    --------- FOR REGISTER FROM WEB ---------------
    @WebMethod(operationName = "wsRegisterSubOtp")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsRegisterSubOtp(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsRegisterSubOtp Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\nMsisdn:").append(msisdn).
                    append("\nserviceId:").append(serviceId).
                    append("\nPackageName:").append(packageName);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
//------danh cho thị trường không có otp ------------------
                // kiem tra thong tin dang nhap
                
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    List<RegisterInfo> listRegInday = db.getRegisterInday(msisdn, packageName);
                    if (listRegInday != null && !listRegInday.isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ALREADY_REGISTER);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ALREADY_REGISTERED, logger));
                    } else {
                        // da dang ki (status = 1) nhung he thong chua kip gia han
                        ProductInfo productInfo = getProductByName(packageName);
                        String resultPaid = "0";
                        int fee = (int) productInfo.getFee();
                        boolean registered = false;
                        if (!db.checkRegistered(msisdn, productInfo.getProductName())) {
                            // new user
                            fee = 0;
                        } else {
                            if (listRegInday != null && !listRegInday.isEmpty()) {
                                fee = 0;
                                registered = true;
                            }
                        }
                        // neu khong co buoc otp thi tao them requestId ban di
                        String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
                        logger.info("after get product info " + fee);
                        // right -----------------------------------------------
                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
                        
                        String errorCode = resultPaid.split("\\|")[0];
                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
//                            logger.info("Register success success " + msisdn + ", fee " + fee);
                            Timestamp expireTime = getExpireTime(productInfo);
                            // check registered
                            RegisterInfo reg;
                            if (!registered) {
                                // insert register
                                reg = new RegisterInfo();
                                reg.setMsisdn(msisdn);
                                reg.setProductName(productInfo.getProductName());
                                reg.setExpireTime(expireTime);
//                                reg.setServiceId(Integer.parseInt("1"));
                                reg.setServiceId(productInfo.getProductId());
                                reg.setChannel("WEB");
                                reg = updateRegRenew(reg, productInfo);
                                db.iInsertRegisterInfo(reg);
                                db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                            } else {
                                reg = listRegInday.get(0);
                                db.iInsertRegisterInfo(reg);
                            }

                            //insert chargelog
                            if (fee > 0) {
                                ChargeLog chargeLog = new ChargeLog();
                                chargeLog.setFee(productInfo.getFee());
                                chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                                chargeLog.setMsisdn(msisdn);
                                chargeLog.setDescription("Register " + packageName);
                                chargeLog.setStatus(Common.Constant.REGISTER_STATUS);
                                db.iInsertChargeLog(chargeLog);
                            }

                            // create a new account_user for this user
                            boolean isCreated = true;
                            // check existed
                            AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                                accountInfo = db.iGetAccount(msisdn);
                            }
                            // create account
                            String password = generateValidateCode(4);
                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                                isCreated = false;
                                String encyptedPassword = Encrypt.getHashCode(msisdn, password, logger);
                                logger.info("Create account success " + msisdn);
                                db.insertAccountUser(msisdn, password, "WEB", serviceId);
                            }
                            // send message
                            String message = "";
                            if (!isCreated) {
                                message = MessageResponse.get(Common.Message.CREATE_ACCOUNT_SUCCESS, logger);
                                message = message.replaceAll("%password%", password);
                                SmsMtObj mt = new SmsMtObj();
                                mt.setMsisdn(msisdn);
                                mt.setChannel(Common.CHANNEL);
                                mt.setMessage(message);
                                db.insertMt(mt);
                            }
                            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                            // send message
                            message = MessageResponse.get(Common.Message.REGISTER_SUCCESS,
                                    Common.Message.REGISTER_SUCCESS, logger);
                            message = message.replace("%fee%", productInfo.getFee() + "");
                            message = message.replace("%spin%", productInfo.getNumberSpin() + "");

                            // check user have registered in the past
                            if (!db.checkRegisteredForTheFirstTime(msisdn,String.valueOf(productInfo.getProductId()) )) {
                                response.setErrorCode(Common.ErrorCode.SUCCESS_FOR_THE_FIRST_TIME_REGISTER);
                            } else {
                                response.setErrorCode(Common.ErrorCode.SUCCESS);
                            }

                            response.setContent(message);
                        } 
                        else {
                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
                        }
                    }
                }
                
//---------------------ket thuc danh cho natcom -------------------------------------------------
                
//-------------- bat dau danh cho thi truong co dung otp    ---------------------------------------           
                 
//                userInfo = authenticate(wsUser, wsPass, ip);
//                if (userInfo == null || userInfo.getWsUserId() <= 0) {
//                    response.setErrorCode(WRONG_PASSWORD);
//                    response.setContent("Authenticate fail!");
//                } else {
//                    msisdn = formatMsisdn(msisdn);
//                    List<RegisterInfo> listReg = db.getRegisterInday(msisdn, packageName);
//                    if (listReg != null && !listReg.isEmpty()) {
//                        response.setErrorCode(Common.ErrorCode.ALREADY_REGISTER);
//                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ALREADY_REGISTERED, logger));
//                    } else {
//                        ProductInfo productInfo = getProductByName(packageName);
//                        String resultPaid = "0";
//                        int fee = (int) productInfo.getFee();
//                        // not waiting confirm
//                        String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
//                        logger.info("REQ: " + REQ);
//                        logger.info("after get product info " + fee);
//
//                        // right -----------------------------------------------
//                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
//                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
//                            logger.info("Create otp success " + msisdn + ", fee " + fee);
//
//                            // send message
//                            String message = MessageResponse.get(Common.Message.REGISTER_WAIT_CONFIRM + "_" + productInfo.getProductName(),
//                                    Common.Message.REGISTER_WAIT_CONFIRM, logger);
//
//                            response.setErrorCode(Common.ErrorCode.WAITING_OTP);
//                            response.setContent(message);
//                            response.setResultCode(REQ);
//                        } else {
//                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
//                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
//                        }
//                    }
//                }
                
// -------------Ket thuc danh cho thi truong có otp------------------
            }
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }

    @WebMethod(operationName = "wsRegisterSubConfirm")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsRegisterSubConfirm(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "RequestId") String requestId,
            @WebParam(name = "Otp") String otp,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsRegisterSubConfirm Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\nMsisdn:").append(msisdn).
                    append("\nPackageName:").append(packageName).
                    append("\nserviceId:").append(serviceId).
                    append("\nOtp:").append(otp);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (otp == null || otp.length() == 0) {
                logger.info("otp is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("otp is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("otp is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    List<RegisterInfo> listRegInday = db.getRegisterInday(msisdn, packageName);
                    if (listRegInday != null && !listRegInday.isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ALREADY_REGISTER);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ALREADY_REGISTERED, logger));
                    } else {
                        // da dang ki (status = 1) nhung he thong chua kip gia han
                        ProductInfo productInfo = getProductByName(packageName);
                        String resultPaid = "0";
                        int fee = (int) productInfo.getFee();
                        serviceId = String.valueOf(productInfo.getProductId());
                        boolean registered = false;
                        if (!db.checkRegistered(msisdn, productInfo.getProductName())) {
                            // new user
                            fee = 0;
                        } else {
                            if (listRegInday != null && !listRegInday.isEmpty()) {
                                fee = 0;
                                registered = true;
                            }
                        }
                        
                        resultPaid = ws.registerMpsConfirm(msisdn, fee, otp, requestId, productInfo.getProductName());
                        String errorCode = resultPaid.split("\\|")[0];
                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
                            logger.info("Register success success " + msisdn + ", fee " + fee);
                            Timestamp expireTime = getExpireTime(productInfo);
                            // check registered
                            RegisterInfo reg;
                            if (!registered) {
                                // insert register
                                reg = new RegisterInfo();
                                reg.setMsisdn(msisdn);
                                reg.setProductName(productInfo.getProductName());
                                reg.setExpireTime(expireTime);
                                reg.setServiceId(Integer.parseInt("1"));
                                reg.setChannel("WEB");
                                reg = updateRegRenew(reg, productInfo);
                                db.iInsertRegisterInfo(reg);
                            } else {
                                reg = listRegInday.get(0);
                                db.iInsertRegisterInfo(reg);
                            }

                            //insert chargelog
                            if (fee > 0) {
                                ChargeLog chargeLog = new ChargeLog();
                                chargeLog.setFee(productInfo.getFee());
                                chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                                chargeLog.setMsisdn(msisdn);
                                chargeLog.setDescription("Register " + packageName);
                                chargeLog.setStatus(Common.Constant.REGISTER_STATUS);
                                db.iInsertChargeLog(chargeLog);
                            }
                            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                            // create a new account_user for this user
                            boolean isCreated = true;
                            // check existed
                            AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, productInfo.getProductName());
                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                                accountInfo = db.iGetAccount(msisdn);
                            }
                            // create account
                            String password = generateValidateCode(4);
                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                                isCreated = false;
                                String encyptedPassword = Encrypt.getHashCode(msisdn, password, logger);
                                logger.info("Create account success " + msisdn);
                                db.insertAccountUser(msisdn, password, "WEB", productInfo.getProductName());
                            }
                            // send message
                            String message = "";
                            if (!isCreated) {
                                message = MessageResponse.get(Common.Message.CREATE_ACCOUNT_SUCCESS, logger);
//                                message = message.replace("%fee%", fee + "");
                                message = message.replaceAll("%password%", password);
//                                message = message.replaceAll("%expire%", sdf.format(reg.getExpireTime()));
                                SmsMtObj mt = new SmsMtObj();
                                mt.setMsisdn(msisdn);
                                mt.setChannel(Common.CHANNEL);
                                mt.setMessage(message);
                                db.insertMt(mt);
                            }

                            // send message
                            message = MessageResponse.get(Common.Message.REGISTER_SUCCESS,
                                    Common.Message.REGISTER_SUCCESS, logger);
                            message = message.replace("%fee%", productInfo.getFee() + "");
                            message = message.replace("%spin%", productInfo.getNumberSpin() + "");
                            // check user have registered in the past
                            if (!db.checkRegisteredForTheFirstTime(msisdn, serviceId)) {
                                response.setErrorCode(Common.ErrorCode.SUCCESS_FOR_THE_FIRST_TIME_REGISTER);
                            } else {
                                response.setErrorCode(Common.ErrorCode.SUCCESS);
                            }

                            response.setContent(message);
                        }
                        else {
                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
                        }
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }

    @WebMethod(operationName = "wsDisableRegister")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsDisableRegister(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "msisdn") String msisdn,
            @WebParam(name = "packName") String packName) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsDisableRegister Params:\n").
                    append("User:").append(msisdn).
                    append("\npackName:").append(packName);
            logger.info(br);

            Request request = new Request();
            request.setUser(msisdn);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (packName == null) {
                logger.info("packName is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("packName is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    // check existed
                    ProductInfo productInfo = getProductByName(packName);
                    AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn,productInfo.getProductName());
                    if (accountInfo == null) {
                        logger.error("Error check exist account: " + msisdn);
                        response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
                        response.setContent("Error database!");
                    } else if (accountInfo.getMsisdn() == null) {
                        logger.info("Account not existed: " + msisdn);

                        String message = MessageResponse.get(Common.Message.ACCOUNT_NOT_EXISTED + "_" + packName, Common.Message.ACCOUNT_NOT_EXISTED, logger);
                        SmsMtObj mt = new SmsMtObj();
                        mt.setMsisdn(msisdn);
                        mt.setChannel(Common.CHANNEL);
                        mt.setMessage(message);
                        db.insertMt(mt);

                        response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_EXISTED);
                        response.setContent(message);
                    } else {
                        String rsCancelMps = "0";
                        // get register
                        if (packName.equals("ALL")) {
                            List<RegisterInfo> regInfo = db.getRegisterInfoAll(msisdn);
                            if (regInfo == null || regInfo.isEmpty()) {
                                String message = MessageResponse.get(Common.Message.DISABLE_NOT_REGISTER + "_" + packName, Common.Message.DISABLE_NOT_REGISTER, logger);
                                SmsMtObj mt = new SmsMtObj();
                                mt.setMsisdn(accountInfo.getMsisdn());
                                mt.setChannel(Common.CHANNEL);
                                mt.setMessage(message);
                                db.insertMt(mt);
                                response.setErrorCode(Common.ErrorCode.NOT_REGISTERED);
                                response.setContent(message);
                            } else {
                                for (RegisterInfo reg : regInfo) {
                                    rsCancelMps = ws.cancelService(msisdn, reg.getProductName());
                                    if (WSProcessor.LIST_CANCEL_SUCCESS_RES.contains(rsCancelMps)) {
                                        db.disableAutoExtend(regInfo.get(0).getRegisterId());
                                    }
                                }
                                // send message
                                String message = MessageResponse.get(Common.Message.DISABLE_EXTEND_SUCCESS + "_" + packName, Common.Message.DISABLE_EXTEND_SUCCESS, logger);
                                SmsMtObj mt = new SmsMtObj();
                                mt.setMsisdn(accountInfo.getMsisdn());
                                mt.setChannel(Common.CHANNEL);
                                mt.setMessage(message);
                                db.insertMt(mt);

                                // return
                                response.setErrorCode(Common.ErrorCode.SUCCESS);
                                response.setContent(message);
                            }
                        } else {
                            List<RegisterInfo> regInfo = db.getRegisterInfo(msisdn, packName);
                            if (regInfo == null || regInfo.isEmpty()) {
                                String message = MessageResponse.get(Common.Message.DISABLE_NOT_REGISTER + "_" + packName, Common.Message.DISABLE_NOT_REGISTER, logger);
                                SmsMtObj mt = new SmsMtObj();
                                mt.setMsisdn(accountInfo.getMsisdn());
                                mt.setChannel(Common.CHANNEL);
                                mt.setMessage(message);
                                db.insertMt(mt);

                                response.setErrorCode(Common.ErrorCode.NOT_REGISTERED);
                                response.setContent(message);
                            } else {
                                rsCancelMps = ws.cancelService(msisdn, regInfo.get(0).getProductName());
                                if (WSProcessor.LIST_CANCEL_SUCCESS_RES.contains(rsCancelMps)) {
                                    db.disableAutoExtend(regInfo.get(0).getRegisterId());

                                    // send message
                                    String message = MessageResponse.get(Common.Message.DISABLE_EXTEND_SUCCESS + "_" + packName, Common.Message.DISABLE_EXTEND_SUCCESS, logger);
                                    SmsMtObj mt = new SmsMtObj();
                                    mt.setMsisdn(accountInfo.getMsisdn());
                                    mt.setChannel(Common.CHANNEL);
                                    mt.setMessage(message);
                                    db.insertMt(mt);

                                    // return
                                    response.setErrorCode(Common.ErrorCode.SUCCESS);
                                    response.setContent(message);
                                } else {
                                    response.setErrorCode(Common.ErrorCode.CHARGE_ERROR);
                                    response.setContent("Transaction failed!");
                                }
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }

        return response;
    }
    
    
    @WebMethod(operationName = "wsGetUserServices")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsGetUserServices(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsGetUserServices Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\nmsisdn:").append(msisdn).
                    append("\nserviceId:").append(serviceId);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // check user and password
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    List<RegisterInfo> listRegs = db.getUserServicesRenew(msisdn, serviceId);
                    List<String> listServices = new ArrayList<>();
                    for (int c = 0; c < listRegs.size(); c++) {
                        logger.info(listRegs.get(c).getProductName());
                        if (listRegs.get(c).getStatus() == 1) {
                            listServices.add(listRegs.get(c).getProductName());
                        }
                    }
                    response.setListServices(listServices);
                    response.setErrorCode(SUCCESS);
                }
            }
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }
        return response;
    }
    
    //có cả buy turn
    @WebMethod(operationName = "wsChargeFeeOtp")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsChargeFeeOtp(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "Fee") String fee,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsChargeFeeOtp Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn).
                    append("\n serviceId:").append(serviceId).
                    append("\n packageName:").append(packageName).
                    append("\n Fee:").append(fee);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            } else if (packageName == null || packageName.length() == 0) {
                logger.info("packageName is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("packageName is null");
            } else if (fee == null || fee.length() == 0) {
                logger.info("fee is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("fee is null");
            }
//------- ----------Dành cho thị trường có OTP -------------------------
    /*
            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    // check account
                    assert msisdn != null;
                    msisdn = formatMsisdn(msisdn);
                    // check account
                    AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
                    // create account
                    if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_EXISTED);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ACCOUNT_NOT_EXISTED, logger));
                    } else {
                        int moneyCharge = Common.ADD_SPIN_FEE;
                        if (fee != null && fee.length() > 0) {
                            moneyCharge = Integer.parseInt(fee);
                        }

                        if (moneyCharge < 0) {
                            response.setErrorCode(Common.ErrorCode.NOT_ENOUGH_MONEY);
                            response.setContent("Charge fail");
                            return response;
                        }

                        ProductInfo productInfo = getProductByName(packageName);
                        if (productInfo == null) {
                            response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
                            response.setContent("Your package name is not valid");
                            return response;
                        }

                        // waiting confirm
                        String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
                        
                        String resultPaid = ws.chargeFeeOtp(msisdn, moneyCharge, REQ);
                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
                            if (Objects.equals(resultPaid, Common.ErrorCode.WAITING_OTP)) {
                                // confirm 2 steps
                                logger.info("Create otp for buy turn success " + msisdn + ", fee " + moneyCharge);

                                // send message
                                String message = MessageResponse.get(Common.Message.CHARGE_WAIT_CONFIRM, logger);
                                assert fee != null;
                                message = message.replaceAll("%money%", fee);

                                response.setErrorCode(Common.ErrorCode.WAITING_OTP);
                                response.setContent(message);
                                response.setResultCode(REQ);
                            } else if (Objects.equals(resultPaid, Common.ErrorCode.SUCCESS)) {
                                // buy turn buy one step

                                boolean registered = false;
                                List<RegisterInfo> listRegInday = null;
                                listRegInday = db.getRegisterInday(msisdn, productInfo.getProductName());
                                if (listRegInday != null && !listRegInday.isEmpty()) {
                                    registered = true;
                                }

                                Timestamp expireTime = getExpireTime(productInfo);
                                // check registered and write the next action to database
                                RegisterInfo reg;
                                if (!registered) {
                                    // insert register
                                    reg = new RegisterInfo();
                                    reg.setMsisdn(msisdn);
                                    reg.setProductName(productInfo.getProductName());
                                    reg.setExpireTime(expireTime);
                                    reg.setServiceId(Integer.parseInt(serviceId));
                                    reg.setChannel("WEB");
                                    reg = updateRegRenew(reg, productInfo);
                                    db.iInsertRegisterInfo(reg);
                                } else {
                                    reg = listRegInday.get(0);
                                    db.iInsertRegisterInfo(reg);
                                }

                                //insert chargelog
                                if (moneyCharge > 0) {
                                    ChargeLog chargeLog = new ChargeLog();
                                    chargeLog.setFee(moneyCharge);
                                    chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                                    chargeLog.setMsisdn(msisdn);
                                    chargeLog.setDescription("Charge");
                                    chargeLog.setStatus(Common.Constant.CHARGE_STATUS);
                                    db.iInsertChargeLog(chargeLog);
                                }
                            }
                        } else {
                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
                        }
                    }
                }

            }
        */
//--------------- Kết thúc mua lượt có otp ---------------------------------------
//--------------- Bắt đầu mua lượt không có otp ----------------------------------
                
            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    int moneyCharge = Common.ADD_SPIN_FEE;
                    if (fee != null && fee.length() > 0) {
                        moneyCharge = Integer.parseInt(fee);
                    }
                    if (moneyCharge < 0) {
                        response.setErrorCode(Common.ErrorCode.NOT_ENOUGH_MONEY);
                        response.setContent("Charge fail");
                        return response;
                    }
                    ProductInfo productInfo = getProductByName(packageName);
                    if (productInfo == null) {
                        response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
                        response.setContent("Your package name is not valid");
                        return response;
                    }
                    String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());

                    // charge
                  String resultPaid = ws.chargeFeeOtp(msisdn, moneyCharge, REQ);
//                    String resultPaid = "0";
                    boolean registered = false;
                    List<RegisterInfo> listRegInday = null;
                    listRegInday = db.getRegisterInday(msisdn, productInfo.getProductName());
                    if (listRegInday != null && !listRegInday.isEmpty()) {
                        registered = true;
                    }

                    if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
                        Timestamp expireTime = getExpireTime(productInfo);
                        // check registered and write the next action to database
                        RegisterInfo reg;
                        if (!registered) {
                            // insert register
                            reg = new RegisterInfo();
                            reg.setMsisdn(msisdn);
                            reg.setProductName(productInfo.getProductName());
                            reg.setExpireTime(expireTime);
                            reg.setServiceId(productInfo.getProductId());
                            reg.setChannel("WEB");
                            reg = updateRegRenew(reg, productInfo);
                            db.iInsertRegisterInfo(reg);
                        } else {
                            reg = listRegInday.get(0);
                            db.iInsertRegisterInfo(reg);
                        }

                        //insert chargelog
                        if (moneyCharge > 0) {
                            ChargeLog chargeLog = new ChargeLog();
                            chargeLog.setFee(moneyCharge);
                            chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                            chargeLog.setMsisdn(msisdn);
//                            chargeLog.setDescription("Charge");
                            String mTOOL_RUN = MessageResponse.get(Common.Message.TOOL_RUN,logger);
                            Boolean msisdnTool = false;
                            try {
                                msisdnTool = db.getMsisdnTool(msisdn);
                            } catch (Exception e) {
                            }
                            if(mTOOL_RUN.equals("START") && msisdnTool == true){
                                chargeLog.setDescription("Charge tool " + productInfo.getProductName());
                                chargeLog.setAccountId("1");
                            }else{
                                chargeLog.setDescription("Charge");
                            }
                            chargeLog.setStatus(Common.Constant.CHARGE_STATUS);
                            db.iInsertChargeLog(chargeLog);
                        }
                        
                        // Update Spin
                        db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                        logger.info("Buy turn success success " + msisdn + ", fee " + fee);
                        
                        response.setMoneyDeducted(moneyCharge);
                        response.setTotalSpinAdd(productInfo.getNumberSpin());
                        
                        String message = MessageResponse.get(Common.Message.CHARGE_FEE_SUCCESS, logger);
                        message = message.replace("%fee%", String.valueOf(moneyCharge));
                        response.setErrorCode(Common.ErrorCode.SUCCESS);
                        response.setContent(message);
                    } 
                    else {
                        response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
                        response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
                    }
                }
            }
        
//--------------- Kết Thúc mua lượt không có otp ----------------------------------
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }
        return response;
    }

    @WebMethod(operationName = "wsChargeFeeConfirm")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsChargeFeeConfirm(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "Fee") String fee,
            @WebParam(name = "RequestId") String requestId,
            @WebParam(name = "Otp") String otp,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsChargeFeeConfirm Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\nMsisdn:").append(msisdn).
                    append("\nFee:").append(fee).
                    append("\nServiceId:").append(serviceId).
                    append("\npackageName:").append(packageName).
                    append("\nOtp:").append(otp);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            } else if (packageName == null || packageName.length() == 0) {
                logger.info("packageName is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("packageName is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    int moneyCharge = Common.ADD_SPIN_FEE;
                    if (fee != null && fee.length() > 0) {
                        moneyCharge = Integer.parseInt(fee);
                    }
                    if (moneyCharge < 0) {
                        response.setErrorCode(Common.ErrorCode.NOT_ENOUGH_MONEY);
                        response.setContent("Charge fail");
                        return response;
                    }
                    ProductInfo productInfo = getProductByName(packageName);
                    if (productInfo == null) {
                        response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
                        response.setContent("Your package name is not valid");
                        return response;
                    }
                    // charge
                    String resultPaid = ws.chargeFeeConfirm(msisdn, moneyCharge, otp, requestId);
                    
                    boolean registered = false;
                    List<RegisterInfo> listRegInday = null;
                    listRegInday = db.getRegisterInday(msisdn, productInfo.getProductName());
                    if (listRegInday != null && !listRegInday.isEmpty()) {
                        registered = true;
                    }

                    if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
                        Timestamp expireTime = getExpireTime(productInfo);
                        // check registered and write the next action to database
                        RegisterInfo reg;
                        if (!registered) {
                            // insert register
                            reg = new RegisterInfo();
                            reg.setMsisdn(msisdn);
                            reg.setProductName(productInfo.getProductName());
                            reg.setExpireTime(expireTime);
                            reg.setServiceId(productInfo.getProductId());
                            reg.setChannel("WEB");
                            reg = updateRegRenew(reg, productInfo);
                            db.iInsertRegisterInfo(reg);
                        } else {
                            reg = listRegInday.get(0);
                            db.iInsertRegisterInfo(reg);
                        }

                        //insert chargelog
                        if (moneyCharge > 0) {
                            ChargeLog chargeLog = new ChargeLog();
                            chargeLog.setFee(moneyCharge);
                            chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                            chargeLog.setMsisdn(msisdn);
                            chargeLog.setDescription("Charge");
                            chargeLog.setStatus(Common.Constant.CHARGE_STATUS);
                            db.iInsertChargeLog(chargeLog);
                        }
                        // Update Spin
                        db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                        logger.info("Buy turn success success " + msisdn + ", fee " + fee);

                        String message = MessageResponse.get(Common.Message.CHARGE_FEE_SUCCESS, logger);
                        message = message.replace("%fee%", String.valueOf(moneyCharge));
                        response.setErrorCode(Common.ErrorCode.SUCCESS);
                        response.setContent(message);
                    } 
                    else {
                        response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
                        response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
                    }
                }
            }
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }

        return response;
    }

    // thưởng money
    @WebMethod(operationName = "wsAddMoney")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsAddMoney(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "Fee") String fee,
            @WebParam(name = "ServiceId") String serviceId,
            @WebParam(name = "top") String top,
            @WebParam(name = "type") String type) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsAddMoney Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn).
                    append("\n PackageName:").append(packageName).
                    append("\n Msisdn:").append(msisdn).
                    append("\n ServiceId:").append(serviceId).
                    append("\n Fee:").append(fee).
                    append("\n Type:").append(type);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (packageName == null || packageName.length() == 0) {
                logger.info("packageName is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("packageName is null");
            } else if (fee == null || fee.length() == 0) {
                logger.info("fee is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("fee is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    // check account
                    AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
                    // create account
                    if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_EXISTED);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ACCOUNT_NOT_EXISTED, logger));
                    } else {

                        int money = Integer.parseInt(fee);
                        ws.addMoney(msisdn, money);

                        ChargeLog chargeLog = new ChargeLog();
                        chargeLog.setFee(-money);
                        chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                        chargeLog.setMsisdn(msisdn);
                        if("DAILY".equals(type)){
                           chargeLog.setDescription("Exchange points to money | DAILY");
                        }else if("WEEKLY".equals(type) ){
                            chargeLog.setDescription("Exchange points to money | WEEKLY");
                        }else if("MONTHLY".equals(type)){
                           chargeLog.setDescription("Exchange points to money | MONTHLY");
                        }else{
                           chargeLog.setDescription("Exchange points to money");
                        }
                        Boolean msisdnTool = false;
                        String mTOOL_RUN = MessageResponse.get(Common.Message.TOOL_RUN,logger);

                        try {
                            msisdnTool = db.getMsisdnTool(msisdn);
                        } catch (Exception e) {
                        }
                        if(mTOOL_RUN.equals("START") && msisdnTool == true){
                            chargeLog.setAccountId("1");
                        }
                        chargeLog.setStatus(Common.Constant.UNCHARGE_STATUS);
                        db.iInsertChargeLog(chargeLog);

                        response.setErrorCode(Common.ErrorCode.SUCCESS);
                        String message = "";
                        if("DAILY".equals(type)){
                            message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS_DAILY, logger);
                            logger.info("message DAILY:"+message);

                        }else if("WEEKLY".equals(type) ){
                            message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS_WEEKLY, logger);
                            logger.info("message WEEKLY:"+message);

                        }else if("MONTHLY".equals(type)){
                           message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS_MONTHLY, logger);
                           logger.info("message MONTHLY:"+message);
                        }else{
                           message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS, logger);
                           logger.info("message EXCHANGE_SUCCESS:"+message);
                        }
                        message = message.replaceAll("%money%", money + "");
                        message = message.replaceAll("%top%", top + "");
                        message = message.replaceAll("%type%", type + "");

                        response.setContent(message);

                        SmsMtObj mt = new SmsMtObj();
                        mt.setMsisdn(msisdn);
                        mt.setChannel(Common.CHANNEL);
                        mt.setMessage(message);
                        db.insertMt(mt);
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }
    
    // thưởng qua ví
    @WebMethod(operationName = "wsAddEmola")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsAddEmola(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PrizeCode") String PrizeCode,
            @WebParam(name = "PrizeType") String PrizeType,
            @WebParam(name = "ServiceId") String serviceId,
            @WebParam(name = "top") String top) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsAddEmola Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn).
                    append("\n PrizeCode:").append(PrizeCode).
                    append("\n PrizeType:").append(PrizeType).
                    append("\n Top:").append(top);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (PrizeCode == null || PrizeCode.length() == 0) {
                logger.info("PrizeCode is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("PrizeCode is null");
            } else if (PrizeType == null || PrizeType.length() == 0) {
                logger.info("PrizeType is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("PrizeType is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    // check account
                    AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
                    if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                        accountInfo = db.iGetAccountByMsisdn(msisdn, "MINHA_VIBE_MR_DAY");
                    }
                    // create account
                    if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_EXISTED);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ACCOUNT_NOT_EXISTED, logger));
                    } else {
                        PrizeObj mListPrize = db.igetListPrizeByActionType(top);
                        String errorCode =  ws.extendService(msisdn,PrizeCode,PrizeType);
                        if(SUCCESS.equals(errorCode)){
                            ChargeLog chargeLog = new ChargeLog();
                            chargeLog.setFee(-mListPrize.getValuePrize());
                            chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                            chargeLog.setMsisdn(msisdn);
                            chargeLog.setDescription("Exchange Emola");
                            chargeLog.setStatus(Common.Constant.UNCHARGE_STATUS);
                            db.iInsertChargeLog(chargeLog);
                            
                            response.setErrorCode(Common.ErrorCode.SUCCESS);
                            String message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS_EMOLA, logger);
                            logger.info("message EXCHANGE_SUCCESS_wsAddEmola:"+message);
                            message = message.replaceAll("%money%", mListPrize.getValuePrize() + "");
                            message = message.replaceAll("%top%", top + "");

                            response.setContent(message);

                            SmsMtObj mt = new SmsMtObj();
                            mt.setMsisdn(msisdn);
                            mt.setChannel(Common.CHANNEL);
                            mt.setMessage(message);
                            db.insertMt(mt);
                        }else{
                            response.setErrorCode(errorCode);
                            String[] resSeprate = errorCode.split("|");
                            response.setContent(errorCode.length() > 1 ? resSeprate[1] : "ERROR when charging");
                        }
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing wsAddEmola", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }

    // thưởng data
    @WebMethod(operationName = "wsAddData")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsAddData(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PackageName") String packageName,
            @WebParam(name = "data") String data,
            @WebParam(name = "ServiceId") String serviceId) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsAddData Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn).
                    append("\n PackageName:").append(packageName).
                    append("\n Msisdn:").append(msisdn).
                    append("\n ServiceId:").append(serviceId).
                    append("\n data:").append(data);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            } else if (packageName == null || packageName.length() == 0) {
                logger.info("packageName is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("packageName is null");
            } else if (data == null || data.length() == 0) {
                logger.info("data is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("fee is null");
            } else if (serviceId == null || serviceId.length() == 0) {
                logger.info("serviceId is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("serviceId is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    // check account
                    AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
                    // create account
                    if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
                        response.setErrorCode(Common.ErrorCode.ACCOUNT_NOT_EXISTED);
                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ACCOUNT_NOT_EXISTED, logger));
                    } else {

                        int dataConvert = Integer.parseInt(data);
                        ws.addData(msisdn, dataConvert);

                        ChargeLog chargeLog = new ChargeLog();
                        chargeLog.setFee(-dataConvert);
                        chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                        chargeLog.setMsisdn(msisdn);
                        chargeLog.setDescription("Exchange points to data");
                        chargeLog.setStatus(Common.Constant.UNCHARGE_STATUS);
                        db.iInsertChargeLog(chargeLog);

                        response.setErrorCode(Common.ErrorCode.SUCCESS);
                        String message = MessageResponse.get(Common.Message.EXCHANGE_SUCCESS, logger);
//                        message = message.replaceAll("%point%", point + "");
                        message = message.replaceAll("%money%", dataConvert + "");
                        response.setContent(message);

                        SmsMtObj mt = new SmsMtObj();
                        mt.setMsisdn(msisdn);
                        mt.setChannel(Common.CHANNEL);
                        mt.setMessage(message);
                        db.insertMt(mt);
                    }
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }
    
    
    

    //     ------------------------- END ----------------------
    
        // GET PRIZE
    @WebMethod(operationName = "wsDoSpin")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsDoSpin(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "Channel") String channel) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsDoSpin Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    // update spin
                    SpinResultObj resultSpin = db.doSpin(msisdn); 
                    
                    if (resultSpin == null) {
                        response.setErrorCode(Common.ErrorCode.DB_ERROR);
                        String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
                        response.setContent(message);
                        return response;
                    }
                    // check prize
                    response.setSpinResult(resultSpin);
                    response.setErrorCode(Common.ErrorCode.SUCCESS);
                    return response;
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }
    
    @WebMethod(operationName = "wsDoSpinT")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsDoSpinT(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "Msisdn") String msisdn,
            @WebParam(name = "PrizeID") String prizeID,
            @WebParam(name = "PrizeWinnerID") String prizeWinnerID,
            @WebParam(name = "PartnerTransId") String partnerTransId,
            @WebParam(name = "TransId") String transId,
            @WebParam(name = "Channel") String channel) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsDoSpin Params:\n").
                    append("WsUser:").append(wsUser).
                    append("\n Msisdn:").append(msisdn);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            } else if (msisdn == null || msisdn.length() == 0) {
                logger.info("msisdn is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("msisdn is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
                    msisdn = formatMsisdn(msisdn);
                    // update spin
                    SpinResultObj resultSpin = null;
                    String mTOOL_RUN = MessageResponse.get(Common.Message.TOOL_RUN,logger);
                    if(mTOOL_RUN.equals("START")){
                        if (prizeID != null && !prizeID.isEmpty()
                                && prizeWinnerID != null && !prizeWinnerID.isEmpty() ) {
                            
                            resultSpin = db.doSpinSubmitPrize(
                                msisdn,
                                Integer.parseInt(prizeID)  ,
                                Integer.parseInt(prizeWinnerID) ,
                                !transId.isEmpty() ? transId : "0"
                            );
                        } else {
                            resultSpin = db.doSpinT(
                                msisdn,
                                (!prizeID.isEmpty() ? Integer.parseInt(prizeID) : 0),
                                partnerTransId
                            );
                        }

                    }else{
                        if (prizeID != null && !prizeID.isEmpty()
                                && prizeWinnerID != null && !prizeWinnerID.isEmpty()
                                && transId != null && !transId.isEmpty()) {
                            
                            resultSpin = db.doSpinSubmitPrize(
                                msisdn,
                                !prizeID.isEmpty() ? Integer.parseInt(prizeID) : 0,
                                !prizeWinnerID.isEmpty() ? Integer.parseInt(prizeWinnerID) : 0,
                                !transId.isEmpty() ? transId : "0"
                            );
                        } else {
                            resultSpin = db.doSpinT(
                                msisdn,
                                (!prizeID.isEmpty() ? Integer.parseInt(prizeID) : 0),
                                partnerTransId
                            );
                        }
                    }
                    if (resultSpin == null) {
                        response.setErrorCode(Common.ErrorCode.DB_ERROR);
                        String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
                        response.setContent(message);
                        return response;
                    }
                    // check prize
                    response.setSpinResult(resultSpin);
                    response.setErrorCode(Common.ErrorCode.SUCCESS);
                    return response;
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            String message = MessageResponse.get(Common.Message.SYSTEM_FAIL, logger);
            response.setContent(message);
        }

        return response;
    }
    
    

    @WebMethod(operationName = "wsLoadPrize")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsLoadPrize(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsLoadPrize:");
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            }
            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                } else {
//                    String lang = (String) ctx.getMessageContext().get("lang");
                    response.setErrorCode(Common.ResultCode.SUCCESS);
                    response.setListPrize(new ArrayList(Common.mapPrize.values()));
                }
            }

        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }

        return response;
    }

    @WebMethod(operationName = "wsGetListWinner")
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
    public Response wsGetListWinner(
            @WebParam(name = "WsUser") String wsUser,
            @WebParam(name = "WsPass") String wsPass,
            @WebParam(name = "msisdn") String msisdn,
            @WebParam(name = "period") String period,
            @WebParam(name = "page") String page,
            @WebParam(name = "pageSize") String pageSize,
            @WebParam(name = "isTop") String isTop,
            @WebParam(name = "codeType") String codeType,
            @WebParam(name = "startDate") String startDate,
            @WebParam(name = "endDate") String endDate) {

        Response response = new Response();
        response.setErrorCode(SUCCESS);
//        Timestamp reqTime = new Timestamp(System.currentTimeMillis());

        try {
            String ip = getIpClient();
            UserInfo userInfo = null;
            br.setLength(0);
            br.append("wsGetListWinner Params:\n").
                    append(", period:").append(period).
                    append(", page:").append(page).
                    append(", codeType:").append(codeType).
                    append(", isTop:").append(isTop);
            logger.info(br);

            Request request = new Request();
            request.setUser(wsUser);
//            request.setPass(password);
            if (wsUser == null || wsUser.length() == 0) {
                logger.info("wsUser is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsUser is null");
            } else if (wsPass == null || wsPass.length() == 0) {
                logger.info("wsPass is null");
                response.setErrorCode(PARAM_NOT_ENOUGH);
                response.setContent("wsPass is null");
            }

            if (SUCCESS.equals(response.getErrorCode())) {
                // kiem tra thong tin dang nhap
                userInfo = authenticate(wsUser, wsPass, ip);
                if (userInfo == null || userInfo.getWsUserId() <= 0) {
                    response.setErrorCode(WRONG_PASSWORD);
                    response.setContent("Authenticate fail!");
                    return response;
                } else {
                    String lang = getLang();
                    // get list code
                    if (page == null) {
                        page = "1";
                    }
                    int top = -1;
                    int codeTypeInt = 0;
                    if (isTop != null && !isTop.isEmpty()) {
                        top = Integer.parseInt(isTop);
                    }
                    if (codeType != null && !codeType.isEmpty()) {
                        codeTypeInt = Integer.parseInt(codeType);
                    }
                    
                    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
                    // Định dạng đầu ra KHÔNG CÓ .0
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    // Chuyển startDate -> "2025-07-24 00:00:00"
                    LocalDate start = LocalDate.parse(startDate, inputFormatter);
                    String startDate1 = outputFormatter.format(start.atStartOfDay());
                    // Chuyển endDate -> "2025-07-25 23:59:59"
                    LocalDate end = LocalDate.parse(endDate, inputFormatter);
                    LocalDateTime endDateTime = end.atTime(23, 59, 59);
                    String endDate1 = outputFormatter.format(endDateTime);
                    
                    List<PrizeWinner> listWinner = db.getListWinner(msisdn, Integer.parseInt(period), Integer.parseInt(page), Integer.parseInt(pageSize), top, codeTypeInt,startDate1,endDate1);
                    response.setListWinner(listWinner);
                    int totalWinner = db.getCountWinner(msisdn, Integer.parseInt(period), top, codeTypeInt,startDate1,endDate1);

                    int totalPages = (int) Math.ceil((double) totalWinner / Double.parseDouble(pageSize));
                    response.setTotalPage(String.valueOf(totalPages));
                    response.setErrorCode(Common.ErrorCode.SUCCESS);
                    return response;

                }
            }
        } catch (Exception e) {
            logger.error("Error processing", e);
            response.setErrorCode(EXCEPTION);
            response.setContent("Transaction fail");
        }

        return response;
    }

    protected String getLang() {
        try {
            Map<String, List> headers = (Map<String, List>) ctx.getMessageContext().get("javax.xml.ws.http.request.headers");
            String lang = (String) headers.get("Lang").get(0);
            if (lang == null) {
                lang = Common.Lang.local;
            }
            return lang;
        } catch (Exception ex) {
            return Common.Lang.local;
        }
    }
    
    public RegisterInfo updateRegRenew(RegisterInfo reg, ProductInfo productInfo) {
        reg.setNumberSpin(productInfo.getNumberSpin());
        reg.setExtendStatus(0);
        reg.setPlayedTimes(0);
        reg.setRenew(productInfo.getRenew());
        reg.setStatus(1);
        return reg;
    }

    private String generateValidateCode(int length) {
        String output = "";
        String input = "1234567890";
        Random rnd = new Random();
        for (int i = 0; i < length; i++) {
            output = output + input.charAt(rnd.nextInt(input.length()));
        }
        return output;
    }

    private String formatMsisdn(String msisdn) {
        if (msisdn.startsWith(WebserviceManager.countryCode)) {
            return msisdn;
        } else if (msisdn.startsWith("0")) {
            return WebserviceManager.countryCode + msisdn.substring(1);
        }
        return WebserviceManager.countryCode + msisdn;
    }

    private void updateRanking(String msisdn, int subType, int count, int rankType, int period) {
        List<RankingObj> listRank = db.getRankObj(msisdn, rankType, period);
        if (listRank != null && listRank.size() > 0) {
            // update
            db.iUpdateRanking(listRank.get(0).getId(), subType, count);
        } else {
            // insert
            Calendar currentTime = Calendar.getInstance();
            Calendar endTime = Calendar.getInstance();
            endTime.set(Calendar.HOUR_OF_DAY, 20);
            endTime.set(Calendar.MINUTE, 0);
            endTime.set(Calendar.SECOND, 0);
            endTime.set(Calendar.MILLISECOND, 0);

            if (currentTime.after(endTime)) {
                endTime.add(Calendar.DAY_OF_MONTH, 1);
            }

            Calendar startTime = Calendar.getInstance();
            startTime.setTimeInMillis(endTime.getTimeInMillis() - 86400000L + 1000);

            RankingObj ranking = new RankingObj();
            ranking.setMsisdn(msisdn);
            ranking.setSpintCount(count);
            ranking.setStartTime(new Timestamp(startTime.getTimeInMillis()));
            ranking.setEndTime(new Timestamp(endTime.getTimeInMillis()));
            ranking.setSubType(subType);
            ranking.setRankType(rankType);

            if (period == Common.PeriodPrize.DAILY) {
                db.iInsertRanking(ranking);
            } else if (period == Common.PeriodPrize.WEEKLY) {
                db.iInsertRankingWeekly(ranking);
            }
            if (period == Common.PeriodPrize.MONTHLY) {
                db.iInsertRankingMonth(ranking);
            }
        }
    }

    private PointTotalObj updatePoint(String msisdn, int point, int type) {
        List<PointTotalObj> listPoint = db.getPointTotal(msisdn);
        if (listPoint != null && listPoint.size() > 0) {
            PointTotalObj newPoint = listPoint.get(0);
            // update
            logger.info("Update point: id " + newPoint.getId() + ", msisdn " + msisdn + ", point " + point);
            if (type == 1) {
                // add
                newPoint.setAddedPoint(point);
                db.iUpdatePointTotal(newPoint.getId(), point);
                newPoint.setPoint(newPoint.getPoint() + point);
            } else if (type == 2) {
                // multiple
                newPoint.setAddedPoint(newPoint.getPoint() * (point - 1));
                db.iUpdatePointTotal(newPoint.getId(), newPoint.getPoint() * (point - 1));
                newPoint.setPoint(newPoint.getPoint() * point);
            }
            return newPoint;
        } else {
            // insert
            PointTotalObj pointObj = new PointTotalObj();
            pointObj.setMsisdn(msisdn);
            if (type == 1) {
                // added
                pointObj.setAddedPoint(point);
                pointObj.setPoint(point);
            } else {
                // multiple
                pointObj.setAddedPoint(0);
                pointObj.setPoint(0);
            }
            pointObj.setSubType(0);
            db.iInsertPointTotal(pointObj);
            return pointObj;
        }
    }

    private ProductInfo getProductByName(String packName) {
        //logger.info(Common.listProduct);
        for (ProductInfo product : Common.listProduct) {
            //logger.info(product.getProductName());
            //logger.info("fee " + product.getFee());
//            logger.info("packName: " + packName);
            if (product.getProductName().equalsIgnoreCase(packName)) {
                return product;
            }
        }
        return null;
    }

    private Timestamp getExpireTime(ProductInfo productInfo) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 0);
        cal.add(Calendar.DAY_OF_MONTH, productInfo.getExpireDays() - 1);
        return new Timestamp(cal.getTimeInMillis());
    }

    protected Timestamp getExpireTimeInDay(int numDay) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 0);
        cal.add(Calendar.DAY_OF_MONTH, numDay - 1);
        return new Timestamp(cal.getTimeInMillis());
    }

    protected Timestamp getExactTimeInDay(int second, int minute, int hour) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        cal.set(Calendar.MILLISECOND, 0);
        cal.add(Calendar.DAY_OF_MONTH, 0);
        return new Timestamp(cal.getTimeInMillis());
    }

    protected Timestamp getExactTimeInDay(int second, int minute, int hour, int numday) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        cal.set(Calendar.MILLISECOND, 0);
        cal.add(Calendar.DAY_OF_MONTH, numday);
        return new Timestamp(cal.getTimeInMillis());
    }

    private Timestamp getTruncSysdate() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return new Timestamp(cal.getTimeInMillis());
    }

    private String getHashCode(String securityCode, String salt, Logger logger) {
        MessageDigest md = null;
        try {
            String seq = salt + securityCode;
            md = MessageDigest.getInstance("SHA-256"); //step 2
            md.update(seq.getBytes("UTF-8")); //step 3
        } catch (Exception ex) {
            logger.error(ex.toString(), ex);
        }
        byte raw[] = md.digest(); //step 4
        String hash = (new BASE64Encoder()).encode(raw); //step 5
        return hash;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//        MessageDigest md = null;
//        String seq = "123456a@" + "32323232";
//        md = MessageDigest.getInstance("SHA-256"); //step 2
//        md.update(seq.getBytes("UTF-8")); //step 3

//        byte raw[] = md.digest(); //step 4
//        String hash = (new BASE64Encoder()).encode(raw); //step 5
//        System.out.println("hash" + hash);
//        String pass = "1QAaz@123@";
//        Pattern pattern = Pattern.compile("abcdefghijklmnopqrstuvwxyz");
        //boolean match = list.matches(".");
//        System.out.println("hash " + pass.matches(".*[A-Z].*"));
//        String output = "";
//        String input = "1234567890";
//        Random rnd = new Random();
//        for (int i = 0; i < 8; i++) {
//            output = output + input.charAt(rnd.nextInt(input.length()));
//        }
//        System.out.println("output = " + output);
//        double x = 1.1;
//        System.out.println("output = " + (((x * 3 / 2) * 100) / 100));
//        System.out.println("output = " + (x * 3 / 2));
//        int point = Integer.parseInt("116000.0");
//        int money = point / 10;
//        System.out.println("Poinnt " + point + ", money: " + money);
    }

    @Override
    public UserInfo authenticate(String userName, String password, String ipAddress) {
        // validate thong tin user
        // validate thong tin user
        UserInfo userInfo = db.iGetUser(userName);
        if (userInfo == null || userInfo.getWsUserId() <= 0) {
            logger.info("User not existed: " + userName);
            userInfo = new UserInfo();
            userInfo.setWsUserId(-1);
            return userInfo;
        }

        if (userInfo.getIp() != null && userInfo.getIp().length() > 0) {
            // Check IP
            String ip[] = userInfo.getIp().split(",");
            boolean pass = false;
            for (String ipConfig : ip) {
                if (pair(ipAddress, ipConfig.trim())) {
                    pass = true;
                    break;
                }
            }
            if (!pass) {
                logger.info("IP address not allowed: " + ipAddress);
                userInfo.setWsUserId(-2);
                return userInfo;
            }
        }
        // Check password
        if (userInfo.getPass() != null && userInfo.getPass().trim().length() > 0) {
            if (password.equals(userInfo.getPass())) {
                return userInfo;
            }

            String passEncript = "";
            passEncript = Encrypt.getHashCode(userName, password, logger);
            if (passEncript.equals(userInfo.getPass())) {
                return userInfo;
            }
            logger.info("Password incorrect: user=" + userName);
            userInfo.setWsUserId(-3);
            return userInfo;
        }
        return null;//tam fix
    }
}
