

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.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.IntoleranceConditionBuilder;
import gov.va.med.cds.testharness.vhim400.builders.IntoleranceConditionBuilderFactory;
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 EndToEndCreateIntoleranceConditionTest
    extends
        AbstractEndToEndReadAllergiesTest
{
    private static final String PATIENTIDENTITY_HDR = "testId6666";
    protected TemplateRequestProcessor requestProcessor;
    protected static final String REQUEST_ID_XPATH = "/clinicaldata:ClinicalData/requestId";
    protected static String DOMAINENTRYPOINT_XPATH = "//intoleranceCondition";
    protected static String ASSIGNING_FACILITY_HDR = "200CH";
    protected static String PATIENT_ID_XPATH = "//intoleranceConditions/patient/identifier/identity";
    protected static String ASSIGNINGAUTHORITY_HDR = "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 beforeIntoleranceConditionTestClassSetUp( )
        throws Exception
    {
        requestProcessor = ( TemplateRequestProcessor )getRequestProcessor();
    }


    @SuppressWarnings( "unused" )
    @Test
    @Suite( groups = { "brokentest" } )
    public void testIntoleranceConditionCreate( )
        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.INTOLERANCE_CONDITION_CREATEORUPDATE_TEMPLATE_ID, createXml );

        readData( patientIdIdentifier );

        doDelete();

    }


    @SuppressWarnings( "unchecked" )
    private void readData( String patientIdIdentifier )
        throws Exception
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        assigningFacilityAndPatientIdentityMap.put( ASSIGNING_FACILITY_HDR, patientIdIdentifier );

        Map<String, String> entryPointMap = new HashMap<String, String>();
        entryPointMap.put( "ID_2", "IntoleranceCondition" );

        String filterXml = createAllergiesSinglePatientMulitEntryPointFilter( assigningFacilityAndPatientIdentityMap, entryPointMap, null, null,
                        ASSIGNINGAUTHORITY_DOD, TemplateIdHelper.IC_SINGLE_PATIENT_ALL_DATA_FILTER, null );

        Document clinicalDataDocument = readAndAssertDomainData( assigningFacilityAndPatientIdentityMap,
                        TemplateIdHelper.INTOLERANCE_CONDITION_READ_TEMPLATE_ID, filterXml, TemplateIdHelper.IC_SINGLE_PATIENT_ALL_DATA_FILTER,
                        getIntoleranceConditionsEntryPointXpath() );

        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 );
        assertTrue( domainElements.size() > 0 );

        return clinicalDataDocument;
    }


    private void doDelete( )
    {
        hdrJdbcTemplate.update( "DELETE FROM allergy_comment_v WHERE allergy_comment_event_id IN (SELECT allergy_comment_event_id FROM allergy_comment_event_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "'))" );
        hdrJdbcTemplate.update( "DELETE FROM allergy_comment_event_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "')" );
        hdrJdbcTemplate.update( "DELETE FROM drug_ingredient_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "')" );
        ;
        hdrJdbcTemplate.update( "DELETE FROM drug_class_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "')" );
        hdrJdbcTemplate.update( "DELETE FROM allergy_pract_part_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "')" );
        hdrJdbcTemplate.update( "DELETE FROM reaction_v WHERE allergy_id in (SELECT allergy_id FROM allergy30_v WHERE patient_identity = '"
                        + PATIENTIDENTITY_HDR + "')" );
        hdrJdbcTemplate.update( "DELETE FROM allergy30_v WHERE patient_identity = '" + PATIENTIDENTITY_HDR + "'" );
    }


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

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

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        IntoleranceConditionBuilderFactory factory = new IntoleranceConditionBuilderFactory();
        factory.setIntoleranceConditionBuilder( new IntoleranceConditionBuilder() );
        domainEntryPointsWrappersMap.put( "IntoleranceCondition", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "patient", PATIENTIDENTITY_HDR, ASSIGNING_FACILITY_HDR,
                        ASSIGNINGAUTHORITY_HDR );

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( TemplateIdHelper.INTOLERANCE_CONDITION_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;
    }


    protected String createDeleteXml( String entryPoint, String templateId, String recordIdentifierIdentity )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.IntoleranceCondition );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        IntoleranceConditionBuilderFactory factory = new IntoleranceConditionBuilderFactory();
        factory.setIntoleranceConditionBuilder( new IntoleranceConditionBuilder() );

        domainEntryPointsWrappersMap.put( "IntoleranceCondition", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Document clinicalDataInsert = clinicalDataBuilder.deleteClinicalDataWithRecordVersion( domainEntryPointsMap.get( templateId ), templateId,
                        recordIdentifierIdentity, "0" );

        return clinicalDataInsert.asXML();
    }

}