package com.bizofficer.subscription.payments;



import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bizofficer.hibernate.entity.PgprepStudentCourses;
import com.bizofficer.hibernate.entity.PgprepStudentDetails;
import com.bizofficer.hibernate.entity.SubscriptionCourses;
import com.bizofficer.hibernate.entity.SubscriptionPaymentPayload;
import com.bizofficer.hibernate.entity.SubscriptionPaymentTransaction;
import com.bizofficer.hibernate.entity.SubscriptionPromocode;
import com.bizofficer.hibernate.repository.PgprepStudentCoursesRepository;
import com.bizofficer.hibernate.repository.PgprepStudentDetailsRepository;
import com.bizofficer.hibernate.repository.SubscriptionCoursesRepository;
import com.bizofficer.hibernate.repository.SubscriptionPaymentPayloadRepository;
import com.bizofficer.hibernate.repository.SubscriptionPaymentTransactionRepository;
import com.bizofficer.subscription.courses.SelectedOrganisationBean;
import com.bizofficer.util.module.MysqlTableNames;
import com.bizofficer.util.system.General;
import com.bizofficer.util.system.MakeDate;


@Service
public class PaymentTokenGenerateService{
	
	private static final Logger logger = Logger.getLogger(PaymentTokenGenerateService.class);
	
    @Autowired
	EntityManagerFactory entityManagerFactory;
    
    @Autowired
    SubscriptionPaymentPayloadRepository sppRepo;
    
    @Autowired
	PgprepStudentDetailsRepository stuRepo;
    
    @Autowired
    SubscriptionCoursesRepository corsRepo;
    
    @Autowired
    PgprepStudentCoursesRepository pscRepo;
    
    @Autowired
    SubscriptionPaymentTransactionRepository sptRepo;
    
    @Autowired
    DataSource appDataSource;
    Connection conn;
    
	@SuppressWarnings("unchecked")
	public Object execute(APayBean objBean){		 	
		PaymentTokenResponseBean responseBeanObj = new PaymentTokenResponseBean();
		
		try {
			responseBeanObj.setResponseTxt("failed"); 
			
			logger.info("courseId: "+objBean.getCourseId() );
			logger.info("courseTitle: "+objBean.getCourseName() );
			logger.info("StudentId: "+objBean.getStudentId() );
			logger.info("studentName: "+objBean.getStudentName() );
			logger.info("Email: "+objBean.getEmail() );
			logger.info("Phone: "+objBean.getPhone() );

			logger.info("PromoCode: "+objBean.getPromoCode() );
			
			if(objBean.getStudentId()==null || objBean.getCourseId()==null) {
				return responseBeanObj;
			}
			
			PgprepStudentDetails stuObj = (PgprepStudentDetails) stuRepo.findIdByStudentId(objBean.getStudentId());
			if(stuObj==null) {
				return responseBeanObj;
			}
			
			logger.info("Verified Student >> " + stuObj.getId() );
			
			SubscriptionCourses myCourse = corsRepo.findByCourseId(objBean.getCourseId());
			logger.info("Sale Price: " + myCourse.getSalePrice() );
			
			BigDecimal payableAmount = myCourse.getSalePrice();
			Boolean promoCodeApplied = false;

			EntityManager entityManager = entityManagerFactory.createEntityManager();
			entityManager.getTransaction().begin();
			
			logger.info("***********************************************************");
			logger.info("PROMO CODE START");
			logger.info("***********************************************************");
			logger.info("webUrl: " + objBean.getWebUrl() );
			logger.info("PromoCode: " + objBean.getPromoCode() );
			if(objBean.getPromoCode()!=null && objBean.getPromoCode().length()>0 ) {
				TypedQuery<SubscriptionPromocode> query = (TypedQuery<SubscriptionPromocode>) entityManager.createQuery("from "+SubscriptionPromocode.class.getName()+" WHERE discount>0 AND CURDATE()>=startDate AND CURDATE()<=endDate AND status=1 AND webUrl=:webUrl AND code=:code  ", SubscriptionPromocode.class);
				query.setParameter("webUrl", objBean.getWebUrl());
				query.setParameter("code", objBean.getPromoCode());
				query.setFirstResult(0);
				query.setMaxResults(1);
				List<?> resultList = query.getResultList();
				Iterator<?> iterator=resultList.iterator();
				if(iterator.hasNext()){
					SubscriptionPromocode myObj = (SubscriptionPromocode)iterator.next();		
					
					logger.info("Valid Code: " + objBean.getPromoCode() );
					
					BigDecimal amount = new BigDecimal(0);
					if("Percent".equals(myObj.getDiscountType()) && myObj.getDiscount()>0 && myCourse.getSalePrice().compareTo(new BigDecimal(0))==1) {
						BigDecimal discountedAmount = new BigDecimal(myObj.getDiscount()).divide(new BigDecimal(100)).multiply(myCourse.getSalePrice());
						logger.info("DiscountedAmount: " + discountedAmount );
						amount = myCourse.getSalePrice().subtract(discountedAmount);
						logger.info("Amount: " + amount );
						promoCodeApplied = true;
					}else if(myObj.getDiscount()>0 && myCourse.getSalePrice().compareTo(new BigDecimal(0))==1){ // Fixed
						if(myObj.getDiscount()!=null && myCourse.getSalePrice().compareTo(new BigDecimal(myObj.getDiscount()))==1 ) {
							amount = myCourse.getSalePrice().subtract(new BigDecimal(myObj.getDiscount()));
							logger.info("Fixed Amount: " + amount );
							promoCodeApplied = true;
						}
					}
					
					logger.info("Final Calculated: " + amount );
					
					if(myObj.getCourseId()!=null && myObj.getCourseId()>0) {
						if(myObj.getCourseId()==objBean.getCourseId()) {						
							payableAmount = amount;
						}
					}else{
						payableAmount = amount;
					}
					
				}
			}
			logger.info("***********************************************************");
			logger.info("PROMO CODE END");
			logger.info("***********************************************************");
			
			logger.info("Payment Gateway Amount: " + payableAmount );
			
			MakeDate dateObj = new MakeDate();
			
			/// IF AMOUNT IS GREATER THAN 0 THAN IT WILL GO TO PAYMENT GATEWAY
			if(new BigDecimal(0).compareTo(payableAmount)==-1) {
	   			   
	        	   General gen = new General();
	   			   
        		   String token = UUID.randomUUID().toString();
        		   token = token.replaceAll("-", "")+gen.getRandomNumber(111002, 999102);
        		   
        		   JSONObject jsonObj  = new JSONObject();
        		   jsonObj.put("sid", stuObj.getId());
        		   jsonObj.put("courseId", objBean.getCourseId());
        		   jsonObj.put("courseTitle", objBean.getCourseName());
        		   jsonObj.put("studentId", objBean.getStudentId());
        		   jsonObj.put("studentName", objBean.getStudentName());
        		   jsonObj.put("email", objBean.getEmail());
        		   jsonObj.put("phone", objBean.getPhone());
        		   jsonObj.put("amount",payableAmount.intValue());
        		   
        		   if(Boolean.TRUE.equals(promoCodeApplied)) {
        			   jsonObj.put("promoCode",objBean.getPromoCode());
        		   }
        		   
        		   SubscriptionPaymentPayload saveObj = new SubscriptionPaymentPayload();
   				   saveObj.setPayload(jsonObj.toJSONString());
   				   saveObj.setToken(token);
   				   saveObj.setCreatedDate(dateObj.getCurrentTimeStamp());

   				   sppRepo.save(saveObj);
	        	   
   				   ///PAYU PAYMENT GATEWAY DETAILS
   				   String merchantKey = "GnfiLS";
   				   String merchantSalt = "VS7BpkRY";
   				   
	   			   responseBeanObj.setToken(token);
	   			   responseBeanObj.setKey(merchantKey);
	   			   responseBeanObj.setProductinfo("Exam: "+objBean.getCourseName());
	   			   responseBeanObj.setAmount(payableAmount.intValue());
	   			   
	   			   ////key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|udf6|udf7|udf8|udf9|udf10
	   			   
	   			   String hashCode = responseBeanObj.getKey()
	   					   +"|"+responseBeanObj.getToken()
	   					   +"|"+responseBeanObj.getAmount()
	   					   +"|"+responseBeanObj.getProductinfo()
	   					   +"|"+objBean.getStudentName()	   					   
	   					   +"|"+objBean.getEmail()
	   					   +"|||||||||||"+merchantSalt;
	   			   
	   			   responseBeanObj.setHashCode(gen.getSHA(hashCode));
	   			   
	   			   logger.info("Hash: "+responseBeanObj.getHashCode() );
	   		
	   		/// IF AMOUNT IS 0 THAN IT WILL LINK TO COURSE DIRECTLY	   
			}else {
				logger.info("*****************************************");
				logger.info("GET IT FREE");
				logger.info("*****************************************");
				
				TypedQuery<PgprepStudentCourses> querySC = (TypedQuery<PgprepStudentCourses>) entityManager.createQuery("from "+PgprepStudentCourses.class.getName()+" WHERE studentId=:studentId AND courseId=:courseId ", PgprepStudentCourses.class);
				querySC.setParameter("studentId", objBean.getStudentId() );
				querySC.setParameter("courseId", objBean.getCourseId() );			
				querySC.setFirstResult(0);
				querySC.setMaxResults(1);
				List<?> resultListSC = querySC.getResultList();
				Iterator<?> iteratorSC=resultListSC.iterator();
				if(iteratorSC.hasNext()){
					PgprepStudentCourses myObjSTCors = (PgprepStudentCourses)iteratorSC.next();
					
					logger.info("FREE TRIAL FOUND");
					
					TypedQuery<SubscriptionCourses> queryCors = (TypedQuery<SubscriptionCourses>) entityManager.createQuery("from "+SubscriptionCourses.class.getName()+" WHERE courseId=:courseId ", SubscriptionCourses.class);
					queryCors.setParameter("courseId", objBean.getCourseId() );			
					queryCors.setFirstResult(0);
					queryCors.setMaxResults(1);
					List<?> resultCors = queryCors.getResultList();
					Iterator<?> iteratorCors=resultCors.iterator();
					if(iteratorCors.hasNext()){
						SubscriptionCourses myCors = (SubscriptionCourses)iteratorCors.next();
	
						logger.info("UPDATE FREE TO PAID COURSE TO STUDENT WITH GET IT FREE ");
						PgprepStudentCourses editObj = (PgprepStudentCourses)entityManager.find(PgprepStudentCourses.class ,myObjSTCors.getId());
						editObj.setSubscriptionType("PAID");
						editObj.setOrganisationId(myCors.getPaidOrganisationId());
						if(myCors.getValidityDate()!=null) {
							editObj.setValidTillDate(dateObj.getStringToDate(myCors.getValidityDate().toString(), "yyyy-MM-dd"));
						}
						entityManager.getTransaction().commit();

						// SAVE TRANSACTION ********************************************
						SubscriptionPaymentTransaction sptSave = new SubscriptionPaymentTransaction();
						sptSave.setWebsiteId(myCors.getWebsiteId());
						sptSave.setDomainName(myCors.getWebUrl());	
						sptSave.setStudentId(objBean.getStudentId());
						sptSave.setStudentName(objBean.getStudentName());
						sptSave.setCourseId(myCors.getCourseId());
						sptSave.setCourseName(myCors.getCourseTitle());
						sptSave.setAmount(new BigDecimal(0));
						sptSave.setReferenceNumber("");
						sptSave.setTxnid("");
						if(Boolean.TRUE.equals(promoCodeApplied)) {
							sptSave.setPromoCode(objBean.getPromoCode());
		        		}
						sptSave.setCreatedDateTime(dateObj.getCurrentTimeStamp());
						sptRepo.save(sptSave);
						
					}
					
				}else {
					
					logger.info("FREE TRIAL NOT FOUND");
					
					TypedQuery<SubscriptionCourses> queryCors = (TypedQuery<SubscriptionCourses>) entityManager.createQuery("from "+SubscriptionCourses.class.getName()+" WHERE courseId=:courseId ", SubscriptionCourses.class);
					queryCors.setParameter("courseId", objBean.getCourseId() );			
					queryCors.setFirstResult(0);
					queryCors.setMaxResults(1);
					List<?> resultCors = queryCors.getResultList();
					Iterator<?> iteratorCors=resultCors.iterator();
					if(iteratorCors.hasNext()){
						SubscriptionCourses myCors = (SubscriptionCourses)iteratorCors.next();
	
						logger.info("ADD NEW PAID COURSE TO STUDENT WITH GET IT FREE ");
						PgprepStudentCourses saveObj = new PgprepStudentCourses();
						saveObj.setSid(stuObj.getId());
						saveObj.setCourseId(objBean.getCourseId());
						saveObj.setCourseTitle(myCors.getCourseTitle());					
						saveObj.setStudentId(objBean.getStudentId());
						saveObj.setSubscriptionType("PAID");
						saveObj.setOrganisationId(myCors.getPaidOrganisationId());						
						if(myCors.getValidityDate()!=null) {
							saveObj.setValidTillDate(dateObj.getStringToDate(myCors.getValidityDate().toString(), "yyyy-MM-dd"));
						}						
						pscRepo.save(saveObj);

						// SAVE TRANSACTION ********************************************
						SubscriptionPaymentTransaction sptSave = new SubscriptionPaymentTransaction();
						sptSave.setWebsiteId(myCors.getWebsiteId());
						sptSave.setDomainName(myCors.getWebUrl());	
						sptSave.setStudentId(objBean.getStudentId());
						sptSave.setStudentName(objBean.getStudentName());
						sptSave.setCourseId(myCors.getCourseId());
						sptSave.setCourseName(myCors.getCourseTitle());
						sptSave.setAmount(new BigDecimal(0));
						sptSave.setReferenceNumber("");
						sptSave.setTxnid("");
						if(Boolean.TRUE.equals(promoCodeApplied)) {
							sptSave.setPromoCode(objBean.getPromoCode());
		        		}
						sptSave.setCreatedDateTime(dateObj.getCurrentTimeStamp());
						sptRepo.save(sptSave);
						
						
					}
					
				}
				
				SelectedOrganisationBean orgBeanObj = new SelectedOrganisationBean();
                List<SelectedOrganisationBean> organisationList = new ArrayList<SelectedOrganisationBean>();
                
                this.conn = this.appDataSource.getConnection();
                if (this.conn != null && objBean.getStudentId()!=null && objBean.getStudentId().length()>0) {

                    PreparedStatement stmtA = conn.prepareStatement("SELECT m.*, ot.template_id, s.validTillDate, s.courseTitle, s.courseId, s.subscriptionType, s.id as validityId FROM "+MysqlTableNames.getPgprepStudentCourses()+" s, "+MysqlTableNames.getOrganisationTemplateAssociation()+" ot, "+MysqlTableNames.getPgprepOrganisationMenu()+" m WHERE s.organisationId = ot.organisation_id AND s.organisationId = m.organisationId AND s.studentId=? group by s.courseId order by s.id ");
                    stmtA.setString(1, objBean.getStudentId());
                    logger.info("Organisations LIST FETCHING: " + stmtA);
                    ResultSet myRow = stmtA.executeQuery();
                    while (myRow.next()) {
                    	orgBeanObj = new SelectedOrganisationBean();
                    	
                    	logger.info("Validity_Id::::: " + myRow.getInt("validityId"));
                    	logger.info("Course_Id::::: " + myRow.getInt("courseId"));
                    	logger.info("Organisation_Id::::: " + myRow.getInt("organisationId"));
                    	logger.info("Course_Title::::: " + myRow.getString("courseTitle"));
                    	logger.info("Template_id::::: " + myRow.getInt("template_id"));
                    	logger.info("Subscription_Type::::: " + myRow.getString("subscriptionType"));
                    	
                    	orgBeanObj.setValidityId(myRow.getInt("validityId"));
                    	orgBeanObj.setCourseId(myRow.getInt("courseId"));
                    	orgBeanObj.setOrganisationId(myRow.getInt("organisationId"));
                    	orgBeanObj.setOrganisationName(myRow.getString("courseTitle"));
                    	orgBeanObj.setTemplateId(myRow.getInt("template_id"));
                    	orgBeanObj.setValidTillDate(myRow.getString("validTillDate"));
                    	orgBeanObj.setSubscriptionType(myRow.getString("subscriptionType"));
                    	
                    	orgBeanObj.setDashboard(myRow.getInt("dashboard"));
                    	orgBeanObj.setReport(myRow.getInt("report"));
                    	orgBeanObj.setSmartLearning(myRow.getInt("smartLearning"));
                    	orgBeanObj.setSelfTest(myRow.getInt("selfTest"));
                    	orgBeanObj.setTopicTest(myRow.getInt("topicTest")); 
                    	orgBeanObj.setMockTest(myRow.getInt("mockTest")); 
                    	orgBeanObj.setClassTest(myRow.getInt("classTest"));
                    	
                    	organisationList.add(orgBeanObj);
                    }
                	
                }
                
                responseBeanObj.setOrganisations(organisationList);
                this.conn.close();

			}
	   			   
	   			   
	   			   responseBeanObj.setResponseTxt("success");
	   			  
	   			
            entityManager.getTransaction().commit();
			entityManager.close();
			
		}catch(Exception e) {
			e.getStackTrace();			
		}
		
		
		return responseBeanObj;
	}
	
	
	
	
}
