package com.alexanderlogistics.mahnlauf;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.inject.Inject;

import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.Model;
import org.imixs.workflow.SignalAdapter;
import org.imixs.workflow.WorkflowKernel;
import org.imixs.workflow.engine.ModelService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException;
import org.imixs.workflow.sepa.services.SepaWorkflowService;

import com.alexanderlogistics.KreditorDebitorService;

/**
 * The MahnlaufRefAddAdapter links an invoice with a Mahnlauf for the
 * dbtr.number item . If there is currently no open Mahnlauf for this key, the
 * adapter automatically creates a new process instance. If a mahnlauf for this
 * dbt.number is found, the invoice is just added.
 * <p>
 * If the invoice has already been linked to a Mahnlauf nothing happens.
 * <p>
 * 
 * @version 1.0
 * @author rsoika
 */
public class MahnlaufRefAddAdapter implements SignalAdapter {

	private static Logger logger = Logger.getLogger(MahnlaufRefAddAdapter.class.getName());

	@EJB
	ModelService modelService;
	
	@EJB
	KreditorDebitorService kreditorDebitorService;

	@EJB
	WorkflowService workflowService = null;

	@Inject
	SepaWorkflowService sepaWorkflowService;

	/**
	 * This method finds or create the Mahnlauf and adds a reference ($workitemref)
	 * to the current invoice.
	 * 
	 * @throws PluginException
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ItemCollection execute(ItemCollection invoice, ItemCollection event)
			throws AdapterException, PluginException {

		
		if (invoice.getTaskID()<MahnlaufService.TASK_MAHNLAUF_START || invoice.getTaskID()>MahnlaufService.TASK_MAHNLAUF_END) {
			throw new PluginException(MahnlaufRefAddAdapter.class.getName(),
					MahnlaufService.ERROR_CONFIG, "Der Mahnlauf kann nur für Rechnungen erstellt werden die bereits die Fälligkeit erreicht haben.");
		}
		
		String dbtrNumber = invoice.getItemValueString(MahnlaufService.ITEM_DBTR_NUMBER);
		ItemCollection mahnLaufWorkitem;
		try {
			mahnLaufWorkitem = findMahnlauf(dbtrNumber);

			if (mahnLaufWorkitem == null) {
				// create one...
				mahnLaufWorkitem = createNewMahnlauf(dbtrNumber, invoice, event);
			}

			// add Invoice to Mahnlauf
			List<String> refList = mahnLaufWorkitem.getItemValue("$workitemref");
			if (!refList.contains(invoice.getUniqueID())) {
				mahnLaufWorkitem.appendItemValueUnique("$workitemref", invoice.getUniqueID());
			}

			// set event 100 and process
			ItemCollection mahnlaufConfig = workflowService.evalWorkflowResult(event, "mahnlauf", invoice, true);
			int eventID = mahnlaufConfig.getItemValueInteger("event");
			
			mahnLaufWorkitem.event(eventID);
			workflowService.processWorkItem(mahnLaufWorkitem);

		} catch (QueryException | ModelException e) {
			throw new PluginException(MahnlaufRefAddAdapter.class.getName(),
					MahnlaufService.ERROR_CONFIG, "Unable to create Mahnlauf", e);
		}
		
		// set mahnlauf ref
		invoice.setItemValue("dunning.ref", mahnLaufWorkitem.getUniqueID());
		return invoice;
	}

	/**
	 * Helper method finds an open mahnlauf for a debtr.numbre (name)
	 * 
	 * @param key
	 * @return
	 * @throws QueryException
	 */
	public ItemCollection findMahnlauf(String key) throws QueryException {
		String query = "(type:workitem) AND ($modelversion:mahnlauf*) AND (name:\"" + key + "\")";
		List<ItemCollection> resultList = workflowService.getDocumentService().find(query, 1, 0, "$modified", true);

		if (resultList.size() > 0) {
			return resultList.get(0);
		}
		// no mahnaluffound
		return null;
	}

	/**
	 * Helper method to create a new Mahnlauf workitem
	 * 
	 * @param key
	 * @param invoice
	 * @return
	 * @throws ModelException
	 * @throws PluginException
	 */
	@SuppressWarnings("unused")
    public ItemCollection createNewMahnlauf(String key, ItemCollection invoice, ItemCollection event)
			throws ModelException, PluginException {
		String modelVersion = null;
		int taskID = -1;
		int eventID=-1;
		// test if the event provides a sepa export configuration
		ItemCollection mahnlaufConfig = workflowService.evalWorkflowResult(event, "mahnlauf", invoice, true);
		if (mahnlaufConfig != null && mahnlaufConfig.hasItem("modelversion") && mahnlaufConfig.hasItem("task")) {
			logger.fine("read model information from event");
			modelVersion = mahnlaufConfig.getItemValueString("modelVersion");
			taskID = mahnlaufConfig.getItemValueInteger("task");
			eventID = mahnlaufConfig.getItemValueInteger("event");
		}

		// build the sepa export workitem....
		ItemCollection mahnlaufWorkitem = new ItemCollection().model(modelVersion).task(taskID);
		mahnlaufWorkitem.replaceItemValue("name", key);
		mahnlaufWorkitem.replaceItemValue(WorkflowKernel.CREATED, new Date());
		mahnlaufWorkitem.replaceItemValue(WorkflowKernel.MODIFIED, new Date());
		// set unqiueid
		mahnlaufWorkitem.setItemValue(WorkflowKernel.UNIQUEID, WorkflowKernel.generateUniqueID());

		// copy dbtr_iban
		mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_NAME, invoice.getItemValue(MahnlaufService.ITEM_DBTR_NAME));
		
		
		// lookup email....
		String dbtrNumber=invoice.getItemValueString("dbtr.number");
		ItemCollection dbtrItemCol=kreditorDebitorService.findDebitor("D"+dbtrNumber);
		if (dbtrItemCol!=null) {
			mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_EMAIL, dbtrItemCol.getItemValue("cdtr.mail"));// dbtr.mail
		}
		
		mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_NUMBER, invoice.getItemValue(MahnlaufService.ITEM_DBTR_NUMBER));		
		mahnlaufWorkitem.setItemValue("invoice.language", invoice.getItemValue("invoice.language"));

		// set workflow group name from the Task Element to identify document in xslt
		Model model = modelService.getModel(modelVersion);
		ItemCollection task = model.getTask(taskID);
		String modelTaskGroupName = task.getItemValueString("txtworkflowgroup"); // DO NOT CHANGE!
		mahnlaufWorkitem.setItemValue(WorkflowKernel.WORKFLOWGROUP, modelTaskGroupName);

		logger.info("...created new mahnlauf " + key + "...");

		return mahnlaufWorkitem;
	}

}