package com.alexanderlogistics.migration;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.imixs.melman.FormAuthenticator;
import org.imixs.melman.RestAPIException;
import org.imixs.melman.WorkflowClient;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.exceptions.PluginException;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import junit.framework.Assert;

/**
 * Dieser Agent ordnet nachträglich Ausgangsrechnungen aus der Migraiton einem
 * Space zu.
 * 
 * @author rsoika
 *
 */
public class MigrationSpaceZuordnung {

    WorkflowClient workflowCLient = null;
    String user = "archive";
    String ps = "archive4imixs";
    String restAPI = "https://alexander-logistics.office-workflow.de/api";
    int countProcessed = 0;
    int notFound = 0;
    int count = 0;
    Map<String, List<String>> spacePosMappings=null;
    Map<String, String> spaceNames=null;

    @Before
    public void setup() throws PluginException, RestAPIException, UnsupportedEncodingException {

        // Init Workflow Client
        workflowCLient = new WorkflowClient(restAPI);
        FormAuthenticator formAuth = new FormAuthenticator(restAPI, user, ps);
        workflowCLient.registerClientRequestFilter(formAuth);

    
        // load spaces Pos Expressions
        loadSpacePosMappings();
      

    }

    /**
     * Diese methode liest offene Ausgangsrechnungen aus udn prüft of space.ref
     * bereits getzt ist.
     * 
     * @throws PluginException
     * @throws RestAPIException
     * @throws UnsupportedEncodingException 
     * 
     */
    @Test 
    @Ignore
    public void anlysiere() throws RestAPIException, PluginException, UnsupportedEncodingException {

        System.out.println("***********************");
        System.out.println("* Update Ausgangsrechnungen Pos-Space Mapping *");
        System.out.println("***********************");

        int maxCount = 3000;

        String query = "$modelversion:\"rechnungsausgang-de-1.0\" AND type:workitem";

        int pageSize = 100;
        int pageIndex =0;
        while (true) {
            workflowCLient.setPageIndex(pageIndex);
            workflowCLient.setPageSize(pageSize);
            workflowCLient.setSortBy("$created");
            List<ItemCollection> invoices = workflowCLient.searchDocuments(query);

            
            System.out.println("... ich processe " + invoices.size() +" invoices...");
            
            // teste space.ref
            for (ItemCollection invoice: invoices) {
                count++;
                boolean update=false;
                
                String currentSpaceRef=invoice.getItemValueString("space.ref");
                List<String> refList=invoice.getItemValueList("$uniqueidref",String.class);
                if (currentSpaceRef.isEmpty() || !refList.contains(currentSpaceRef)) {
                   
                    // Jezt noch das Space mapping
                    // dazu kucken wir in alle spaces den config wert 'pos.mapping'
                    String text = invoice.getItemValueString("invoice.text");
                    if (!text.isEmpty()) {
                     
                        for (Map.Entry<String, List<String> > entry : spacePosMappings.entrySet()) {
                            List<String> expressionsList=entry.getValue();
                            for (String expr : expressionsList) {
                                
                                Pattern p = Pattern.compile(expr);
                                Matcher m = p.matcher(text);
                                if (m.find()) {
                                    // we have a match
                                    invoice.setItemValue("space.ref", entry.getKey());
                                    invoice.setItemValue("space.name", spaceNames.get(entry.getKey()));
                                    invoice.appendItemValueUnique("$uniqueidref", entry.getKey());
                                    
                                    update=true;
                                    break;
                                }
                            }
                            if (update) {
                                break;
                            }
                        }
                    }
                }
                
                if (update) {
                    // update invioce
                    System.out.println("...ich update invoice: " + invoice.getUniqueID());
                    try {
                    workflowCLient.saveDocument(invoice);
                    countProcessed++;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                
                
            }

            // fetrig?
            if (invoices.size() < pageSize) {
                break;
            }
            if (count>=maxCount) {
                break;
            }
            pageIndex++;
        }

        System.out.println("=================================================");
        System.out.println("... fininshed - read " + count + " invoices");
        System.out.println("    updated " + countProcessed + " invoices");

    }

    /**
     * Helper method that loads all expressions from the spaces
     * 
     * @return List of list of expressions
     * @throws UnsupportedEncodingException 
     * @throws RestAPIException 
     */
    private void loadSpacePosMappings() throws RestAPIException, UnsupportedEncodingException {
        spacePosMappings = new HashMap<>();
        spaceNames= new HashMap<>();
        // als erstes lesen wir die pos.mappings aus den Spaces ein, auf die dann eine
        // Rechnung emapped werden kann.

        List<ItemCollection> spaces_subs = workflowCLient.searchDocuments("type:space");
        for (ItemCollection space : spaces_subs) {
            spacePosMappings.put(space.getUniqueID(), space.getItemValueList("pos.mapping", String.class));
            spaceNames.put(space.getUniqueID(), space.getItemValueString("space.name"));
        }

        
    }
}
