

package gov.va.med.cds.integration.vhim400;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import gov.va.med.cds.integration.AbstractEndToEndTest;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.request.TemplateRequestProcessor;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndReadProblemListTest
    extends
        AbstractEndToEndTest
{
    private static final String PROBLEM_LIST_ENTRY_POINT = "HealthConcern";
    private static final String OPTION_PARAM_STATUS = "status";
    private static final String OPTION_PARAM_CONDITION = "condition";

    protected TemplateRequestProcessor templateRequestProcessor;

    private static final String XPATH_HEALTH_CONCERN = "//patients/patient/healthConcerns/healthConcern";
    private static final String PROBLEM_LIST__QUERY_NAME = "ID_1";

    private static final String FILTER_ID = TemplateIdHelper.PROBLEMLIST_SINGLE_PATIENT_FILTER;
    private static final String TEMPLATE_ID = TemplateIdHelper.PROBLEM_LIST_TEMPLATE_ID;
    private static final String REQUEST_ID = TemplateIdHelper.getUniqueIdentifier();


    @Before
    @Suite( groups = { "checkintest" } )
    public void beforeEndToEndReadHdrVistaTestClassSetUp( )
        throws Exception
    {
        templateRequestProcessor = ( TemplateRequestProcessor )getRequestProcessor();
        templateRequestProcessor.setValidateReadResponseXML( true );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testProblemListRead_OnlyPatient( )
        throws Exception
    {
        // Patient only Query
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, null, null, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 12, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testProblemListRead_PatientWithDates( )
        throws Exception
    {
        String startDate = "2004-01-01";
        String endDate = "2004-12-31";

        // Patient Query with Dates
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), startDate, endDate, null, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 10, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        // Patient Query with Dates (no End Date)
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), startDate, null, null, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 12, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        // Patient Query with Dates (no Start Date)
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, endDate, null, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 10, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testProblemListRead_PatientWithStatus( )
        throws Exception
    {

        Map<String, String> optionalParamsMap = new LinkedHashMap<String, String>();
        optionalParamsMap.clear();
        optionalParamsMap.put( OPTION_PARAM_STATUS, "A" );

        // Patient Query with Status (ACTIVE 'A')
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 6, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        optionalParamsMap.clear();
        optionalParamsMap.put( OPTION_PARAM_STATUS, "I" );

        // Patient Query with Status (INACTIVE 'I')
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientsForInactiveStatus_TwoSites(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 9, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        // Patient Query with Dates and Status (INACTIVE 'I')
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientsForInactiveStatus_TwoSites(), "2004-01-01", "2004-12-31", optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 6, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testProblemListRead_PatientWithCondition( )
        throws Exception
    {
        Map<String, String> optionalParamsMap = new LinkedHashMap<String, String>();
        optionalParamsMap.clear();
        optionalParamsMap.put( OPTION_PARAM_CONDITION, "H" );

        // Patient Query with Condition (HIDDEN 'H")
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 32, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        String startDate = "1997-01-01";
        String endDate = "1999-12-31";

        // Patient Query with Dates and Condition (HIDDEN 'H")
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), startDate, endDate, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 8, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testProblemListRead_PatientWithStatusAndCondition( )
        throws Exception
    {
        Map<String, String> optionalParamsMap = new LinkedHashMap<String, String>();
        optionalParamsMap.put( OPTION_PARAM_STATUS, "A" );
        optionalParamsMap.put( OPTION_PARAM_CONDITION, "H" );

        // Patient With Status and Condition
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 26, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        String startDate = "1997-01-01";
        String endDate = "1997-12-31";

        // Patient With Dates, Status and Condition
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), startDate, endDate, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 5, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        optionalParamsMap.clear();
        optionalParamsMap.put( OPTION_PARAM_CONDITION, "H" );
        optionalParamsMap.put( OPTION_PARAM_STATUS, "I" );

        // Patient With Condition and Status
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 6, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );

        startDate = "2005-01-01";
        endDate = "2005-12-31";

        // Patient With Dates, Condition and Status
        filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_TwoSites(), startDate, endDate, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 0, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    @Ignore
    @Test
    @Suite( groups = { "prototypetest" } )
    public void testProblemListRead_PatientWithStatus_SQA( )
        throws Exception
    {
        Map<String, String> optionalParamsMap = new LinkedHashMap<String, String>();
        optionalParamsMap.clear();
        optionalParamsMap.put( OPTION_PARAM_STATUS, "A" );

        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatients_OneSite_MARTSQA(), null, null, optionalParamsMap,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = templateRequestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, REQUEST_ID );

        assertEquals( 4, clinicalDataDocument.selectNodes( XPATH_HEALTH_CONCERN ).size() );
    }


    private List<Map<String, String>> getResolvedPatients_TwoSites( )
    {
        String[] vistaPatient578 = { "USVHA", "578", "362" }; //Chicago
        String[] vistaPatient580 = { "USVHA", "580", "260" }; //Houston
        String[][] patientIdentifiers = { vistaPatient578, vistaPatient580 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getResolvedPatientsForInactiveStatus_TwoSites( )
    {
        String[] vistaPatient578 = { "USVHA", "578", "362" }; //Chicago
        String[] vistaPatient580 = { "USVHA", "580", "229" }; //Houston
        String[][] patientIdentifiers = { vistaPatient578, vistaPatient580 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getResolvedPatients_OneSite_MARTSQA( )
    {
        String[] vistaPatient613 = { "USVHA", "613", "201990" };
        String[][] patientIdentifiers = { vistaPatient613 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getEntryPointFilterMaps( )
    {
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, PROBLEM_LIST_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, PROBLEM_LIST__QUERY_NAME );

        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMap );

        return entryPointFilterMaps;
    }
}
