

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.clinicaldata.DomainEntryPoint;
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.BaseDatatypesBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDataBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDomainBuilderFactoryInterface;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;
import gov.va.med.cds.testharness.vhim400.builders.NonVaMedBuilder;
import gov.va.med.cds.testharness.vhim400.builders.NonVaMedBuilderFactory;
import gov.va.med.cds.uniqueidentifier.UniqueIdentifier;

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

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndCreateNonVAMedsHdrTest
    extends
        AbstractEndToEndTest
{
    private static String READ_TEST_DOMAINENTRYPOINT_XPATH = "//nonVaMedicationEvents/nonVaMedicationEvent";
    private static String CLIENT_NAME = "PGD";

    private static final String PATIENTIDENTITY_HDR = "testId5555";
    private static final String ASSIGNING_FACILITY_HDR = "200CH";
    private static final String ASSIGNING_AUTHORITY_HDR = "USDOD";

    private static final String REQUEST_ID_XPATH = "/clinicaldata:ClinicalData/requestId";
    private static final String ERROR_SECTION_ERRORS_XPATH = "//clinicaldata:ClinicalData/errorSection/errors";
    private static final String ERROR_SECTION_WARNINGS_XPATH = "//clinicaldata:ClinicalData/errorSection/warnings";
    private static final String ERROR_SECTION_FATAL_ERRORS_XPATH = "//clinicaldata:ClinicalData/errorSection/fatalErrors";

    protected static String DOMAIN_ENTRY_POINT = "NonVaMedicationEvent";
    private static String QUERY_NAME_BASE = "NonVAMedicationsRead3.NonVAMedication.patient";

    @Autowired
    private JdbcTemplate hdrJdbcTemplate;

    @Autowired
    TemplateRequestProcessor requestProcessor;


    @Test
    @Suite( groups = { "brokentest" } )
    public void testNonVAMedCreate( )
        throws Exception
    {
        // Clean up any old test data
        doDelete( PATIENTIDENTITY_HDR );

        String requestId = new UniqueIdentifier().toString();
        Document createRequestDoc = createWriteRequestXml();
        String createRequestXml = createRequestDoc.asXML();

       // Document clinicalDataDocument = createAndAssertDomainData( TemplateIdHelper.NONVAMEDICATION_CREATE_TEMPLATE_ID, createRequestXml, requestId );
        Document clinicalDataDocument = createAndAssertDomainData( "", createRequestXml, requestId );
        assertNotNull( clinicalDataDocument );

        // Verify requestId
        String requestIdFromResponse = clinicalDataDocument.selectSingleNode( REQUEST_ID_XPATH ).getText();
        assertTrue( requestId.equals( requestIdFromResponse ) );
        
        readData();

        // Clean up
        doDelete( PATIENTIDENTITY_HDR );
    }


    private void readData( )
        throws Exception
    {
        Map<String, String> resolvedPatient = new HashMap<String, String>();
        resolvedPatient.put( FilterBuilder.ASSIGNING_AUTHORITY_KEY, ASSIGNING_AUTHORITY_HDR );
        resolvedPatient.put( FilterBuilder.ASSIGNING_FACILITY, ASSIGNING_FACILITY_HDR );
        resolvedPatient.put( FilterBuilder.IDENTITY, PATIENTIDENTITY_HDR );

        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( READ_TEST_DOMAINENTRYPOINT_XPATH ).size() );

    }


    @SuppressWarnings( "unchecked" )
    private Document readAndAssertDomainData( String templateId, String filter, String filterId )
        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( READ_TEST_DOMAINENTRYPOINT_XPATH );
        assertTrue( domainElements.size() > 0 );

        return clinicalDataDocument;
    }


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


    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() ) );
    }


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

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

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        NonVaMedBuilderFactory factory = new NonVaMedBuilderFactory();
        factory.setNonVaMedBuiler( new NonVaMedBuilder() );
        domainEntryPointsWrappersMap.put( "NonVaMedicationEvent", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "patient", PATIENTIDENTITY_HDR, ASSIGNING_FACILITY_HDR,
                        ASSIGNING_AUTHORITY_HDR );
        //Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( TemplateIdHelper.NONVAMEDICATION_CREATE_TEMPLATE_ID, 1, patient );
        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( "", 1, patient );
     
        return vdmClinicalDataInsert;
    }


    @SuppressWarnings( "unchecked" )
    private Document createAndAssertDomainData( String templateId, String createRequestXml, String requestId )
        throws Exception
    {
        requestProcessor.setValidateReadResponseXML( true );
        Document clinicalDataDocument = requestProcessor.createClinicalData( createRequestXml, templateId, requestId );
        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 );

        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;
    }

    private void doDelete( String patientId )
    {
        int recordExists = 0;

        recordExists = hdrJdbcTemplate.queryForObject( "SELECT COUNT(1) FROM NONVAMED_V WHERE PATIENT_IDENTITY = '" + patientId + "'", Integer.class );

        if ( recordExists > 0 )
        {
            hdrJdbcTemplate.update( "DELETE FROM NONVAMED_V WHERE PATIENT_IDENTITY = '" + patientId + "'" );
        }
    }
}
