

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.AbstractEndToEndTest;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.request.RequestProcessorInterface;
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.dom4j.Document;
import org.dom4j.Element;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

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

import javax.annotation.Resource;


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndReadPatientAlertListTest
    extends
        AbstractEndToEndTest
{
    private static final String XPATH_PATIENTALERT = "/patientalertdata:PatientAlertData/patients/patient/patientAlerts/patientAlert";
    private static final String XPATH_ERRORSECTION = "//errorSection";
    private static final String XPATH_ERRORSECTION_WARNING = "/patientalertdata:PatientAlertData/errorSection/warnings/warning";
    private static final String XPATH_ERRORSECTION_WARNING_ERRORCODE = "/patientalertdata:PatientAlertData/errorSection/warnings/warning/errorCode";
    @SuppressWarnings( "unused" )
    private static final String XPATH_ERRORSECTION_ERROR = "/patientalertdata:PatientAlertData/errorSection/errors/error";
    private static final String XPATH_ERRORSECTION_ERROR_ERRORCODE = "/patientalertdata:PatientAlertData/errorSection/errors/error/errorCode";
    private static final String XPATH_ERRORSECTION_FATALERROR = "/patientalertdata:PatientAlertData/errorSection/fatalErrors/fatalError";
    private static final String XPATH_ERRORSECTION_FATALERROR_ERRORCODE = "/patientalertdata:PatientAlertData/errorSection/fatalErrors/fatalError/errorCode";
    @SuppressWarnings( "unused" )
    private static final String XPATH_ERRORSECTION_WARNING_DISPLAYMSG = "/patientalertdata:PatientAlertData/errorSection/warnings/warning/displayMessage";
    private static final String XPATH_ERRORSECTION_FATALERROR_DISPLAYMSG = "/patientalertdata:PatientAlertData/errorSection/fatalErrors/fatalError/displayMessage";

    private static final String ASSIGNING_AUTHORITY_VISTA = "USVHA";
    private static final String ASSIGNING_FACILITY_VISTA_578 = "578";
    private static final String PATIENT_IDENTITY_VISTA = "3";
    private static final String ASSIGNING_FACILITY_VISTA_580 = "580";

    @Resource
    private RequestProcessorInterface rpcRequestProcessor = null;
    protected TemplateRequestProcessor templateRequestProcessor;


    @Before
    @Suite( groups = { "checkintest" } )
    public void beforeEndToEndReadVrmTestClassSetUp( )
        throws Exception
    {
        templateRequestProcessor = ( TemplateRequestProcessor )getRpcRequestProcessor();
    }


    protected RequestProcessorInterface getRpcRequestProcessor( )
    {
        return rpcRequestProcessor;
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientAlertListRead_SingleSite( )
    {
        String clientRequestInitiationTime = "2015-05-05T12:00:00Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient578 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_578, PATIENT_IDENTITY_VISTA };
        String[][] patientIdentifiers = { vistaPatient578 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapAppts = new HashMap<String, String>();
        entryPointFilterMapAppts.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientAlert" );
        entryPointFilterMapAppts.put( FilterBuilder.QUERY_NAME_KEY, "PatientAlert-Standard" );
        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMapAppts );

        // build filter
        String filterXml = FilterBuilder.buildAppointmentsFilterElementWithResolvedIdentfiers(
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, entryPointFilterMaps, resolvedPatients, null, null,
                        clientRequestInitiationTime ).asXML();

        Document dataDocument = readAndAssertDomainData( TemplateIdHelper.PATIENTALERTLISTREAD1,
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, requestId, filterXml, resolvedPatients );

        List<Element> elementList = dataDocument.selectNodes( XPATH_PATIENTALERT );
        assertTrue( elementList.size() == 69 );

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientAlertListRead_MultiSite( )
    {
        String clientRequestInitiationTime = "2015-05-05T12:00:00Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient578 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_578, PATIENT_IDENTITY_VISTA };
        String[] vistaPatient580 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_580, PATIENT_IDENTITY_VISTA };
        String[][] patientIdentifiers = { vistaPatient578, vistaPatient580 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapAppts = new HashMap<String, String>();
        entryPointFilterMapAppts.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientAlert" );
        entryPointFilterMapAppts.put( FilterBuilder.QUERY_NAME_KEY, "PatientAlert-Standard" );
        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMapAppts );

        // build filter
        String filterXml = FilterBuilder.buildAppointmentsFilterElementWithResolvedIdentfiers(
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, entryPointFilterMaps, resolvedPatients, null, null,
                        clientRequestInitiationTime ).asXML();

        Document dataDocument = readAndAssertDomainData( TemplateIdHelper.PATIENTALERTLISTREAD1,
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, requestId, filterXml, resolvedPatients );

        List<Element> elementList = dataDocument.selectNodes( XPATH_PATIENTALERT );
        assertTrue( elementList.size() == 138 );

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientAlertListRead_SingleSite_WithStartDate( )
    {
        String clientRequestInitiationTime = "2015-05-05T12:00:00Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient578 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_578, PATIENT_IDENTITY_VISTA };
        String[][] patientIdentifiers = { vistaPatient578 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapAppts = new HashMap<String, String>();
        entryPointFilterMapAppts.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientAlert" );
        entryPointFilterMapAppts.put( FilterBuilder.QUERY_NAME_KEY, "PatientAlert-Standard" );
        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMapAppts );

        // build filter
        String filterXml = FilterBuilder.buildAppointmentsFilterElementWithResolvedIdentfiers(
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, entryPointFilterMaps, resolvedPatients, "2000-01-01", null,
                        clientRequestInitiationTime ).asXML();

        Document dataDocument = readAndAssertDomainData( TemplateIdHelper.PATIENTALERTLISTREAD1,
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, requestId, filterXml, resolvedPatients );

        List<Element> elementList = dataDocument.selectNodes( XPATH_PATIENTALERT );
        assertTrue( elementList.size() == 69 );

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientAlertListRead_MultiSite_WithStartDate( )
    {
        String clientRequestInitiationTime = "2015-05-05T12:00:00Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient578 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_578, PATIENT_IDENTITY_VISTA };
        String[] vistaPatient580 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_580, PATIENT_IDENTITY_VISTA };
        String[][] patientIdentifiers = { vistaPatient578, vistaPatient580 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapAppts = new HashMap<String, String>();
        entryPointFilterMapAppts.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientAlert" );
        entryPointFilterMapAppts.put( FilterBuilder.QUERY_NAME_KEY, "PatientAlert-Standard" );
        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMapAppts );

        // build filter
        String filterXml = FilterBuilder.buildAppointmentsFilterElementWithResolvedIdentfiers(
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, entryPointFilterMaps, resolvedPatients, "2010-04-22", null,
                        clientRequestInitiationTime ).asXML();

        Document dataDocument = readAndAssertDomainData( TemplateIdHelper.PATIENTALERTLISTREAD1,
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_LIST_FILTER, requestId, filterXml, resolvedPatients );

        List<Element> elementList = dataDocument.selectNodes( XPATH_PATIENTALERT );
        assertTrue( elementList.size() == 66 );

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientAlertDetailRead_SingleSite( )
    {
        String clientRequestInitiationTime = "2015-05-05T12:00:00Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient578 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_578, PATIENT_IDENTITY_VISTA };
        String[][] patientIdentifiers = { vistaPatient578 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapAppts = new HashMap<String, String>();
        entryPointFilterMapAppts.put( FilterBuilder.START_DATE_KEY, "2000-01-01" );
        entryPointFilterMapAppts.put( FilterBuilder.RECORD_IDENTITY, "27890" );
        entryPointFilterMapAppts.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientAlert" );
        entryPointFilterMapAppts.put( FilterBuilder.QUERY_NAME_KEY, "PatientAlert-Standard" );

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

        // build filter

        // buildPatientAlertFilterElementWithRequestId( String filterId, List<Map<String, String>> entryPointFilterMaps,
        // List<Map<String, String>> resolvedPatients, String startDate, String endDate, String clientRequestInitiationTime,
        // String identity, String namespaceId, String universalId, String universalIdType )

        String filterXml = FilterBuilder.buildPatientAlertFilterElementWithRequestId( TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_DETAIL_FILTER,
                        entryPointFilterMaps, resolvedPatients, null, null, clientRequestInitiationTime, "27890", "2000-01-01", null, null ).asXML();

        Document dataDocument = readAndAssertDomainData( TemplateIdHelper.PATIENTALERTDETAILREAD1,
                        TemplateIdHelper.PATIENTALERT_SINGLE_PATIENT_DETAIL_FILTER, requestId, filterXml, resolvedPatients );

        List<Element> elementList = dataDocument.selectNodes( XPATH_PATIENTALERT );
        assertTrue( elementList.size() == 1 );

    }


    private Document readAndAssertDomainData( String demographicsReadTemplateId, String demographicsSinglePatientFilter, String requestId,
                    String filterXml, List<Map<String, String>> resolvedPatients )
    {
        templateRequestProcessor.setValidateReadResponseXML( true );
        Document dataDocument = templateRequestProcessor.readClinicalData( demographicsReadTemplateId, filterXml, demographicsSinglePatientFilter,
                        requestId );
        assertNotNull( dataDocument );

        return dataDocument;
    }

}
