package com.alexanderlogistics;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;

import javax.inject.Inject;
import javax.xml.bind.JAXBException;
import javax.xml.transform.TransformerException;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.imixs.archive.core.SnapshotService;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.SignalAdapter;
import org.imixs.workflow.engine.ReportService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;

/**
 * This adapter exports the invoice data to a ftp server connected to cargosoft.
 * <p>
 * The adapter can be configured through the model result item 'cargosoft'
 * <p>
 * report = report definition to transfers the workitem into the cargosoft xml
 * structure
 * 
 * <pre>
 * {@code
        <cargosoft name="report">cargosoft</cargosoft>
       
   }
 * </pre>
 * <p>
 * Because we also export the attachment data to cargosoft, the adaper lookups
 * the conente of the attachment in the snapshot of the origin workitem
 * 
 * 
 * @version 1.0
 * @author rsoika
 */
public class CargosoftExportAdapter implements SignalAdapter {

    public static final int EVENT_SUCCESS = 200;
    public static final int EVENT_FAILURE = 300;

    public static final String REPORT_ERROR = "REPORT_ERROR";
    public static final String CONFIG_ERROR = "CONFIG_ERROR";

    @Inject
    @ConfigProperty(name = FTPConnector.ENV_EXPORT_FTP_MAX_ATTACHMENT_SIZED, defaultValue = "10485760")
    long maxAttachmentSize;

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

    @Inject
    @ConfigProperty(name = FTPConnector.ENV_EXPORT_FTP_HOST)
    Optional<String> ftpServer;

    @Inject
    WorkflowService workflowService;

    @Inject
    SnapshotService snapshotService;

    @Inject
    ReportService reportService;

    @Inject
    FTPConnector ftpConnector;

    /**
     * This method computes the cargosoft export data file
     */
    @Override
    public ItemCollection execute(ItemCollection document, ItemCollection event) throws AdapterException {

        logger.info("......starting export...");
        try {

            // read the cargosoft export options
            ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "cargosoft", document, false);

            if (evalItemCollection == null) {
                throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), CONFIG_ERROR,
                        "missign cargosoft configuration in model event - please check model configuration");
            }
            String reportID = evalItemCollection.getItemValueString("report");
            ItemCollection report = reportService.findReport(reportID);

            if (report == null) {
                throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), CONFIG_ERROR,
                        "missign cargosoft report '" + reportID + "' - please check model configuration");
            }

            List<ItemCollection> sourceData = new ArrayList<ItemCollection>();
            // add the file data form the snapshot origin workitem
            ItemCollection documentWithFileData = loadFileDataFromSnapshot(document);
            sourceData.add(documentWithFileData);
            // start transformation
            FileData exportFile = reportService.transformDataSource(report, sourceData,
                    document.getUniqueID() + ".xml");
            // attach result
            document.addFileData(exportFile);

            // transfer file via FTP...
            if (ftpServer.isPresent()) {
                logger.info("ftp transfer...");
                ftpConnector.put(exportFile);
            }

            // finally append the success event id
            document.event(EVENT_SUCCESS);

        } catch (PluginException | JAXBException | TransformerException | IOException e) {
            logger.severe("cargosoft export failed: " + e.getMessage());
            document.setItemValue("cargosoft.error", e.getMessage());
            document.event(EVENT_FAILURE);
        }

        return document;
    }

    /**
     * This method lookups the origin snapshot data and add the content of the $file
     * to the export document
     * <p>
     * Change 14.10.2021 - Wir senden maximal 5MB and Daten, da die Cargosoft
     * Schnittstelle größere Datensätze mit großen Dateianhängen einfach verschluckt
     * ohne eine Fehlermeldugn zu liefern.
     * 
     * 
     * @param document
     * @return
     */
    @SuppressWarnings("unchecked")
    private ItemCollection loadFileDataFromSnapshot(ItemCollection document) {
        ItemCollection origin = null;
        ItemCollection result = (ItemCollection) document.clone();

        // find the origin document
        List<String> refs = document.getItemValue(WorkflowService.UNIQUEIDREF);
        for (String ref : refs) {
            origin = workflowService.getWorkItem(ref);
            // "Rechnungseingang".equals(origin.getWorkflowGroup())
            if (InvoicePlugin.isCargoRechnung(origin)) {
                break;
            }
            origin = null;
        }

        // we should have found the origin...
        if (origin != null) {
            ItemCollection snapshot = snapshotService.findSnapshot(origin);
            // we should have found a snapshot...
            if (snapshot != null) {
                List<FileData> fileDataList = snapshot.getFileData();
                // transfer origin file content
                result.removeItem("$file");
                long currentAttachmentSize = 0;
                // we do only accept .pdf files and a maximum size of 10MB
                for (FileData filedata : fileDataList) {
                    if (filedata.getName().toLowerCase().endsWith(".pdf")) {
                        // test if the size of the file is below the
                        // "cargosoft.export.ftp.maxattachmentsize"
                        if ((currentAttachmentSize + filedata.getContent().length) > maxAttachmentSize) {
                            long maxSizeInMB = maxAttachmentSize / 1024 / 1024;
                            String message = "Attachment '" + filedata.getName()
                                    + "' can not be exported to cargosoft - max file size exeeded (" + maxSizeInMB
                                    + "MB)!";
                            logger.warning(message);
                            // add comment
                            document.setItemValue("txtComment", message);
                        } else {
                            result.addFileData(filedata);
                            currentAttachmentSize = currentAttachmentSize + filedata.getContent().length;
                        }
                    }
                }
            } else {
                logger.warning("...did not found snapshot for origin workitem " + origin.getUniqueID());
            }
        } else {
            logger.warning("...did not found  origin workitem " + document.getUniqueID());
        }

        return result;

    }

}