

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


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

import gov.va.med.cds.clinicaldata.DomainEntryPoint;
import gov.va.med.cds.integration.AbstractEndToEndReadAllergiesTest;
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.AllergyAssessmentBuilder;
import gov.va.med.cds.testharness.vhim400.builders.AllergyAssessmentBuilderFactory;
import gov.va.med.cds.testharness.vhim400.builders.BaseDatatypesBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDataBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDomainBuilderFactoryInterface;
import gov.va.med.cds.uniqueidentifier.UniqueIdentifier;

import org.dom4j.Document;
import org.dom4j.Element;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

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


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndCreateAllergyAssessmentTest
    extends
        AbstractEndToEndReadAllergiesTest
{
    private static final String HDR_PATIENTIDENTITY = "testId2227";
    protected TemplateRequestProcessor requestProcessor;
    protected static final String REQUEST_ID_XPATH = "/clinicaldata:ClinicalData/requestId";
    protected static String DOMAINENTRYPOINT_XPATH = "//AllergyAssessment";
    protected static String HDR_ASSIGNING_FACILITY = "200CH";
    protected static String PATIENT_ID_XPATH = "//allergyAssessments/patient/identifier/identity";
    protected static String HDR_ASSIGNINGAUTHORITY = "USDOD";
    protected static String RECORD_IDENTIFIER_XPATH = "//recordIdentifier/identity";
    protected static final String ERROR_SECTION_ERRORS_XPATH = "//clinicaldata:ClinicalData/errorSection/errors";
    protected static final String ERROR_SECTION_WARNINGS_XPATH = "//clinicaldata:ClinicalData/errorSection/warnings";
    protected static final String ERROR_SECTION_FATAL_ERRORS_XPATH = "//clinicaldata:ClinicalData/errorSection/fatalErrors";
    protected String recordIdentifier = null;
    String createXmlRequestId = null;

    @Autowired
    protected JdbcTemplate hdrJdbcTemplate;


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


    @SuppressWarnings( "unused" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testAllergyAssessmentCreate( )
        throws Exception
    {

        Document createDoc = createWriteRequestXml();
        String createXml = createDoc.asXML();
        String recordIdentifierIdentity = createDoc.selectSingleNode( RECORD_IDENTIFIER_XPATH ).getText();
        String patientIdIdentifier = createDoc.selectSingleNode( PATIENT_ID_XPATH ).getText();
        createAndAssertDomainData( TemplateIdHelper.ALLERGY_ASSESSMENT_CREATEORUPDATE_TEMPLATE_ID, createXml );

        //Test reads with different filter template combinations
        readData( patientIdIdentifier, TemplateIdHelper.ALLERGY_ASSESSMENT_READ_TEMPLATE_ID, HDR_ASSIGNING_FACILITY, HDR_ASSIGNINGAUTHORITY,
                        TemplateIdHelper.AA_SINGLE_PATIENT_ALL_DATA_FILTER );
        readData( patientIdIdentifier, TemplateIdHelper.ALLERGIES_READ_TEMPLATE_ID, HDR_ASSIGNING_FACILITY, HDR_ASSIGNINGAUTHORITY,
                        TemplateIdHelper.ALLERGY_SINGLE_PATIENT_ALL_DATA_FILTER );
        readData( patientIdIdentifier, TemplateIdHelper.VW_ALLERGIES_READ_TEMPLATE_ID, HDR_ASSIGNING_FACILITY, HDR_ASSIGNINGAUTHORITY,
                        TemplateIdHelper.VW_ALLERGY_SINGLE_PATIENT_FILTER );

        doDelete();

    }


    @SuppressWarnings( "unchecked" )
    private void readData( String patientIdIdentifier, String templateId, String assigingFacility, String assigningAuthority, String filterId )
        throws Exception
    {

        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        assigningFacilityAndPatientIdentityMap.put( assigingFacility, patientIdIdentifier );

        Map<String, String> entryPointMap = new HashMap<String, String>();
        entryPointMap.put( "ID_2", "AllergyAssessment" );
        if ( filterId.contains( "ALLERGY_SINGLE" ) )
        {
            entryPointMap.put( "ID_1", "IntoleranceCondition" );
        }

        Map<String, String> xpathMap = new HashMap<String, String>();
        if ( filterId.equals( "VW_ALLERGY_SINGLE_PATIENT_FILTER" ) )
        {
            xpathMap.put( "ID_1", "intoleranceConditions[status != 'E']" );
            xpathMap.put( "ID_2", "allergyAssessments[status != 'E']" );
        }
        String filterXml = createAllergiesSinglePatientMulitEntryPointFilter( assigningFacilityAndPatientIdentityMap, entryPointMap, null, null,
                        assigningAuthority, filterId, xpathMap );

        Document clinicalDataDocument = readAndAssertDomainData( assigningFacilityAndPatientIdentityMap, templateId, filterXml, filterId,
                        getAllergyAssessmentsEntryPointXpath() );
        List<Element> resultsResolvedIdentifiersList = clinicalDataDocument.selectNodes( XPATH_IDENTIFIERS );
        assertNotNull( resultsResolvedIdentifiersList );

    }


    @SuppressWarnings( "unchecked" )
    protected Document readAndAssertDomainData( Map<String, String> assigningFacilityAndPatientIdentityMap, String templateId, String filter,
                    String filterId, String entryPointXpath )
        throws Exception
    {
        requestProcessor.setValidateReadResponseXML( true );

        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( entryPointXpath );
        if ( templateId.equals( TemplateIdHelper.ALLERGY_ASSESSMENT_READ_TEMPLATE_ID ) )
        {
            assertTrue( domainElements.size() > 0 );
        }
        else
        {
            assertTrue( domainElements.size() == 0 );
        }

        return clinicalDataDocument;
    }


    private void doDelete( )
    {
        hdrJdbcTemplate.update( "DELETE FROM ALLERGY_ASSESSMENT30_V where patient_identity = '" + HDR_PATIENTIDENTITY + "'" );
    }


    private Document createWriteRequestXml( )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( TemplateIdHelper.ALLERGY_ASSESSMENT_CREATEORUPDATE_TEMPLATE_ID, DomainEntryPoint.AllergyAssessment );

        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        AllergyAssessmentBuilderFactory factory = new AllergyAssessmentBuilderFactory();
        factory.setAllergyAssessmentBuilder( new AllergyAssessmentBuilder() );
        domainEntryPointsWrappersMap.put( "AllergyAssessment", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "patient", HDR_PATIENTIDENTITY, HDR_ASSIGNING_FACILITY,
                        HDR_ASSIGNINGAUTHORITY );

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( TemplateIdHelper.ALLERGY_ASSESSMENT_CREATEORUPDATE_TEMPLATE_ID, 1,
                        patient );

        return vdmClinicalDataInsert;
    }


    @SuppressWarnings( "unchecked" )
    protected Document createAndAssertDomainData( String templateId, String createRequestXml )
        throws Exception
    {
        requestProcessor.setValidateReadResponseXML( true );
        createXmlRequestId = new UniqueIdentifier().toString();
        Document clinicalDataDocument = requestProcessor.createClinicalData( createRequestXml, templateId, createXmlRequestId );
        assertNotNull( clinicalDataDocument );

        // Check for an empty error section
        List<Element> errorSections = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION );
        assertTrue( errorSections.size() == 1 );
        Element errorSection = errorSections.get( 0 );
        assertTrue( errorSection.content().size() == 0 );

        String requestIdFromResponse = clinicalDataDocument.selectSingleNode( REQUEST_ID_XPATH ).getText();
        assertTrue( createXmlRequestId.equals( requestIdFromResponse ) );

        List<Element> errors = clinicalDataDocument.selectNodes( ERROR_SECTION_ERRORS_XPATH );
        assertTrue( errors.size() == 0 );

        List<Element> warnings = clinicalDataDocument.selectNodes( ERROR_SECTION_WARNINGS_XPATH );
        assertTrue( warnings.size() == 0 );

        List<Element> fatalErrors = clinicalDataDocument.selectNodes( ERROR_SECTION_FATAL_ERRORS_XPATH );
        assertTrue( fatalErrors.size() == 0 );

        return clinicalDataDocument;
    }

}