/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.rule.service;

// Java classes
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.financials.DependentFinancials;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.Income;
import gov.va.med.esr.common.model.lookup.IncomeType;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.person.Dependent;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.rule.service.impl.RuleValidationMessage;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;

import java.math.BigDecimal;
import java.util.Calendar;

/**
 * @author Van Sioung Ng 
 * @version 1.0
 */

public class DependentValidationTest extends RuleAbstractTestCase
{
    public DependentValidationTest(String testName) throws Exception 
    {
        super(testName);
    }

    public void testSameSSNAsVeteran() throws Exception 
    {
        Integer incomeYear = new Integer(2004);
        
        Person incoming = getPerson();
        Person onFile = (Person)incoming.clone();
        
        Dependent dependent = new Dependent();
        dependent.setName(createName());
        dependent.setRelationship(getRandomRelationship());
        dependent.addSsn(incoming.getOfficialSsn());
        dependent.setDob(ImpreciseDateUtils.createImpreciseDate(2000,11,30));
        dependent.setStartDate(ImpreciseDateUtils.createImpreciseDate(2005,9,29));
        DependentFinancials dependentFinancials = createDependentFinancials(dependent);
        
        FinancialStatement stmt = createFinancialStatement();
        stmt.addDependentFinancials(dependentFinancials);
        
        incoming.setFinancialStatement(incomeYear,stmt);
        
        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateDependentFinancials(incomeYear,dependentFinancials,incoming,onFile,true,true);
            assertNotNull(messages);

			assertTrue(!messages.isEmpty());
			assertTrue((messages.getCount() == 1));
			
			ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
			assertEquals(firstMessage.getKey(),RuleValidationMessage.INVALID_DEPEDENT_SSN_SAME_AS_VETERAN.getName() );
        }
        catch( Exception e )
        {
            logger.debug( "Got an un-expected validation exception ", e );
            this.fail( "Got an un-expected validation exception", e );
        }
    }
    
    /**
     * Tests that effective date is provided.
     */
    public void testHasNoEffectiveDate() throws Exception 
    {
        Integer incomeYear = new Integer(2004);
        
        Person incoming = getPerson();
        Person onFile = (Person)incoming.clone();
      
        Dependent dependent = new Dependent();
        dependent.setName(createName());
        dependent.setRelationship(getRandomRelationship());
      
        SSN dependentSSN = (SSN)incoming.getOfficialSsn().clone();
        dependentSSN.setSsnText("111-22-3333");
        dependent.addSsn(dependentSSN);
      
        dependent.setDob(ImpreciseDateUtils.createImpreciseDate(2000,11,30));
      
        //dependent.setStartDate(ImpreciseDateUtils.createImpreciseDate(2005,9,29));
      
        DependentFinancials dependentFinancials = createDependentFinancials(dependent);
      
        FinancialStatement stmt = createFinancialStatement();
        stmt.addDependentFinancials(dependentFinancials);
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateDependentFinancials(incomeYear,dependentFinancials,incoming,onFile,true,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.EFFECTIVE_DATE_REQUIRED.getName() );
        }
        catch( Exception e )
        {
            logger.debug( "Got an un-expected validation exception ", e );
            this.fail( "Got an un-expected validation exception", e );
        }
    }
    
    /**
     * Tests that effective date is in future.
     */
    public void testHasEffectiveDateIsFuture() throws Exception 
    {
        Integer incomeYear = new Integer(2004);
        
        Person incoming = getPerson();
        Person onFile = (Person)incoming.clone();
      
        Dependent dependent = new Dependent();
        dependent.setName(createName());
        dependent.setRelationship(getRandomRelationship());
      
        SSN dependentSSN = (SSN)incoming.getOfficialSsn().clone();
        dependentSSN.setSsnText("111-22-3333");
        dependent.addSsn(dependentSSN);
      
        dependent.setDob(ImpreciseDateUtils.createImpreciseDate(2000,11,30));
      
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH,1);
        
        dependent.setStartDate(new ImpreciseDate(cal));
      
        DependentFinancials dependentFinancials = createDependentFinancials(dependent);
      
        FinancialStatement stmt = createFinancialStatement();
        stmt.addDependentFinancials(dependentFinancials);
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateDependentFinancials(incomeYear,dependentFinancials,incoming,onFile,true,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.INVALID_FUTURE_EFFECTIVE_DATE.getName() );
        }
        catch( Exception e )
        {
            logger.debug( "Got an un-expected validation exception ", e );
            this.fail( "Got an un-expected validation exception", e );
        }
    }
    
    /**
     * Tests that DOB after effective date.
     */
    public void testDOBAfterEffectiveDate() throws Exception 
    {
        Integer incomeYear = new Integer(2004);
        
        Person incoming = getPerson();
        Person onFile = (Person)incoming.clone();
      
        Dependent dependent = new Dependent();
        dependent.setName(createName());
        dependent.setRelationship(getRandomRelationship());
      
        SSN dependentSSN = (SSN)incoming.getOfficialSsn().clone();
        dependentSSN.setSsnText("111-22-3333");
        dependent.addSsn(dependentSSN);
      
        dependent.setDob(ImpreciseDateUtils.createImpreciseDate(2000,11,30));
        dependent.setStartDate(ImpreciseDateUtils.createImpreciseDate(1999,11,30));
      
        DependentFinancials dependentFinancials = createDependentFinancials(dependent);
      
        FinancialStatement stmt = createFinancialStatement();
        stmt.addDependentFinancials(dependentFinancials);
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateDependentFinancials(incomeYear,dependentFinancials,incoming,onFile,true,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 2));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.INVALID_DEPENDENT_DOB_AFTER_EFFECTIVE_DATE.getName() );
        }
        catch( Exception e )
        {
            logger.debug( "Got an un-expected validation exception ", e );
            this.fail( "Got an un-expected validation exception", e );
        }
    }
    
    /**
     * Tests that Income Amounts in Range.
     */
    public void testIncomeAmountsInRange() throws Exception 
    {
        Integer incomeYear = new Integer(2004);
        
        Person incoming = getPerson();
        Person onFile = (Person)incoming.clone();
      
        Dependent dependent = new Dependent();
        dependent.setName(createName());
        dependent.setRelationship(getRandomRelationship());
      
        SSN dependentSSN = (SSN)incoming.getOfficialSsn().clone();
        dependentSSN.setSsnText("111-22-3333");
        dependent.addSsn(dependentSSN);
      
        dependent.setDob(ImpreciseDateUtils.createImpreciseDate(1999,11,30));
        dependent.setStartDate(ImpreciseDateUtils.createImpreciseDate(2004,11,30));
      
        DependentFinancials dependentFinancials = createDependentFinancials(dependent);
        
        // Add Income amounts
        IncomeType type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_CIVIL_SERVICE.getName());
        dependentFinancials.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME.getName());
        dependentFinancials.setIncome(type,new Income(new BigDecimal(99999991.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_OTHER_RETIREMENT.getName());
        dependentFinancials.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_MILITARY_RETIREMENT.getName());
        dependentFinancials.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME.getName());
        dependentFinancials.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
      
        FinancialStatement stmt = createFinancialStatement();
        stmt.addDependentFinancials(dependentFinancials);
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateDependentFinancials(incomeYear,dependentFinancials,incoming,onFile,false,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.DEPENDENT_INCOME_NOT_IN_RANGE.getName() );
        }
        catch( Exception e )
        {
            logger.debug( "Got an un-expected validation exception ", e );
            this.fail( "Got an un-expected validation exception", e );
        }
    }
    
    private Person getPerson() throws Exception
    {
        Person person = this.buildPerson();
        SSN ssn = person.getOfficialSsn();
        if(ssn == null)
        {
            ssn = createSSN("123-12-1234");
            SSNType officalType = (SSNType)this.getLookupService().getByCode(SSNType.class,SSNType.CODE_ACTIVE.getName());
            ssn.setType(officalType);
            person.addSsn(ssn);
        }
        else
        {
            ssn.setSsnText("123-12-1234");    
        }
        return person;
    }
}
