package performa.utils;

import com.stripe.Stripe;
import com.stripe.exception.APIConnectionException;
import com.stripe.exception.APIException;
import com.stripe.exception.AuthenticationException;
import com.stripe.exception.CardException;
import com.stripe.exception.InvalidRequestException;
import com.stripe.model.Card;
import com.stripe.model.Customer;
import com.stripe.model.ExternalAccount;
import com.stripe.model.ExternalAccountCollection;
import com.stripe.model.Plan;
import com.stripe.model.Subscription;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import oneit.appservices.config.ConfigMgr;
import oneit.logging.LogLevel;
import oneit.logging.LogMgr;
import oneit.logging.LoggingArea;
import oneit.objstore.StorageException;
import oneit.security.SecUser;
import oneit.utils.DateDiff;
import oneit.utils.parsers.FieldException;
import performa.orm.Company;
import performa.orm.CompanyUser;


public class StripeUtils 
{
    public static final String  STRIPE_KEY          =   ConfigMgr.getKeyfileString("stripe.key","");
    public static final String  STRIPE_PUB_KEY      =   ConfigMgr.getKeyfileString("stripe.pubkey","");
    public static final String  STRIPE_PLAN_ID      =   ConfigMgr.getKeyfileString("stripe.plan.id","0001");
    public static final String  STRIPE_COUPON_ID    =   ConfigMgr.getKeyfileString("stripe.coupon.id","EAP");
    
    static
    {
        Stripe.apiKey   =   STRIPE_KEY;
    }
    
    
    public static void createCustomer(CompanyUser companyUser) throws FieldException
    {
        try 
        {
            Company             company         =   companyUser.getCompany();
            SecUser             secUser         =   companyUser.getUser();
            Map<String, Object> customerParams  =   new HashMap<>();

            customerParams.put("description", company);
            customerParams.put("email", secUser.getEmail());
            
            Customer    customer    =   Customer.create(customerParams);
            
            company.setStripeReference(customer.getId());
            
        } 
        catch (StorageException | AuthenticationException | InvalidRequestException | APIConnectionException | CardException | APIException ex) 
        {
            LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, ex, "Error while creating a customer in stripe");
        } 
    }
    
    
    public static Card updateCardDetails(Company company, String token) throws FieldException
    {
        try 
        {
            if(company.getStripeReference() == null)
            {
                createCustomer(company.getAddedByUser());
            }
            
            Customer customer = Customer.retrieve(company.getStripeReference());
            
            Map<String, Object> updateParams = new HashMap<>();
            
            updateParams.put("source", token);

            customer    =   customer.update(updateParams);
            
            return (Card) customer.getSources().retrieve(customer.getDefaultSource());
            
        } 
        catch (StorageException | AuthenticationException | InvalidRequestException | APIConnectionException | CardException | APIException ex) 
        {
            LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, ex, "Error while updating a customer in stripe");
        } 
        
        return null;
    }
    
    
    public static Card retrieveCard(Company company) throws FieldException
    {
        try 
        {
            Customer customer = Customer.retrieve(company.getStripeReference());
            
            return (Card) customer.getSources().retrieve(customer.getDefaultSource());
        } 
        catch (StorageException | AuthenticationException | InvalidRequestException | APIConnectionException | CardException | APIException ex) 
        {
            LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, ex, "Error while updating a customer in stripe");
        } 
        
        return null;
    }
    
    
    public static void subscribeCustomer(Company company) throws FieldException
    {
        try 
        {
            Plan    plan        =   Plan.retrieve(STRIPE_PLAN_ID);
            Date    today       =   new Date(); 
            Date    trialExpiry =   DateDiff.add(today, Calendar.DATE, plan.getTrialPeriodDays());
            
            Map<String, Object> item    =   new HashMap<>();
            item.put("plan", STRIPE_PLAN_ID);

            Map<String, Object> items   =   new HashMap<>();
            items.put("0", item);

            Map<String, Object> params  =   new HashMap<>();
            params.put("items", items);
            params.put("coupon", STRIPE_COUPON_ID);
            params.put("customer", company.getStripeReference());
            params.put("trial_end", trialExpiry.getTime() / 1000L);

            Subscription    subscription    =   Subscription.create(params);
            
            company.setStripeSubscription(subscription.getId());
        } 
        catch (StorageException | AuthenticationException | InvalidRequestException | APIConnectionException | CardException | APIException ex) 
        {
            LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, ex, "Error while creating subscrition in stripe");
        } 
    }
}
