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

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.comms.HandBookMailQueue;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKey;
import gov.va.med.esr.service.HandBookService;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.fw.batchprocess.AbstractDataFileSingleRowIncrementProcess;
import gov.va.med.fw.batchprocess.DataFileProcessExecutionContext;
import gov.va.med.fw.batchprocess.FailedRecordWriterProcessCompletedHandler;
import gov.va.med.fw.batchprocess.HealthBenefitsPlanProcessStatistics;
import gov.va.med.fw.batchprocess.ProcessStatistics;
import gov.va.med.fw.service.ServiceException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class HealthBenefitPlanImportProcess extends
		AbstractDataFileSingleRowIncrementProcess {

	private LookupService lookupService;

	private HandBookService handBookService;

	private PersonService personService;
	
	private int numVersionsToKeep = 3;

	private String pdfFilesLocation;
	
	private final String[] validProductIds = {"H400H", "H400B", "H400F"};
	
	
	public void processDataRecords(DataFileProcessExecutionContext context,
			List acquiredData) {
		for (int i = 0; acquiredData != null && i < acquiredData.size(); i++) {
			HealthBenefitPlanData healthBenefitPlanData = (HealthBenefitPlanData) acquiredData.get(i);
			String rawData = context.getCurrentRowRawData();
			try {
				List errors =  validateRequest(healthBenefitPlanData);
				if ( errors == null || errors.size() == 0  ) {
					saveHealthBenefitPlan(healthBenefitPlanData, context);
					HealthBenefitsPlanProcessStatistics stats = (HealthBenefitsPlanProcessStatistics)context.getProcessStatistics();
					stats.incrementNumberOfSuccessfulRecords();
					
				} else {
					//there are validation errors.
					context.getProcessStatistics().incrementNumberOfErrorRecords();
					context.getExceptionData().add(rawData + "^" + getErrorString(errors));
				}
				
				
				
			} catch (Exception e) {
				
				if (logger.isErrorEnabled())
					logger.error("Error processing data record: " + rawData, e);
				context.getProcessStatistics().incrementNumberOfErrorRecords();
				context.getExceptionData().add(rawData + "^" + e.getMessage());
				context.getFailedData().add(rawData);
			}
		}
		//write to the exception and failed file for each file increment.
		FailedRecordWriterProcessCompletedHandler dataFileCompletedHandler  = (FailedRecordWriterProcessCompletedHandler)getDataProcessCompletedHandler();
		dataFileCompletedHandler.writeExceptionData(context);
		dataFileCompletedHandler.writeFailedData(context);
	}
	
	/*
	 * Dummay implementation 
	 * (non-Javadoc)
	 * @see gov.va.med.fw.batchprocess.AbstractDataFileSingleRowIncrementProcess#processDataRecord(gov.va.med.fw.batchprocess.DataFileProcessExecutionContext, java.lang.Object)
	 */
	protected  boolean processDataRecord(
            DataFileProcessExecutionContext context, Object bean){
		return false;
	}
	
	private List validateRequest(HealthBenefitPlanData healthBenefitPlanData) throws ServiceException{
		ArrayList errors = new ArrayList();
		if ( healthBenefitPlanData.getProductID() == null || healthBenefitPlanData.getProductID().length() <= 0 ) {
			errors.add("Missing Required field: ProductId");
		} else {
			List list = Arrays.asList(validProductIds);
			if ( ! list.contains(healthBenefitPlanData.getProductID()) )
			{
				errors.add("Invalid ProductId: " + healthBenefitPlanData.getProductID());
			}
		}
		if ( healthBenefitPlanData.getHandbookRequestId() == null || healthBenefitPlanData.getHandbookRequestId().length() <= 0 ) {
			errors.add("Missing Required field: HandbookRequestId");
		}
		if ( healthBenefitPlanData.getReleaseControlNumber() == null || healthBenefitPlanData.getReleaseControlNumber().length() <= 0 ) {
			errors.add("Missing Required field: ReleaseControlId");
		}
		if ( healthBenefitPlanData.getIcn() == null || healthBenefitPlanData.getIcn().length() <= 0 ) {
			errors.add("Missing Required field: Unique Identifier for the Veteran");
		}
		if ( healthBenefitPlanData.getHealthBenefitCode() == null || healthBenefitPlanData.getHealthBenefitCode().length() <= 0 ) {
			errors.add("Missing Required field: Benefit Code");
		}
		if ( healthBenefitPlanData.getCategoryCode() == null || healthBenefitPlanData.getCategoryCode().length() <= 0 ) {
			errors.add("Missing Required field: Benefits Categoty Code");
		}
		if ( healthBenefitPlanData.getCoveragePlanCode() == null || healthBenefitPlanData.getCoveragePlanCode().length() <= 0 ) {
			errors.add("Missing Required field: Coverage Plan Code");
		}
		
		PersonIdEntityKey personId =null; 
		if ( healthBenefitPlanData.getIcn() != null ) {
			try{
			//check if the VPID is valid. 
				personId = personService.getPersonIdByVPID( CommonEntityKeyFactory.createVPIDEntityKey(healthBenefitPlanData.getVpid()));
			} catch ( ServiceException e) {
				//e.printStackTrace();
				throw e;
			}
			if ( personId == null ) {
				errors.add("Invalid ICN :" + healthBenefitPlanData.getIcn());
			}
			
			HandBookMailQueue mailQueue = handBookService.findHandBookByIdentifier(healthBenefitPlanData.getHandbookRequestId());

			if ( mailQueue == null ) {
				errors.add("Invalid HandBookRequestId :" + healthBenefitPlanData.getHandbookRequestId());
			} else {
				//check if the person id mataches 
				if (! personId.getKeyValue().equals(mailQueue.getPersonId())) {
					errors.add("Invalid ICN, ICN does not match the HandBookRequestId :" + healthBenefitPlanData.getIcn());
				}
				
				
				if (! mailQueue.getHandBookReleaseControl().getCode().equals(healthBenefitPlanData.getReleaseControlNumber())) {
					errors.add("Invalid Release Control ID, Does not match the request :" + healthBenefitPlanData.getReleaseControlNumber());
				}
			}
			
		}
		
		return errors;
	}

	/**
	 * 
	 * @param healthBenefitPlanData
	 * @throws ServiceException
	 */
	public void saveHealthBenefitPlan(
			HealthBenefitPlanData healthBenefitPlanData, DataFileProcessExecutionContext context)
			throws ServiceException {
		try
		{
			getHandBookService().processHealthBenefitsPlanRecord(healthBenefitPlanData, getPdfFilesLocation(), context);
		} catch (Exception e ) { 
			throw new RuntimeException(e);
		}
	}

	
	private String getErrorString(List errorsList) {
		StringBuffer errors = new StringBuffer();
		for ( int i=0; errorsList != null && i < errorsList.size(); i++) {
			if ( i > 0 ) {
				errors = errors.append(":");
			}
			errors.append(errorsList.get(i));
		}
		return errors.toString();
	}
	
	public HandBookService getHandBookService() {
		return handBookService;
	}

	public void setHandBookService(HandBookService handBookService) {
		this.handBookService = handBookService;
	}

	public LookupService getLookupService() {
		return lookupService;
	}

	public void setLookupService(LookupService lookupService) {
		this.lookupService = lookupService;
	}

	public int getNumVersionsToKeep() {
		return numVersionsToKeep;
	}

	public void setNumVersionsToKeep(int numVersionsToKeep) {
		this.numVersionsToKeep = numVersionsToKeep;
	}

	public String getPdfFilesLocation() {
		return pdfFilesLocation;
	}

	public void setPdfFilesLocation(String pdfFilesLocation) {
		this.pdfFilesLocation = pdfFilesLocation;
	}

	public PersonService getPersonService() {
		return personService;
	}

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

	protected ProcessStatistics createProcessStatistics() {
		return new HealthBenefitsPlanProcessStatistics();
	}
}
