

package gov.va.med.cds.integration;


import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.filter.CdsFilterInterface;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.persistence.hibernate.IdentityException;
import gov.va.med.cds.request.ReadResponseInterface;
import gov.va.med.cds.request.ResponseInterface;
import gov.va.med.cds.request.ValidationException;
import gov.va.med.cds.uniqueidentifier.UniqueIdentifier;
import gov.va.med.cds.xml.schema.SchemaValidationException;

import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith( SuiteAwareRunner.class )
public abstract class AbstractEndToEndErrorHandlingUseCasesTest
    extends
        AbstractEndToEndTest
{
    private static final String DONTCARE_FILTER = "dontcare_filter";


    protected CdsFilterInterface getCdsFilterByName( String aFilterPropertyName )
        throws Exception
    {
        CdsFilterInterface cdsFilter = getCdsFilterByXml( createBadFilter() );
        return cdsFilter;
    }


    @SuppressWarnings( "unchecked" )
    protected abstract void compareFatalException( Class cdsException, ErrorCodeEnum errorCode, String responseXml, boolean checkDisplayMessage );


    protected abstract String createBadFilter( );


    protected CdsFilterInterface getCdsFilterByXml( String aXmlString )
        throws Exception
    {
    	Document filterDocument = DocumentHelper.parseText(aXmlString);
        return getFilterFactory().create( filterDocument, "templateId", "requestId" );
    }


    /**
     * ExceptionHandlingSpreadsheet: A delete request does not contain a valid identity: is a Fatal Error. returns a
     * message to the client. logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testBadIdentityDeleteRequest( )
        throws Exception
    {
        String deleteRequest = createBadIdentityDeleteRequest();
        String deleteRequestTemplateId = createBadIdentityDeleteRequestTemplateId();

        Document response = getRequestProcessor().deleteClinicalData( deleteRequest, deleteRequestTemplateId,
                        new UniqueIdentifier().toString() );

        logger.debug( " testBadIdentityDeleteRequest( ) " + response.asXML() );
        compareFatalException( IdentityException.class, ErrorCodeEnum.NON_UNIQUE_IDENTITY, response.asXML(), false );
    }


    protected abstract String createBadIdentityDeleteRequestTemplateId( );


    protected abstract String createBadIdentityDeleteRequest( );


    /**
     * ExceptionHandlingSpreadsheet: A write request does not contain something that is required: is a Fatal Error.
     * returns a message to the client. logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testIntegrityConstraintViolationWriteRequest( )
        throws Exception
    {
        String writeRequest = createIntegrityConstraintViolationWriteRequest();
        String writeRequestTemplateId = createIntegrityConstraintViolationWriteRequestTemplateId();

        Document response = getRequestProcessor().createClinicalData( writeRequest, writeRequestTemplateId,
                        new UniqueIdentifier().toString() );

        compareFatalException( SchemaValidationException.class, ErrorCodeEnum.SCHEMA_VALIDATION_FAILED, response.asXML(), false );
    }


    protected abstract String createIntegrityConstraintViolationWriteRequestTemplateId( );


    protected abstract String createIntegrityConstraintViolationWriteRequest( );


    /**
     * ExceptionHandlingSpreadsheet: A read request does not contain a valid template id: is a Fatal Error. returns a
     * message to the client.  logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testInvalidTemplateIdReadRequest( )
    {
        String invalidTemplateId = createInvalidTemplateId();

        Document response = getRequestProcessor().readClinicalData( invalidTemplateId, null, DONTCARE_FILTER,
                        new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.INVALID_TEMPLATE, response.asXML(), false );
    }


    /**
     * ExceptionHandlingSpreadsheet: A read request does not contain a valid filter xml: is a Fatal Error. returns a
     * message to the client. logs internally.
     * @throws IOException 
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testInvalidFilterXmlReadRequest( )
    {
        String readTemplateId = createValidReadTemplateId();
        String invalidFilter = createInvalidReadFilter();

        Document response = getRequestProcessor().readClinicalData( readTemplateId, invalidFilter, null,
                        new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.ERROR_MARSHALLING_FILTER_XML, response.asXML(), false );
    }


    protected abstract String createInvalidReadFilter( );


    protected abstract String createValidReadTemplateId( );


    /**
     * ExceptionHandlingSpreadsheet: A null write request: is a Fatal Error. returns a message to the client. logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testNullXmlWriteRequest( )
    {
        Document response = getRequestProcessor().createClinicalData( null, null, new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.WRITE_REQUEST_XML_NULL, response.asXML(), true );
    }


    /**
     * ExceptionHandlingSpreadsheet: A write request does not contain a valid template id: is a Fatal Error. returns a
     * message to the client. logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testInvalidTemplateIdWriteRequest( )
        throws IOException
    {

        String writeRequest = createInvalidTemplateIdWriteRequest();
        String writeRequestTemplateId = createInvalidTemplateId();

        Document response = getRequestProcessor().createClinicalData( writeRequest, writeRequestTemplateId,
                        new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.WRITE_REQUEST_TEMPLATE_ID_INVALID, response.asXML(), false );
    }


    protected abstract String createInvalidTemplateId( );


    protected abstract String createInvalidTemplateIdWriteRequest( );


    /**
     * ExceptionHandlingSpreadsheet: A null templateId in a read request: is a Fatal Error. returns a message to the
     * client. logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testNullTemplateIdReadRequest( )
    {
        Document response = getRequestProcessor().readClinicalData( null, DONTCARE_FILTER, null, new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.READ_REQUEST_TEMPLATE_ID_NULL, response.asXML(), true );
    }


    /**
     * ExceptionHandlingSpreadsheet: A null filter in a read request: is a Fatal Error. returns a message to the client.
     *  logs internally.
     */
    @Test
    @Suite( groups = { "brokentest" } )
    public void testNullFilterXmlReadRequest( )
    {
        String readTemplateId = createValidReadTemplateId();
        Document response = getRequestProcessor().readClinicalData( readTemplateId, null, null, new UniqueIdentifier().toString() );

        compareFatalException( ValidationException.class, ErrorCodeEnum.READ_REQUEST_FILTER_XML_NULL, response.asXML(), true );
    }

}
