package performa.form;

import java.util.HashMap;
import java.util.Map;
import oneit.appservices.config.ConfigMgr;
import oneit.servlets.forms.SubmissionDetails;
import oneit.servlets.process.SaveFP;
import oneit.utils.BusinessException;
import oneit.utils.StringUtils;
import oneit.utils.math.NullArith;
import oneit.utils.parsers.FieldException;
import javax.servlet.http.HttpServletRequest;
import oneit.logging.LogLevel;
import oneit.logging.LogMgr;
import oneit.objstore.StorageException;
import oneit.servlets.forms.SuccessfulResult;
import oneit.servlets.process.ORMProcessState;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.Card;
import com.stripe.model.Charge;
import oneit.logging.LoggingArea;
import oneit.security.SecUser;
import performa.orm.Company;
import performa.orm.CompanyUser;
import performa.utils.StripeUtils;


public class MakePaymentFP extends SaveFP
{

    public  static final String         STRIPE_KEY      =   ConfigMgr.getKeyfileString("stripe.key","");
    public  static final String         STRIPE_PUB_KEY  =   ConfigMgr.getKeyfileString("stripe.pubkey","");
    private static final LoggingArea    LOG             =   LoggingArea.createLoggingArea("MakePaymentFP");

    @Override
    public SuccessfulResult processForm(ORMProcessState process, SubmissionDetails submission, Map p) throws BusinessException, StorageException
    {
        HttpServletRequest  request =   submission.getRequest();
        
        LogMgr.log(LOG, LogLevel.PROCESSING1,"In MakePaymentFP : " );

        Stripe.apiKey = STRIPE_KEY;
            
        String              token                   = request.getParameter("stripe-token-id");
        
        if(StringUtils.subBlanks(token) == null)
        {
            throw new BusinessException("Updating card details failed, Please contact adminstrator for more info.");
        }
        
        try
        {
            SecUser     secUser     =   SecUser.getTXUser(process.getTransaction());
            CompanyUser companyUser =   secUser.getExtension(CompanyUser.REFERENCE_CompanyUser);
            Card        card        =   StripeUtils.updateCardDetails(companyUser.getCompany(), token);
            Company     company     =   companyUser.getCompany();
            
            company.setNameOnCard(card.getName());
            company.setCardPostCode(card.getAddressZip());
            company.setCardID(card.getId());
        }
        catch(StorageException | FieldException e)
        {
            LogMgr.log(LOG, LogLevel.PROCESSING1, e, "Error while making payment");
        }

        return super.processForm(process, submission, p);
    }
    
    
    private void performStripePayment(SubmissionDetails submission) throws FieldException, BusinessException
    {
        HttpServletRequest  request                     = submission.getRequest();
        String              token                   = request.getParameter("stripe-token-id");
        
        if(StringUtils.subBlanks(token) == null)
        {
            throw new BusinessException("Stripe payment was failed, Please contact adminstrator for more info.");
        }
        
        Stripe.apiKey = STRIPE_KEY;

        // Charge the Customer instead of the card:
        Map<String, Object> chargeParams = new HashMap<>();
        chargeParams.put("amount", NullArith.intVal(NullArith.multiply(100d, 100, 0d)));
        chargeParams.put("currency", "aud");
        chargeParams.put("description", "Charges of creating job");
        chargeParams.put("source", token);
        Charge charge;
        
        try
        {
            charge = Charge.create(chargeParams);
        }
        catch (StripeException e)
        {
            throw new BusinessException("Stripe payment failure. Reason :: " + e.getMessage());
        }
        if(charge.getFailureCode() != null)
        {
            String errorMsg = "Stripe payment failure Code :: " + charge.getFailureCode() + ", Message :: " + charge.getFailureMessage();
            
            if(charge.getFraudDetails() != null)
            {
                errorMsg += ", Fraud Details :: " + charge.getFraudDetails();
            }
            
            throw new BusinessException(errorMsg);
        }
    }
}