

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


import static org.junit.Assert.assertEquals;
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.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.dom4j.XPath;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

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


public class EndToEndReadNonVaMedsHdrTest
    extends
        AbstractEndToEndTest
{
    protected static String ASSIGNINGAUTHORITY = "USVHA";
    //protected static String ASSIGNINGAUTHORITY_DOD = "USDOD";
    //protected static String RECORDIDENTIFIER1 = "6";
    protected static String NAMESPACEID1 = "580_8925";
    protected static String XPATH_DOMAINENTRYPOINT = "//nonVaMedicationEvents";
    protected static String DOMAIN_ENTRY_POINT = "NonVaMedicationEvent";
    private static String STATUS_ACTIVE = "ACTIVE"; // null or no value
    private static String STATUS_DISCONTINUED = "DISCONTINUED"; // VistA value of 1 = discontinued,  or 2 = expired
    private static String QUERY_NAME_BASE = "NonVAMedicationsRead3.NonVAMedication.patient";
    private static String PATIENTIDENTITY1 = "999999999"; // ACTIVE patient
    private static String ASSIGNINGFACILITY1 = "200DOD";
    private static String PATIENTIDENTITY2 = "777777777";
    //private static String PATIENTIDENTITY3 = "69"; // DISCONTINUED patient where status = 1
   // private static String ASSIGNINGFACILITY2 = "578";
    private static String XPATH_NONVAMEDICATIONEVENTS = "//patient/nonVaMedicationEvents/nonVaMedicationEvent";
    private static String XPATH_STATUS_DISCONTINUED = "//patient/nonVaMedicationEvents/nonVaMedicationEvent/status/code";
    //private static String XPATH_DETECTEDISSUEEVENTS = "//patient/nonVaMedicationEvents/nonVaMedicationEvent/detectedIssueEvents/detectedIssueEvent";

    @Autowired
    private TemplateRequestProcessor requestProcessor;


    @Test
    @Suite( groups = { "smoketest" } )
    public void testNonVaReadWithNoStatus_SingleSite( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, null );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );
        //expecting 1
        assertEquals( 1, clinicalDataDocument.selectNodes( XPATH_NONVAMEDICATIONEVENTS ).size() );
        System.out.println(clinicalDataDocument.asXML());
    }


    @Test
    @Suite( groups = { "smoketest" } )
    public void testNonVaReadWithActiveStatus_SingleSite( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, STATUS_ACTIVE );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );

        //expecting 1
        assertEquals( 1, clinicalDataDocument.selectNodes( XPATH_NONVAMEDICATIONEVENTS ).size() );
        System.out.println(clinicalDataDocument.asXML());
    }


   // @Test
    //@Suite( groups = { "brokentest" } )
    /*
     * marked 'broken' as there is a data discrepancy in Vista
     */
   /* public void testNonVaReadWithDiscontinuedStatus_2_SingleSite( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        //resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY2 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, STATUS_DISCONTINUED );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );

        //expecting 1
        assertEquals( 1, clinicalDataDocument.selectNodes( XPATH_NONVAMEDICATIONEVENTS ).size() );

        // Status contains Date of Death Entered
        assertTrue( ( ( ( Element )clinicalDataDocument.selectSingleNode( XPATH_STATUS_DISCONTINUED ) ).getText() ).equals( "2" ) );
    }
*/

    //@Test
    //@Suite( groups = { "brokentest" } )
    /*
     * marked 'broken' as there is a data discrepancy in Vista
     */
    /*public void testNonVaReadWithDiscontinuedStatus_1_SingleSite( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        //resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY3 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, STATUS_DISCONTINUED );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );

        //expecting 1
        assertEquals( 1, clinicalDataDocument.selectNodes( XPATH_NONVAMEDICATIONEVENTS ).size() );

        // Status contains Date of Death Entered
        assertTrue( ( ( ( Element )clinicalDataDocument.selectSingleNode( XPATH_STATUS_DISCONTINUED ) ).getText() ).equals( "1" ) );
    }
*/

   // @Test
   // @Suite( groups = { "checkintest" } )
    /*public void testNonVaReadWithNoStatus_MulitSite( )
        throws Exception
    {
        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        Map<String, String> resolvedPatient1 = new HashMap<String, String>();
        resolvedPatient1.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient1.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient1.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );
        resolvedPatientsList.add( resolvedPatient1 );

        Map<String, String> resolvedPatient2 = new HashMap<String, String>();
        resolvedPatient2.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        //resolvedPatient2.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY2 );
        //resolvedPatient2.put( FilterBuilder.IDENTITY, PATIENTIDENTITY2 );
        resolvedPatientsList.add( resolvedPatient2 );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, null );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );

        //expecting 2
        assertEquals( 2, clinicalDataDocument.selectNodes( XPATH_NONVAMEDICATIONEVENTS ).size() );
    }
*/

    //@Test
    //@Suite( groups = { "checkintest" } )
   /* public void testNonVaReadWithDetectedIssueEvents_SingleSite( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, null );
        Document clinicalDataDocument = readAndAssertDomainData( getNonVaMedsReadTemplateID(), filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER );
        //expecting 2
        //assertEquals( 2, clinicalDataDocument.selectNodes( XPATH_DETECTEDISSUEEVENTS ).size() );
    }*/


   /* @Test
    @Suite( groups = { "checkintest" } )
    public void testNonVaReadWithInvalidTemplateId( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, null );
        Document clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.IMMUNIZATIONS_READ3_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.NONVAMED_SINGLE_PATIENT_FILTER, new UniqueIdentifier().toString() );

        String readResult = clinicalDataDocument.asXML();

        assertTrue( readResult.contains( "<errorSection>" ) );

    }*/


   /* @Test
    @Suite( groups = { "checkintest" } )
    public void testNonVaReadWithInvalidFilterId( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNINGAUTHORITY );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNINGFACILITY1 );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY1 );

        List<Map<String, String>> resolvedPatientsList = new ArrayList<Map<String, String>>();
        resolvedPatientsList.add( resolvedPatient );

        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, DOMAIN_ENTRY_POINT );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, QUERY_NAME_BASE );

        // Non Va Meds read filter
        String filterXml = createNonVaMedsSinglePatientDataFilter( TemplateIdHelper.IMMUNIZATION_SINGLE_PATIENT_FILTER, entryPointFilterMap,
                        resolvedPatientsList, null );
        Document clinicalDataDocument = requestProcessor.readClinicalData( TemplateIdHelper.NONVA_MEDICATIONS_READ2_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.IMMUNIZATION_SINGLE_PATIENT_FILTER, new UniqueIdentifier().toString() );

        String readResult = clinicalDataDocument.asXML();

        assertTrue( readResult.contains( "<errorSection>" ) );
    }*/


    @SuppressWarnings( "unchecked" )
    private Document readAndAssertDomainData( String templateId, String filter, String filterId )
        throws Exception
    {
        requestProcessor.setValidateReadResponseXML( false );

        Document clinicalDataDocument = requestProcessor.readClinicalData( templateId, filter, filterId, new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        // Check for error sections
        List<Element> errorSections = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION );
        assertTrue( errorSections.size() == 0 );

        // Check for domain entry point elements
        List<Element> domainElements = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        assertTrue( domainElements.size() > 0 );

        return clinicalDataDocument;
    }


    private String getNonVaMedsReadTemplateID( )
    {
        //return TemplateIdHelper.NONVA_MEDICATIONS_READ3_TEMPLATE_ID;
    	return "NonVAMedicationsRead3";
    }


    private String createNonVaMedsSinglePatientDataFilter( String filterId, Map<String, String> entryPointFilter,
                    List<Map<String, String>> resolvedPatients, String statusValue )
    {
        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilter );

        return FilterBuilder.buildNonVaMedFilterWithResolvedIdentfiers( filterId, entryPointFilterMaps, resolvedPatients, statusValue,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );
    }
}
