package gov.va.med.esr.common.batchprocess;

import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;
import gov.va.med.esr.service.PersonService;
import gov.va.med.fw.batchprocess.AbstractDataProcess;
import gov.va.med.fw.batchprocess.AbstractDataQueryIncrementalProcess;
import gov.va.med.fw.batchprocess.AbstractDataQueryProcess;
import gov.va.med.fw.batchprocess.DataProcessExecutionContext;
import gov.va.med.fw.batchprocess.DataQueryProcessExecutionContext;
import gov.va.med.fw.batchprocess.ProcessStatistics;
import gov.va.med.fw.service.ServiceException;


import java.math.BigDecimal;
import java.util.List;

import org.apache.commons.lang.Validate;

/**
 * The batch process is a one-time process to add 200ESR Correlation for thoses ESR records that have enrollment records,
 * but no 200ESR Correlations. This could be possible only for migrated data. 
 * This is needed for CCR 11403. After the batch job is run successfully, all ESR recores that have 
 * enrollment record are guaranteed to have 200ESR Correlation
 * 
 * @author George Tsai
 *
 */
public class Add200ESRCorrelationBatchProcess extends AbstractDataQueryProcess {
///	AbstractDataQueryIncrementalProcess {

	private final String sql_getEnrollmentWithout200ESR = 
		"SELECT ed.person_id as personId " +
			  "FROM enrollment_determination ed " +
			"WHERE NOT EXISTS ( " +
			          "SELECT p.person_id " +
			            "FROM person p, ps_person_correlation pc " +
			           "WHERE p.person_id = ed.person_id " +
			             "AND p.vpid_id = pc.person_vpid_id " +
			             "AND pc.system_of_interest_type_id = 139)";

    private PersonService personService;
    

	protected void processData(DataProcessExecutionContext context, List acquiredData) {
		if(logger.isInfoEnabled())
			logger.info("Add 200ESR Correlation batch process: result Size="+(acquiredData == null ? 0 : acquiredData.size()));

		Person person = null;
		BigDecimal personId = null;
		ProcessStatistics stats = context.getProcessStatistics();
		
		//++++++++++++++ Remove it ++++++++++++++++//
//		acquiredData.clear();
//		acquiredData.add(new BigDecimal(373964457));
//		acquiredData.add(new BigDecimal(373975270));
		
		
        // Add check for isInterrupted so don't have to wait for entire batch to finish
		for (int i = 0; i < acquiredData.size() && !isInterrupted(context); i++) {
			
            personId = (BigDecimal)  acquiredData.get(i);
			
			if(logger.isDebugEnabled())
				logger.debug("Processing person # " + (i+1) + " with id = " + personId);
			
			try {
				person = personService.getPerson(new PersonIdEntityKeyImpl(personId));
				personService.addESRCorrelation(person);
				stats.incrementNumberOfSuccessfulRecords();
 			} catch (ServiceException ex) {
 				stats.incrementNumberOfErrorRecords();
				String errMsg = "Error while executing Add 200ESR Correlation batch process for person "
								+ personId;
				context.getExceptionData().add(errMsg+ " Reason: "+ ex.getMessage());
				if(logger.isWarnEnabled())
					logger.warn(errMsg + " Reason: ", ex);
			}
            
			// Update statistics more frequently than once per batch (default size 500)
            if(stats.isTotalNumberMod(512))
                this.updateJobResult(context);
		}
		
		if(logger.isDebugEnabled()) {
			logger.debug("Add200ESRCorrelationBatchProcess: Processing of current batch complete.");
			logger.debug("Add200ESRCorrelationBatchProcess: Successful records count = "+context.getProcessStatistics().getNumberOfSuccessfulRecords());
			logger.debug("Add200ESRCorrelationBatchProcess: Failure records count ="+context.getProcessStatistics().getNumberOfErrorRecords());
		}
	}

	// override super to use the execute SQL with prepared statement in Ge
	protected List doAcquireData(DataQueryProcessExecutionContext context) throws Exception {
		return getDao().executeSQLQuery(sql_getEnrollmentWithout200ESR, "ALTER SESSION FORCE PARALLEL QUERY");
	}
	

	public PersonService getPersonService() {
		return personService;
	}

	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}

}
