package com.alexanderlogistics.xml;

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

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;

import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.exceptions.AccessDeniedException;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.ProcessingErrorException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;

import com.alexanderlogistics.InvoiceUtil;
import com.alexanderlogistics.KreditorDebitorService;
import com.alexanderlogistics.mahnlauf.MahnlaufService;

/**
 * Testet den Import Vorgang anhand einer Cargosoft XML Datei
 * 
 * 
 * 
 * @author rsoika
 */
@RunWith(MockitoJUnitRunner.class)
public class InvoiceImportTester {

	@Spy
	@InjectMocks
	private CargosoftXMLInvoiceImportService service;

	@Mock
	private DocumentService documentService;

	@Mock
	private KreditorDebitorService kreditorDebitorService;

	@Mock
	private MahnlaufService mahnlaufService;

	@Before
	public void setUp() {
		// Mock protected Methode 'alreadyImported' -> always false
		Mockito.when(service.alreadyImported(Mockito.anyString())).thenReturn(false);
	}

	/**
	 * Ein Einfacher test
	 * 
	 * @throws TransformerException
	 * @throws XPathExpressionException
	 * @throws ModelException
	 * @throws PluginException
	 * @throws ProcessingErrorException
	 * @throws AccessDeniedException
	 * 
	 * @throws Exception
	 */
	@Test
	public void testInvoiceBasic() throws Exception {

		ItemCollection source = new ItemCollection();
		String fileName = "001_R_224380_110136787.xml";
		byte[] xmlContent = readTestFile("cargosoft/" + fileName);
		assertNotNull(xmlContent);

		// Act
		ItemCollection result = service.createWorkitem(source, fileName, xmlContent, new HashMap<>());

		// Assert
		assertNotNull(result);
		assertEquals("001", result.getItemValueString("mandant.id"));

		// test Rows
		List<ItemCollection> rows = InvoiceUtil.explodeChildList(result);
		assertNotNull(rows);
		assertEquals(2, rows.size());
		ItemCollection row1 = rows.get(0);
		ItemCollection row2 = rows.get(1);
		assertEquals("EX-GCA-2408-042", row1.getItemValueString("datev.text"));
		assertEquals("EX-GCA-2408-042", row2.getItemValueString("datev.text"));

	}

	/**
	 * Ein ATC test
	 * 
	 * @throws IOException
	 * 
	 * @throws Exception
	 */
	@Test
	public void testInvoiceATC() throws Exception {

		ItemCollection source = new ItemCollection();
		String fileName = "001_R_224225_115103063.xml";
		byte[] xmlContent = readTestFile("cargosoft/" + fileName);
		assertNotNull(xmlContent);

		// Act
		ItemCollection result = service.createWorkitem(source, fileName, xmlContent, new HashMap<>());

		// Assert
		assertNotNull(result);
		assertEquals("001", result.getItemValueString("mandant.id"));
		assertEquals("ATC400012650820242452", result.getItemValueString("invoice.atc.number"));
		assertEquals(3752.95, result.getItemValueDouble("invoice.total"), 0.0);

		// test Rows
		List<ItemCollection> rows = InvoiceUtil.explodeChildList(result);
		assertNotNull(rows);
		assertEquals(2, rows.size());
		ItemCollection row1 = rows.get(0);
		assertEquals("IM-GCA-2408-116", row1.getItemValueString("datev.text"));
		assertEquals("EUST", row1.getItemValueString("category"));
		assertEquals("EUST", row1.getItemValueString("BillingCode"));
		// test BillingText
		List<String> billingTextList = row1.getItemValue("BillingText");
		assertEquals(2, billingTextList.size());
		// test ATC Number
		assertEquals("ATC400012650820242452", row1.getItemValueString("atc.number"));
		// Umsatz
		assertEquals(3591.34, row1.getItemValueDouble("datev.umsatz"), 0.0);

		ItemCollection row2 = rows.get(1);
		assertEquals("IM-GCA-2408-116", row2.getItemValueString("datev.text"));
		assertEquals("SONST", row2.getItemValueString("category"));
		// Umsatz
		assertEquals(161.61, row2.getItemValueDouble("datev.umsatz"), 0.0);
	}

	/**
	 * Hilfsmethode zum einlesen einer xml test datei
	 * 
	 * @return
	 * @throws IOException
	 */
	private byte[] readTestFile(String filename) throws IOException {
		// Load the file from the resources folder
		ClassLoader classLoader = getClass().getClassLoader();
		InputStream inputStream = classLoader.getResourceAsStream(filename);
		byte[] data = inputStream.readAllBytes();
		inputStream.close();
		return data;
	}
}
