package performa.orm;

import com.stripe.model.Card;
import com.stripe.model.Coupon;
import java.util.Date;
import java.util.Set;
import oneit.logging.LoggingArea;
import oneit.objstore.FieldWriteability;
import oneit.objstore.ValidationContext;
import oneit.objstore.rdbms.filters.EqualsFilter;
import oneit.security.SecUser;
import oneit.utils.DateDiff;
import oneit.utils.StringUtils;
import oneit.utils.filter.Filter;
import oneit.utils.parsers.FieldException;
import performa.orm.types.AssessmentType;
import performa.orm.types.RoleType;
import performa.utils.StripeUtils;


public class HiringTeam extends BaseHiringTeam
{
    private static final long serialVersionUID = 0L;
    
    public  static LoggingArea  LOG = LoggingArea.createLoggingArea("HiringTeam");

    // This constructor should not be called
    public HiringTeam ()
    {
        // Do not add any code to this, always put it in initialiseNewObject
    }
    
    public boolean showHasClientSupport()
    {
        return isTrue(getHasClientSupport());
    }
    
    @Override
    public void validate(ValidationContext context) 
    {
//        if(getStatus() != ObjectStatus.NEW)
//        {
//            context.check(getHiringTeamType() != null , this, FIELD_HiringTeamType, "mandatory");
//        }
        
        super.validate(context);
    }
        
    @Override
    public String getToString() 
    {
        return StringUtils.subNulls(getHiringTeamName(), super.getToString());
    }
    
    public Set<CompanyUser> getActiveTeammates()
    {
        Filter<CompanyUser> filter  =   CompanyUser.SearchByAll()
                                                    .andIsAccountVerified(new EqualsFilter<>(Boolean.TRUE))
                                                    .andIsDisabled(new EqualsFilter<>(Boolean.FALSE));
        
        return CompanyUserHiringTeamLink.pipesCompanyUserHiringTeamLink(getUsersSet()).toCompanyUser(filter).uniqueVals();
    }
    
    public boolean isPPJ()
    {
        return isTrue(getIsPPJ());
    }
    
    public int getRemainingJobs()
    {
        return getPaymentPlan() != null && getPaymentPlan().getActiveJobCount() != null ? 
                    getPaymentPlan().getActiveJobCount() - getUsedCredits() : 0;
    }
    
    public Card getCard() throws FieldException
    {
       return StripeUtils.retrieveCard(this);
    }
    
    
    public String getCardNumber() throws FieldException
    {
        if(getStripeLast4() == null)
        {
            Card    card    =   StripeUtils.retrieveCard(this);
            
            if(card != null)
            {
                setStripeLast4(card.getLast4());
                setStripeBrand(card.getBrand());
                
                return "xxxx-xxxx-xxxx-" + getStripeLast4();
            }
            else
            {
                return "";
            }
        }
        
        return "xxxx-xxxx-xxxx-" + getStripeLast4();
    }
    
    
    public String getExpiry () throws FieldException
    {
        Card    card    =   StripeUtils.retrieveCard(this);

        return card != null ? String.format("%02d", card.getExpMonth()) + " / " + (card.getExpYear() % 100) : "";
    }

    
    @Override
    public Integer getMaxCap() 
    {
        return super.getMaxCap()!= null ? super.getMaxCap() : 0;
    }
    
    
    @Override
    public Integer getUsedCredits() 
    {
        return super.getUsedCredits() != null ? super.getUsedCredits() : 0;
    }
    
    
    @Override
    public Integer getAvailableCredits() 
    {
        return super.getAvailableCredits()!= null ? super.getAvailableCredits() : 0;
    }
    
    
    public boolean hasValidCoupon() throws FieldException
    {
        if(getCoupon() != null)
        {
            Coupon coupon   =   StripeUtils.retrieveCoupon(getCoupon().getCouponCode());

            if(coupon.getValid() && (getCouponExpiryDate() == null  || DateDiff.getToday().before(getCouponExpiryDate())))
            {
                return true;
            }
        }
        
        setCoupon(null);
        setCouponExpiryDate(null);
        
        return false;
    }
    
    
    public boolean hasValidCouponOn(Date date) throws FieldException
    {
        if(getCoupon() != null)
        {
            Coupon coupon   =   StripeUtils.retrieveCoupon(getCoupon().getCouponCode());

            if(coupon.getValid() && (getCouponExpiryDate() == null  || date.before(getCouponExpiryDate())))
            {
                return true;
            }
        }
        
        return false;
    }
    
    public boolean canCreateJob()
    {        
        if(getManageOwnBilling())
        {
            return getAvailableCredits()  > getUsedCredits() || !getHasCap() || (getHasCap() && getMaxCap() > getUsedCredits());
        }
        
        return getBilledByTeam().canCreateJob();
    }

    
    @Override
    public FieldWriteability getObjectWriteability() 
    {
        SecUser secUser =   SecUser.getTXUser(getTransaction());
        
        if(secUser != null && secUser.getExtension(CompanyUser.REFERENCE_CompanyUser) != null)
        {
            CompanyUser companyUser =   secUser.getExtension(CompanyUser.REFERENCE_CompanyUser);
            
            if(companyUser != null && companyUser.getRoleForHiringTeam(this) == RoleType.STANDARD)
            {
                return FieldWriteability.NOT_IN_GUI;
            }
        }
        
        return super.getObjectWriteability();
    }

    
    @Override
    public FieldWriteability getWriteability_ManageOwnBilling() 
    {
        if(getManageOwnBilling() && getBillingTeamsCount() > 0)
        {
            return FieldWriteability.NOT_IN_GUI;
        }
        
        return super.getWriteability_ManageOwnBilling();
    }

    @Override
    public FieldWriteability getWriteability_BilledByTeam() 
    {
        if(!getManageOwnBilling())
        {
            return FieldWriteability.NOT_IN_GUI;
        }
        
        return super.getWriteability_ManageOwnBilling();
    }
    
    public Double getPPJAmount(Job job)
    {
        double amount   =   job != null ? (job.getAssessmentType() == AssessmentType.COMPREHENSIVE ? PaymentPlan.PER_PER_JOB_AMOUNT : PaymentPlan.PER_PER_JOB_EXPRESS) : PaymentPlan.PER_PER_JOB_AMOUNT;
        
        return amount * (getCoupon() != null ? (100 - getCoupon().getPercentageOff()) * 0.01 : 1);
    }
}