/********************************************************************
 * Copyright © 2005 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.model.financials.Asset;
import gov.va.med.esr.common.model.financials.Expense;
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.AssetType;
import gov.va.med.esr.common.model.lookup.ExpenseType;
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;

/**
 * @author Muddaiah Ranga
 * @version 1.0
 */

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

    /**
     * Tests that Veteran 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(2000,11,30));
        dependent.setStartDate(ImpreciseDateUtils.createImpreciseDate(1999,11,30));

        FinancialStatement stmt = createFinancialStatement();
        
        // Add Income amounts
        IncomeType type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_CIVIL_SERVICE.getName());
        stmt.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME.getName());
        stmt.setIncome(type,new Income(new BigDecimal(99999991.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_OTHER_RETIREMENT.getName());
        stmt.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_MILITARY_RETIREMENT.getName());
        stmt.setIncome(type,new Income(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getIncomeTypeByCode(IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME.getName());
        stmt.setIncome(type,new Income(new BigDecimal(1000.00d)));
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateVeteranFinancials(incomeYear,incoming,onFile,(Person)onFile.clone(),false,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.VETERAN_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 );
        }
    }
    
    /**
     * Tests that Veteran Expense Amounts in Range.
     */
    public void testExpenseAmountsInRange() 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));

        FinancialStatement stmt = createFinancialStatement();
        
        // Add Expense amounts
        ExpenseType type =  this.getLookupService().getExpenseTypeByCode(ExpenseType.EXPENSE_TYPE_EDUCATIONAL_EXPENSES_BY_DEPENDENT.getName());
        stmt.setExpense(type,new Expense(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getExpenseTypeByCode(ExpenseType.EXPENSE_TYPE_FOOD.getName());
        stmt.setExpense(type,new Expense(new BigDecimal(99999991.00d)));
        
        type =  this.getLookupService().getExpenseTypeByCode(ExpenseType.EXPENSE_TYPE_FUNERAL_AND_BURIAL.getName());
        stmt.setExpense(type,new Expense(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getExpenseTypeByCode(ExpenseType.EXPENSE_TYPE_OTHER_EXPENSES.getName());
        stmt.setExpense(type,new Expense(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getExpenseTypeByCode(ExpenseType.EXPENSE_TYPE_NON_MEDICAL_INSURANCE.getName());
        stmt.setExpense(type,new Expense(new BigDecimal(1000.00d)));
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateVeteranFinancials(incomeYear,incoming,onFile,(Person)onFile.clone(),false,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.VETERAN_EXPENSE_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 );
        }
    }
    
    /**
     * Tests that Veteran Asset Amounts in Range.
     */
    public void testAssetAmountsInRange() 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));

        FinancialStatement stmt = createFinancialStatement();
        
        // Add Asset amounts
        AssetType type =  this.getLookupService().getAssetTypeByCode(AssetType.CODE_CASH.getName());
        stmt.setAsset(type,new Asset(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getAssetTypeByCode(AssetType.CODE_REAL_ESTATE.getName());
        stmt.setAsset(type,new Asset(new BigDecimal(99999991.00d)));
        
        type =  this.getLookupService().getAssetTypeByCode(AssetType.CODE_STOCKS_AND_BONDS.getName());
        stmt.setAsset(type,new Asset(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getAssetTypeByCode(AssetType.CODE_OTHER.getName());
        stmt.setAsset(type,new Asset(new BigDecimal(1000.00d)));
        
        type =  this.getLookupService().getAssetTypeByCode(AssetType.CODE_NON_LIQUID_ASSET.getName());
        stmt.setAsset(type,new Asset(new BigDecimal(1000.00d)));
      
        incoming.setFinancialStatement(incomeYear,stmt);

        try
        {
            ValidationMessages messages = this.getRuleValidationService().validateVeteranFinancials(incomeYear,incoming,onFile,(Person)onFile.clone(),false,true);
            assertNotNull(messages);

            assertTrue(!messages.isEmpty());
            assertTrue((messages.getCount() == 1));
			
            ValidationFieldMessage firstMessage = (ValidationFieldMessage)messages.get().next(); 
			
            assertEquals(firstMessage.getKey(),RuleValidationMessage.VETERAN_ASSET_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;
    }
}
