

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.TemplateRequestProcessor;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;
import gov.va.med.cds.testharness.xml.XmlValidator;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
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 org.springframework.test.context.ContextConfiguration;

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


@RunWith( SuiteAwareSpringRunner.class )
@ContextConfiguration( locations = { "classpath:gov/va/med/cds/config/hdr2FailingDataSourceContext.xml" } )
public class HdrFailingReadAllergiesTest
    extends
        AbstractEndToEndTest
{
    private static final String PATIENT_IDENTITY_HDR = "test_sourceid_10000";
    private static final String ASSIGNING_FACILITY_HDR = "200CH";
    private static final String ASSIGNING_AUTHORITY_HDR = "USDOD";

    private static final String XPATH_PATIENT_IC = "//patient/intoleranceConditions";
    private static final String READ_REQUEST_DATA_SOURCE_FAILURE = "READ_REQUEST_DATA_SOURCE_FAILURE";

    private static final String INTOLERANCECONDITION_DOMAIN_ENTRYPOINT = "IntoleranceCondition";

    private static final String INTOLERANCECONDITION_QUERY_NAME = "ID_IC";

    protected TemplateRequestProcessor templateRequestProcessor;


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


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testHdrIntoleranceConditionRead( )
        throws Exception
    {
        //return only intolerance condition data for a known HDR patient - using resolved identifiers
        String templateIds[] = { TemplateIdHelper.INTOLERANCE_CONDITION_READ_TEMPLATE_ID };
        for ( int ii = 0; ii < templateIds.length; ii++ )
        {
            String readTemplateId = templateIds[ii];
            String filterId = TemplateIdHelper.IC_SINGLE_PATIENT_ALL_DATA_FILTER;
            String requestId = TemplateIdHelper.getUniqueIdentifier();

            String[] hdrPatient = { ASSIGNING_AUTHORITY_HDR, ASSIGNING_FACILITY_HDR, PATIENT_IDENTITY_HDR };
            //String[] vistaPatient580 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA, PATIENT_IDENTITY_VISTA };
            String[][] patientIdentifiers = { hdrPatient };
            List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

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

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

            Document clinicalDataDocument = readAndAssertDomainData( readTemplateId, filterId, requestId, entryPointFilterMaps, resolvedPatients );

            assertNotNull( clinicalDataDocument );
            detachExcludeIdentifierNodes( clinicalDataDocument );
            String clinicalDataXml = clinicalDataDocument.asXML();
            XmlValidator.validateXml( clinicalDataXml, readTemplateId );

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

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

            // Check for error sections
            Node warningCode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_WARNINGERRORCODE );
            assertTrue( warningCode.getText().contains( READ_REQUEST_DATA_SOURCE_FAILURE ) );
        }
    }


    protected Document readAndAssertDomainData( String templateId, String filterId, String requestId, List<Map<String, String>> entryPointFilterMaps,
                    List<Map<String, String>> resolvedPatients )
        throws Exception
    {
        String filterXml = FilterBuilder.buildFilterWithResolvedIdentfiers( filterId, entryPointFilterMaps, resolvedPatients,
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        templateRequestProcessor.setValidateReadResponseXML( false );

        return templateRequestProcessor.readClinicalData( templateId, filterXml, filterId, requestId );
    }


    private void detachExcludeIdentifierNodes( Document clinicalDataDocument )
    {
        while ( clinicalDataDocument.getRootElement().element( "patient" ).asXML().contains( "requestedExcludedIdentifiers" ) )
        {
            clinicalDataDocument.getRootElement().element( "patient" ).element( "requestedExcludedIdentifiers" ).detach();
        }
    }
}
