/**
 * Copyright (c) 2010 Penril Datability (SEA) Sdn Bhd All rights reserved.
 *
 * This software is copyrighted. Under the copyright laws, this software
 * may not be copied, in whole or in part, without prior written consent
 * of Penril Datability (SEA) Sdn Bhd or its assignees. This software is
 * provided under the terms of a license between Penril Datability (SEA)
 * Sdn Bhd and the recipient, and its use is subject to the terms of that
 * license.
 */
package my.com.kfh.enterprise.services.ib104_fundtransfer.own;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import my.com.kfh.enterprise.services.GenericESBServicesImpl;
import my.com.kfh.enterprise.services.IBEnterpriseServices;
import my.com.kfh.enterprise.services.IBEnterpriseServicesWorkspace;
import my.com.kfh.enterprise.services.IBUtils;
import my.com.kfh.enterprise.services.ib101_access.AccessConstants;
import my.com.kfh.enterprise.services.ib101_access.IBAccessDBUtils;
import my.com.kfh.enterprise.services.ib112_si.IBGenericSIServices;
import my.com.kfh.enterprise.services.ib112_si.SIConstants;
import my.com.kfh.enterprise.services.ib112_si.SIDBUtils;
import my.com.kfh.enterprise.services.ib112_si.SI_PAYMENT_MODE;
import my.com.kfh.error.exception.IBGenericException;
import my.com.kfh.error.exception.IBServiceException;
import my.com.kfh.error.handler.CommonErrorCode;
import my.com.kfh.error.handler.IBErrorHandler;
import my.com.kfh.esb.response.ESBAccountEnquiryTC100Bean;
import my.com.kfh.esb.response.ESBCompanyProfileBean;
import my.com.kfh.esb.response.ESBFundTransferOwnBean;
import my.com.kfh.esb.response.ESBTransferGLtoCASABean;
import my.com.kfh.esb.response.ESBTransferToGLBean;
import my.com.kfh.sms.services.SMSConstants;
import my.com.kfh.sms.services.SMSServices;
import my.com.kfh.web.utils.BVI_DateTime;
import my.com.kfh.web.utils.DataValidator;
import my.com.kfh.web.utils.DateTimeUtils;
import my.com.kfh.web.utils.FormatterUtils;
import my.com.kfh.web.utils.GSTUtils;
import my.com.kfh.web.utils.IBLoadProperty;
import my.com.kfh.web.utils.IBLogger;
import my.com.kfh.web.utils.IBSessionObjects;
import my.com.kfh.web.utils.IBTimer;
import my.com.kfh.web.utils.ResourcesUtils;
import my.com.kfh.web.utils.constant.CurrencyCode;
import my.com.kfh.web.utils.constant.ESBConstants;
import my.com.kfh.web.utils.constant.LogTables;
import my.com.kfh.web.utils.constant.ServiceInfo;

import com.broadvision.data.client.DataManager;
import com.broadvision.data.common.TableData;

/**
 * <pre>
 * PROGRAMMER: Ang Wei Cheng
 * CHANGE-NO:
 * TASK-NO:
 * DATE CREATED: Apr 4, 2010
 * TAG AS:
 * REASON(S):
 * MODIFICATION:
 * </pre>
 */

/**
 * <Class description>
 */
public class IBOwnSITransferResultsServices
{
	private static Class c_oClass = IBOwnSITransferResultsServices.class;

	public static void executeTransaction(String siId) throws IBGenericException
	{
        String m_sMethodName = "executeTransaction";
        IBTimer m_oTimer = IBLogger.logBSFNMethodEnteringMessage (c_oClass, m_sMethodName, String.class.getName ());

		String m_sSICharges = "0";
		String m_sSIChargesRefNo = null;
		boolean m_boSIChargeStatus = false;
		String m_sSIGSTCharges = "0";
		String m_sSIGSTChargesRefNo = null;
		boolean m_boSIGSTChargeStatus = false;
		String m_sSIChargesRevertRefNo = null;
		boolean m_boSIChargeRevertStatus = false;
		double m_dAvailableBal = 0.0;
		double m_dTransferAmount = 0.0;
		double m_dTotalAmount = 0.0;
		double m_dSICharges = 0.0;
		String m_sSIChargeResponseCode = null;
		boolean m_boIsFundSufficient = true;

		String	m_sReferenceNo = null;
		String m_sStatus = ResourcesUtils.getUnsuccessful ();
		String m_sReason = null;
		boolean hasReceipt = false;

		String m_sEsbDescription = null;
		String SIGSTCharges = "0";
		String m_sFromAccNewBal = "";
		String m_sToAccNewBal = "";
		String m_sFromAccIsoCurr = CurrencyCode.MALAYSIA_RINGGIT;
		String m_sToAccIsoCurr = CurrencyCode.MALAYSIA_RINGGIT;

		try
		{
			BVI_DateTime m_oCurrentBVIDateTime = DateTimeUtils.getCurrentIBDateTimeObject ();

			IBSessionObjects m_oSessionObj = mock(IBSessionObjects.class);
			when(m_oSessionObj.getDataManager()).thenReturn(new DataManager());

			TableData table = SIDBUtils.getSICurrentTransId(new IBEnterpriseServicesWorkspace(m_oSessionObj), siId);
			String currentTrnxId  = table.getStringValue(0, LogTables.IB_SI.CURRENT_TRNX_ID.toString ());
			String siPaymentModeCode = table.getStringValue(0, LogTables.IB_SI.PAYMENT_MODE.toString ());
			String trnxTypeDisplay = table.getStringValue(0, LogTables.IB_SI.TRNX_TYPE.toString ());


			m_sEsbDescription = ESBConstants.FUND_TRANSFER_OWN;
			m_sEsbDescription = IBGenericSIServices.getESBDescription (m_sEsbDescription, siPaymentModeCode);

			IBEnterpriseServices p_oEnterpriseServices = new IBEnterpriseServicesWorkspace(m_oSessionObj);

			//get user id from trnx
			table = OwnTransferDBUtils.getTransactionByTrnxId(p_oEnterpriseServices, currentTrnxId);
			String userId = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.USER_ID.toString ());

			com.broadvision.visitor.client.Visitor visitor = mock(com.broadvision.visitor.client.Visitor.class);
			when(visitor.getId()).thenReturn(Long.parseLong(userId));
			when(m_oSessionObj.getVisitor()).thenReturn(visitor);

			//get various data from transaction
			String m_sFromAccount = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.FROM_ACCOUNT_NO.toString ());
			String m_sToAccount = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.TO_ACCOUNT_NO.toString ());
			String m_sAmount = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.AMOUNT.toString ());
			String fromCurrency = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.FROM_CURRENCY.toString ());
			String toCurrency = table.getStringValue(0, LogTables.IB_INTRA_TRANSFER.TO_CURRENCY.toString ());
			String charges = "0";

			//get user rim no
			String rimNo = IBAccessDBUtils.getRimNoByUserId(p_oEnterpriseServices, userId);
			when(m_oSessionObj.getHttpSessionAttrObject (AccessConstants.RIM_NO)).thenReturn(rimNo);

			GenericESBServicesImpl m_oEsbServices = new GenericESBServicesImpl (m_oSessionObj);

			ESBAccountEnquiryTC100Bean m_oTCEnquiryBean = m_oEsbServices.getAccountDetailsTC100 (m_sFromAccount);
			if (!DataValidator.isEmptyString (m_oTCEnquiryBean.getAvailable_Bal ()))
			{
				m_dAvailableBal = Double.parseDouble (m_oTCEnquiryBean.getAvailable_Bal ());
			}

			if (SI_PAYMENT_MODE.RECURRING_PAYMENT.getCode ().equals (siPaymentModeCode))
			{
				m_dSICharges = IBGenericSIServices.getSICharges (ServiceInfo.SI_FEE_OWN);
    			m_sSICharges = String.valueOf (m_dSICharges);

				if (m_dSICharges > 0)
				{
					if (m_dAvailableBal > m_dSICharges)
					{
						String m_sChargeGLAccount = IBGenericSIServices.getSICollectionAccountNo (m_sFromAccount);

						ESBTransferToGLBean m_oESBTransferToGLBean = m_oEsbServices.chargesTransferOwn (m_sFromAccount,
								m_sChargeGLAccount, m_sSICharges, ESBConstants.SI_CHARGES+":"+m_sEsbDescription, null);

						m_sSIChargeResponseCode = m_oESBTransferToGLBean.getResponseCode ();
						if (ESBConstants.IB_SUCCESS_RC.equalsIgnoreCase (m_sSIChargeResponseCode))
						{
							m_boSIChargeStatus = true;
							m_sSIChargesRefNo = m_oESBTransferToGLBean.getReferenceNo ();
							
							String SIGSTChargesRate = IBUtils.getGSTRate(new IBEnterpriseServicesWorkspace(m_oSessionObj), IBLoadProperty.getValue(GSTUtils.SI_CHARGES_CODE));
    						SIGSTCharges = GSTUtils.gstAmount2Dec(m_sSICharges, SIGSTChargesRate);
    						
    						ESBTransferToGLBean m_oGSTESBTransferToGLBean = m_oEsbServices.chargesTransfer (m_sFromAccount,
    								ResourcesUtils.getGLAccountResource ("gl.account.gst"), SIGSTCharges, ESBConstants.SI_GST_CHARGES+":"+m_sEsbDescription, null, "", "", "", "");
    						
    						String m_sSIGSTChargeResponseCode = m_oGSTESBTransferToGLBean.getResponseCode ();
	    					if (ESBConstants.IB_SUCCESS_RC.equalsIgnoreCase (m_sSIGSTChargeResponseCode)){
	    						m_boSIGSTChargeStatus = true;
	    						m_sSIGSTChargesRefNo = m_oGSTESBTransferToGLBean.getReferenceNo ();
	    					}else{
	    						m_boIsFundSufficient = false;
								hasReceipt = false;
								m_sStatus = ResourcesUtils.getUnsuccessful ();
								m_sReason = m_oESBTransferToGLBean.getErrorMessage ();
	    						
	    						ESBTransferGLtoCASABean m_oESBTransferGLtoCASABean = m_oEsbServices.transferGLtoCASA(m_sChargeGLAccount, m_sFromAccount, m_sSICharges, ESBConstants.SI_CHARGES_REVERT, null, "", "");
	    						
	    						String m_sSIGSTRevertChargeResponseCode = m_oESBTransferGLtoCASABean.getResponseCode ();
	    						if (ESBConstants.IB_SUCCESS_RC.equalsIgnoreCase (m_sSIGSTRevertChargeResponseCode)){
	    							m_boSIChargeRevertStatus = true;
	    							m_sSIChargesRevertRefNo = m_oESBTransferGLtoCASABean.getReferenceNo();
	    						}
	    					}
						}
						else
						{
							m_boIsFundSufficient = false;
							hasReceipt = false;
							m_sStatus = ResourcesUtils.getUnsuccessful ();
							m_sReason = m_oESBTransferToGLBean.getErrorMessage ();
						}
					}
					else
					{
						m_boIsFundSufficient = false;
						hasReceipt = false;
						m_sStatus = ResourcesUtils.getUnsuccessful ();
						m_sReason = ResourcesUtils.getApplicationResourceMessage (SIConstants.RESOURCES_INSUFFICIENT_FUND);
					}
				}
			}

			// Makesure m_boIsFundSufficient is NEVER set to false previously. Check is account balance sufficient to do transfer?
			if (m_boIsFundSufficient)
			{
				m_dTransferAmount = Double.parseDouble (m_sAmount);
				m_dTotalAmount = m_dTransferAmount + m_dSICharges + Double.parseDouble(SIGSTCharges);

				if(m_dAvailableBal < m_dTotalAmount)
				{
					m_boIsFundSufficient = false;
					hasReceipt = false;
					m_sStatus = ResourcesUtils.getUnsuccessful ();
					m_sReason = ResourcesUtils.getApplicationResourceMessage (SIConstants.RESOURCES_INSUFFICIENT_FUND);
				}
			}

			if (m_boIsFundSufficient)
			{
				ESBFundTransferOwnBean m_oOwnTransfer = m_oEsbServices.ownFundTransfer (m_sFromAccount, m_sToAccount,
						m_sEsbDescription, m_sAmount, null);

				String m_sResponseCode = m_oOwnTransfer.getResponseCode ();
				m_sFromAccNewBal = m_oOwnTransfer.getFromAccountBalance ();
				m_sToAccNewBal = m_oOwnTransfer.getToAccountBalance ();
				m_sReferenceNo = m_oOwnTransfer.getReferenceNo ();
				
				
				m_oOwnTransfer.getToAccountBalance();
				if (ESBConstants.IB_SUCCESS_RC.equalsIgnoreCase (m_sResponseCode))
				{
					hasReceipt = true;
					m_sStatus = ResourcesUtils.getSuccessful ();
				}
				else //handle the negative testing,status=UNSUCCESSFUL
				{
					m_sStatus = ResourcesUtils.getUnsuccessful ();
					m_sReason = m_oOwnTransfer.getErrorMessage ();
				}
			}

			//get new trnx id
			String m_sTransID = IBUtils.getTransactionId (m_oSessionObj.getDataManager ());

			if(hasReceipt)
			{
				Map<String, String> m_oReceiptDetails = new LinkedHashMap <String, String> ();
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("receipt.transaction.type"), trnxTypeDisplay);
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.status"), m_sStatus);
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.fromAccount"), m_sFromAccount);
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.toAccount"), m_sToAccount);
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.amount"),
						FormatterUtils.formatMoneyDisplay (m_sAmount, fromCurrency, true));

				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.reference.number"), FormatterUtils.formatTransID (m_sTransID));
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.reference"), m_sReferenceNo );

				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.transaction.date"), DateTimeUtils.formatDayMonthYear (m_oCurrentBVIDateTime));
				m_oReceiptDetails.put (ResourcesUtils.getApplicationResourceMessage ("general.transaction.time"), m_oCurrentBVIDateTime.getTime ());

				//insert into table IB_RECEIPT_DETAILS
				IBUtils.loopIntoReceiptDetails (p_oEnterpriseServices, m_oReceiptDetails, m_oCurrentBVIDateTime.getSimpleDate (), m_sTransID);
			}
			//log into si history
			IBLogger.logSIHistory(p_oEnterpriseServices, rimNo, siId, m_sTransID, m_oCurrentBVIDateTime.getJavaDate (),
					SIConstants.TRANSCODE_OWN_TRANSFER,
					m_sFromAccount, m_sToAccount, fromCurrency, toCurrency,
					m_sAmount,
					"0", // ForeignAmount
					charges,
					m_sSICharges, // SICharges
					m_sStatus,
					m_sReason,
					m_sReferenceNo,
					"", // PhxRevRefNo
					false, // PhxRevStatus
					"", // EpayRefNo
					"", // PhxChargeRefNo
					false, // PhxChargeStatus
					"", // PhxChargeRevRefNo
					false, // PhxCharRevStatus
					m_sSIChargesRefNo, // SIChargeRefNo
					m_boSIChargeStatus,
					m_sSIChargesRevertRefNo, // SIChargeRevRefNo
					m_boSIChargeRevertStatus, // SIChargeRevStatus
					"",
					hasReceipt,
					m_sSIGSTCharges, // SI GST Charges
					"", // Service GST Charges
					"", // SIGSTChargesRevertRefNo
					false); // SIGSTChargeRevertStatus
			
			//SMS Notification START
			SMSServices.sendCustomerSMSForSI (
					p_oEnterpriseServices, 
					userId, 
					"", 
					SIConstants.TRANSCODE_OWN_TRANSFER, 
					m_sStatus, 
					m_sTransID, 
					m_sFromAccount, 
					m_sAmount, 
					m_oCurrentBVIDateTime,
					FormatterUtils.formatMoneyDisplay (m_sFromAccNewBal, m_sFromAccIsoCurr, true),
					visitor.getName().length()>15?visitor.getName().substring(0, 15):visitor.getName());
			
			Map m_oCustomerInfo = SMSServices.getCustomerProfileForSI(p_oEnterpriseServices, userId);
			
			SMSServices.sendBeneficiarySMSForSI(
					p_oEnterpriseServices, 
					userId, 
					"", 
					SIConstants.TRANSCODE_OWN_TRANSFER, 
					m_sStatus, 
					m_sTransID, 
					m_sToAccount, 
					(String) m_oCustomerInfo.get (AccessConstants.COL_MOBILE_NUMBER),
					m_sAmount, 
					m_oCurrentBVIDateTime,
					FormatterUtils.formatMoneyDisplay (m_sToAccNewBal, m_sToAccIsoCurr, true));
			//SMS Notification END
		}
		catch(Exception e)
		{
			e.printStackTrace();
        	if (e instanceof IBGenericException)
            {
                throw (IBGenericException) e;
            }
            throw IBErrorHandler.createServiceException(IBServiceException.GENERAL_SERVICE_ERROR, true,
                    new String[] {CommonErrorCode.GENERIC_CODE, "", "", "", IBErrorHandler.generateErrorMessage(e)}, c_oClass);
		}
		IBLogger.logBSFNMethodLeavingMessage (c_oClass, m_sMethodName, m_oTimer);
	}
}
