

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


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

import gov.va.med.cds.integration.AbstractEndToEndInvalidSitesTest;
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 gov.va.med.cds.uniqueidentifier.UniqueIdentifier;

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.Test;
import org.junit.runner.RunWith;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;

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


@RunWith( SuiteAwareSpringRunner.class )
//@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
public class InvalidVistaSitesEndToEndReadTest
    extends
        AbstractEndToEndInvalidSitesTest
{
    protected static String XPATH_DOMAINENTRYPOINT = "HealthConcern";
    protected TemplateRequestProcessor requestProcessor;
    private static final String QUERY_NAME = "ID_1";

    private static String FILTER_ID = TemplateIdHelper.PROBLEMLIST_SINGLE_PATIENT_FILTER;
    private static String TEMPLATE_ID = TemplateIdHelper.PROBLEM_LIST_TEMPLATE_ID;
    private static String XPATH_ERRORSECTION_FATAL_ERROR = "/clinicaldata:ClinicalData/errorSection/fatalErrors/fatalError";
    private static String XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE = "/clinicaldata:ClinicalData/errorSection/fatalErrors/fatalError/errorCode";
    private static String ALL_ASSIGNING_FACILITIES_INVALID_IN_FILTER_XML_REQUEST = "ALL_ASSIGNING_FACILITIES_INVALID_IN_FILTER_XML_REQUEST";
    private static String XPATH_ERRORSECTION_WARNING = "/clinicaldata:ClinicalData/errorSection/warnings/warning";


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


    @Test
    @Suite( groups = { "checkintest" } )
    public void testInvalidAssigningFacilityInFilter( )
        throws Exception
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                                        getResolvedPatientOneAssigningFacility(), null, null, null,
                                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );

        List<Node> fatalNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATAL_ERROR );
        Assert.assertTrue( fatalNodes.size() == 1 );
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 0 );

        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE );

        Assert.assertTrue( errorCodeNode.getText().contains( ALL_ASSIGNING_FACILITIES_INVALID_IN_FILTER_XML_REQUEST ) );

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testAllInvalidAssigningFacilitiesInFilter( )
        throws Exception
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientAllInvalidAssigningFacilities(), null, null, null,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );
        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE );
        Assert.assertTrue( errorCodeNode.getText().contains( ALL_ASSIGNING_FACILITIES_INVALID_IN_FILTER_XML_REQUEST ) );
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testOneInvalidAssigningFacilityInFilter( )
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientOneInvalidAssigningFacilities(), null, null, null,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 1 );
        List<Node> fatalNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATAL_ERROR );
        Assert.assertTrue( fatalNodes.size() == 0 );
        String responseXml = clinicalDataDocument.asXML();

        Assert.assertTrue( responseXml.contains( "<errorCode>INVALID_ASSIGNING_FACILITIES_IN_FILTER_XML_REQUEST" ) );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testEmptyAssigningFacilityInFilter( )
        throws Exception
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientEmptyAssigningFacility(), null, null, null,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );
       
        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );
        String responseXml = clinicalDataDocument.asXML();
       
        Assert.assertTrue( responseXml.contains( "<errorCode>PATIENT_ID_MISSING_ASSIGNING_FACILITY" ) );
       
    }

    @Test
    @Suite( groups = { "checkintest" } )
    public void testAllEmptyInFilter( )
        throws Exception
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientEmptyAssigningFacility(), null, null, null,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );
        
        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );
        String responseXml = clinicalDataDocument.asXML();
       
        Assert.assertTrue( responseXml.contains( "<errorCode>PATIENT_ID_MISSING_ASSIGNING_FACILITY" ) );
        
    }
    
    @Test
    @Suite( groups = { "checkintest" } )
    public void testOneEmptyAssigningFacilityInFilter( )
        throws Exception
    {
        String filterXml = FilterBuilder.buildProblemListFilterElementWithResolvedIdentfiers( FILTER_ID, getEntryPointFilterMaps(),
                        getResolvedPatientOneEmptyAssigningFacilities(), null, null, null,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        Document clinicalDataDocument = requestProcessor.readClinicalData( TEMPLATE_ID, filterXml, FILTER_ID, new UniqueIdentifier().toString() );
        String responseXml = clinicalDataDocument.asXML();

        Assert.assertTrue( responseXml.contains( "<errorCode>PATIENT_ID_MISSING_ASSIGNING_FACILITY" ) );
    }


    private List<Map<String, String>> getResolvedPatientOneAssigningFacility( )
    {
        String[] vistaPatient800 = { "USVHA", "800", "55512122" };
        String[][] patientIdentifiers = { vistaPatient800 };

        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getResolvedPatientEmptyAssigningFacility( )
    {
        String[] hdrPatientNoAF = { "USVHA", "", "test_sourceid_1000000" };
        String[][] patientIdentifiers = {hdrPatientNoAF};
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }

    private List<Map<String, String>> getEmptyResolvedPatient( )
    {
        String[][] patientIdentifiers = {};
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }
    
    private List<Map<String, String>> getResolvedPatientOneInvalidAssigningFacilities( )
    {
        String[] vistaPatient800 = { "USVHA", "800", "5551212" };
        String[] vistaPatient580 = { "USVHA", "580", "260" };
        String[] vistaPatient200 = { "USVHA", "200", "2601" };

        String[][] patientIdentifiers = { vistaPatient800, vistaPatient580, vistaPatient200 };

        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getResolvedPatientOneEmptyAssigningFacilities( )
    {
        String[] vistaPatient800 = { "USVHA", "800", "5551212" };
        String[] vistaPatient900 = { "USVHA", "", "" };
        String[][] patientIdentifiers = { vistaPatient800, vistaPatient900 };

        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        return resolvedPatients;
    }


    private List<Map<String, String>> getResolvedPatientAllInvalidAssigningFacilities( )
    {
        String[] vistaPatient800 = { "USVHA", "800", "5551212" };
        String[] vistaPatient900 = { "USVHA", "900", "5551212" };
        String[][] patientIdentifiers = { vistaPatient800, vistaPatient900 };

        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, XPATH_DOMAINENTRYPOINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME );

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

        return entryPointFilterMaps;
    }


   // @Test
   // @Suite( groups = { "deprecatedtest" } )
    public void testInvalidValidNullAssigningFacilityInHAFilter( )
        throws Exception
    {
        
        String[] hdrPatient200DOD = { "USDOD", "200DOD", "test_sourceid_1000000" };
        String[] hdrPatient200 = { "USDOD", "200", "test_sourceid_1000000" };
        String[] hdrPatient200NVW = { "USDOD", "200NVW", "test_sourceid_1000000" };
        String[] hdrPatientInvalidAF = { "USDOD", "1", "test_sourceid_1000000" };
        String[] hdrPatientNoAF = { "USDOD", "", "test_sourceid_1000000" };
        
        //existing valid assigning facility
        String[][] patientIdentifiers = { hdrPatient200DOD };
        List<Map<String, String>> patients = getResolvedPatients( patientIdentifiers );

        Map<String, String> entryPointFilter = new HashMap<String, String>();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "SkillTracking" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );

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

        Map<String, String> optionalQueryParameters = new HashMap<String, String>();
        optionalQueryParameters.put( "skillType", "Stretching" );
        String filterXml = FilterBuilder.buildFilterWithEdiPi( TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, entryPointFilterMaps, patients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ), "filter:skillTrackingDomainEntryPointFilter", optionalQueryParameters );
        
        requestProcessor.setValidateReadResponseXML( true );
        String requestId = new UniqueIdentifier().toString();
        Document clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, requestId );
       
        assertNotNull( clinicalDataDocument );
        List<Element> errorSections = clinicalDataDocument.selectNodes( "/clinicaldata:ClinicalData/errorSection" );
        assertTrue( errorSections.size() == 0 );

        //new valid assigning facility
        String[][] patientIdentifiers1 = { hdrPatient200NVW };
        patients = getResolvedPatients( patientIdentifiers1 );

        entryPointFilter.clear();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "SkillTracking" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );
   
        entryPointFilterMaps.clear();
        entryPointFilterMaps.add( entryPointFilter );

        optionalQueryParameters.clear();
        optionalQueryParameters.put( "skillType", "Stretching" );
        filterXml = FilterBuilder.buildFilterWithEdiPi( TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, entryPointFilterMaps, patients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ), "filter:skillTrackingDomainEntryPointFilter", optionalQueryParameters );
        
        requestProcessor.setValidateReadResponseXML( true );
        requestId = new UniqueIdentifier().toString();
        clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, requestId );
      
        assertNotNull( clinicalDataDocument );
        errorSections = clinicalDataDocument.selectNodes( "/clinicaldata:ClinicalData/errorSection" );
        assertTrue( errorSections.size() == 0 );
        
        //invalid assignign facility
        String[][] patientIdentifiers2 = { hdrPatientInvalidAF };
        patients = getResolvedPatients( patientIdentifiers2 );

        entryPointFilter.clear();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "SkillTracking" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );
        entryPointFilter.put( FilterBuilder.START_DATE_KEY, "2012-06-29" );
        entryPointFilter.put( FilterBuilder.END_DATE_KEY, "2013-06-01" );

        entryPointFilterMaps.clear();
        entryPointFilterMaps.add( entryPointFilter );

        optionalQueryParameters.clear();
        optionalQueryParameters.put( "skillType", "Stretching" );
        filterXml = FilterBuilder.buildFilterWithEdiPi( TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, entryPointFilterMaps, patients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ), "filter:skillTrackingDomainEntryPointFilter", optionalQueryParameters );
        
        requestProcessor.setValidateReadResponseXML( true );
        requestId = new UniqueIdentifier().toString();
        clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, requestId );
      
        assertNotNull( clinicalDataDocument );
        List<Node> fatalNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATAL_ERROR );
        Assert.assertTrue( fatalNodes.size() == 1 );
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 0 );

        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE );

        Assert.assertTrue( errorCodeNode.getText().contains( ALL_ASSIGNING_FACILITIES_INVALID_IN_FILTER_XML_REQUEST ) );
        
        //No assigning facility
        String[][] patientIdentifiers3 = { hdrPatientNoAF };
        patients = getResolvedPatients( patientIdentifiers3 );

        entryPointFilter.clear();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "SkillTracking" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );
        entryPointFilter.put( FilterBuilder.START_DATE_KEY, "2012-06-29" );
        entryPointFilter.put( FilterBuilder.END_DATE_KEY, "2013-06-01" );

        entryPointFilterMaps.clear();
        entryPointFilterMaps.add( entryPointFilter );

        optionalQueryParameters.clear();
        optionalQueryParameters.put( "skillType", "Stretching" );
        filterXml = FilterBuilder.buildFilterWithEdiPi( TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, entryPointFilterMaps, patients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ), "filter:skillTrackingDomainEntryPointFilter", optionalQueryParameters );
        
        requestProcessor.setValidateReadResponseXML( true );
        requestId = new UniqueIdentifier().toString();
        clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, requestId );
       
        assertNotNull( clinicalDataDocument );
        fatalNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATAL_ERROR );
        Assert.assertTrue( fatalNodes.size() == 1 );
        warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 0 );

        errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE );

        Assert.assertTrue( errorCodeNode.getText().contains( "EDIPI_PATIENT_ID_MISSING_ASSIGNING_FACILITY" ) );
        
        //All empty
        String[][] patientIdentifiers4 = {};
        patients = getResolvedPatients( patientIdentifiers4 );

        entryPointFilter.clear();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "SkillTracking" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );
        entryPointFilter.put( FilterBuilder.START_DATE_KEY, "2012-06-29" );
        entryPointFilter.put( FilterBuilder.END_DATE_KEY, "2013-06-01" );

        entryPointFilterMaps.clear();
        entryPointFilterMaps.add( entryPointFilter );

        optionalQueryParameters.clear();
        optionalQueryParameters.put( "skillType", "Stretching" );
        filterXml = FilterBuilder.buildFilterWithEdiPi( TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, entryPointFilterMaps, patients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ), "filter:skillTrackingDomainEntryPointFilter", optionalQueryParameters );
        
        requestProcessor.setValidateReadResponseXML( true );
        requestId = new UniqueIdentifier().toString();
        clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, requestId );
       
        assertNotNull( clinicalDataDocument );
        fatalNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATAL_ERROR );
        Assert.assertTrue( fatalNodes.size() == 1 );
        warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 0 );

        errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATAL_ERROR_ERROR_CODE );
        Assert.assertTrue( errorCodeNode.getText().contains( "INVALID_FILTER_SCHEMA" ) );
        
    }
}
