package gov.va.med.esr.voa.validator;

import gov.va.med.esr.voa.common.ErrorCode;
import gov.va.med.esr.voa.webservice.AddressInfo;
import gov.va.med.esr.voa.webservice.InsuranceInfo;
import gov.va.med.esr.voa.webservice.ObjectFactory;

import org.springframework.validation.BindException;

public class InsuranceInfoValidatorTest extends VoaCommonTestCase {

	private InsuranceInfoValidator validator;

	private InsuranceInfo insuranceInfo;

	@Override
	public void onSetUpInTransaction() throws Exception {
		super.onSetUpInTransaction();
		validator = new InsuranceInfoValidator();
		validator.setLookupService(getLookupService());

		ObjectFactory factory = new ObjectFactory();
		insuranceInfo = factory.createInsuranceInfo();

		insuranceInfo.setCompanyName("company Name");
		insuranceInfo.setPolicyHolderName("policy holder name");
		insuranceInfo.setGroupName("group name");
		insuranceInfo.setGroupNumber("group number");
		insuranceInfo.setEnrolledInPartA(Boolean.TRUE);
		insuranceInfo.setPartAEffectiveDate("01/01/1970");
		insuranceInfo.setEnrolledInPartB(Boolean.TRUE);
		insuranceInfo.setPartBEffectiveDate("01/01/1970");
		insuranceInfo.setSubscriber("subscriber");
		insuranceInfo.setPolicyNumber("12345");
		insuranceInfo.setPolicyNumber("12345");
		insuranceInfo.setInsuranceMappingTypeName("PI");

		AddressInfo addressInfo = factory.createAddressInfo();
		insuranceInfo.setInsAddress(addressInfo);

		addressInfo.setLine1("line1");
		addressInfo.setLine2("line2");
		addressInfo.setLine3("line3");
		addressInfo.setCity("Dallas");
		addressInfo.setState("TX");
		addressInfo.setCountry("USA");
		addressInfo.setZipCode("75024");
	}

	@Override
	public void onTearDownInTransaction() {
		validator = null;
		insuranceInfo = null;
		super.onTearDownInTransaction();
	}

	public void testInsuranceInfo() throws Exception {
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertFalse(errors.hasErrors());
	}

	public void testEmptyCompayName() throws Exception {
		insuranceInfo.setCompanyName(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testEmptyPolicyHolder() throws Exception {
		insuranceInfo.setPolicyHolderName(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testEmptyPolicyNumber() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setPolicyNumber(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testEmptyEnrolledInPartA() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setEnrolledInPartA(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		boolean hasError0069 = contain(errors, ErrorCode.VOA_0069);
		boolean hasError0227 = contain(errors, ErrorCode.VOA_0227);
		
		assertTrue(hasError0227 && hasError0069);
		assertEquals(errors.getErrorCount(), 2);

		insuranceInfo.setEnrolledInPartA(Boolean.FALSE);
		errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		hasError0227 = contain(errors, ErrorCode.VOA_0227);
		
		assertTrue(hasError0227);
	}

	public void testEnrolledInPartA() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setPartAEffectiveDate(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);

		insuranceInfo.setPartAEffectiveDate("01/01/2022");
		errors = new BindException(insuranceInfo, "associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testEmptyEnrolledInPartB() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setEnrolledInPartB(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testEnrolledInPartB() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setPartBEffectiveDate(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testSubscriber() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setSubscriber(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testPolicyNumber() throws Exception {
		insuranceInfo.setInsuranceMappingTypeName("MDCR");
		insuranceInfo.setPolicyNumber(null);
		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testAddressLine() throws Exception {
		ObjectFactory factory = new ObjectFactory();
		AddressInfo addressInfo = factory.createAddressInfo();
		insuranceInfo.setInsAddress(addressInfo);

		addressInfo.setLine1("line1 - 12345678901234567890123456789012345");
		addressInfo.setLine2("line2");
		addressInfo.setLine3("line3");
		addressInfo.setCity("Dallas");
		addressInfo.setState("TX");
		addressInfo.setCountry("USA");
		addressInfo.setZipCode("75024");

		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testAddressCity() throws Exception {
		ObjectFactory factory = new ObjectFactory();
		AddressInfo addressInfo = factory.createAddressInfo();
		insuranceInfo.setInsAddress(addressInfo);

		addressInfo.setLine1("line1");
		addressInfo.setLine2("line2");
		addressInfo.setLine3("line3");
		addressInfo.setCity("Dallas - 12345678901234567890123456789012345");
		addressInfo.setState("TX");
		addressInfo.setCountry("USA");
		addressInfo.setZipCode("75024");

		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

	public void testAddressState() throws Exception {
		ObjectFactory factory = new ObjectFactory();
		AddressInfo addressInfo = factory.createAddressInfo();
		insuranceInfo.setInsAddress(addressInfo);

		addressInfo.setLine1("line1");
		addressInfo.setLine2("line2");
		addressInfo.setLine3("line3");
		addressInfo.setCity("Dallas");
		addressInfo.setState("TX - invalid");
		addressInfo.setCountry("USA");
		addressInfo.setZipCode("75024");

		BindException errors = new BindException(insuranceInfo,
				"associationInfo");
		validator.validate(insuranceInfo, errors);

		assertEquals(errors.getErrorCount(), 1);
	}

}
