/*******************************************************************************
 *  Imixs Workflow Technology
 *  Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,  
 *  http://www.imixs.com
 *  
 *  This program is free software; you can redistribute it and/or 
 *  modify it under the terms of the GNU General Public License 
 *  as published by the Free Software Foundation; either version 2 
 *  of the License, or (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 *  General Public License for more details.
 *  
 *  You can receive a copy of the GNU General Public
 *  License at http://www.gnu.org/licenses/gpl.html
 *  
 *  Contributors:  
 *  	Imixs Software Solutions GmbH - initial API and implementation
 *  	Ralph Soika
 *  
 *******************************************************************************/
package com.alexanderlogistics;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Logger;

import org.imixs.marty.team.TeamController;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.office.views.SearchController;
import org.imixs.workflow.office.views.SearchEvent;

import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.inject.Named;

/**
 * Der CustomSearchController reagiert auf SeachEvents und erweitert das Search
 * Query um Rechnungbetrag von-bis.
 * 
 * @author rsoika
 * @version 1.0
 */

@Named
// @SessionScoped
@RequestScoped
public class CustomSearchController implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @Inject
    SearchController searchController;

    @Inject
    TeamController teamController;

    boolean isArchiveSearch = false;

    public void init() {
        isArchiveSearch = true;
    }

    /**
     * Diese Suche schränkt immer auf Archive und Rechnugnscontrolling ein!!
     * 
     * @param searchEvent
     */
    public void onSearchEvent(@Observes SearchEvent searchEvent) {

        if (!isArchiveSearch) {
            // Keine Anpassung für andere Prozesse
            return;
        }

        String query = searchEvent.getQuery();
        float invoiceTotal = searchEvent.getSearchFilter().getItemValueFloat("invoice.total");
        Date invoiceDate = searchEvent.getSearchFilter().getItemValueDate("invoice.date");
        Date dueDate = searchEvent.getSearchFilter().getItemValueDate("invoice.duedate");
        Date closingDate = searchEvent.getSearchFilter().getItemValueDate("invoice.closingdate");

        String cdtrNumber = searchEvent.getSearchFilter().getItemValueString("cdtr.number").trim();
        String invoiceType = searchEvent.getSearchFilter().getItemValueString("invoice.type");
        String invoiceCurrency = searchEvent.getSearchFilter().getItemValueString("invoice.currency").trim();

        String invoiceNumber = searchEvent.getSearchFilter().getItemValueString("invoice.number");

        String paymentType = searchEvent.getSearchFilter().getItemValueString("payment.type").trim();
        String sequenceNumber = searchEvent.getSearchFilter().getItemValueString("sequencenumber").trim();

        query += " (type:\"workitemarchive\") ";
        // process ref= Rechnugnscontorling Prozess
        ItemCollection process = teamController.getProcessByName("Rechnungscontrolling");
        if (process == null) {
            process = teamController.getProcessByName("Invoice Controlling");
        }
        if (process != null) {
            query += " AND ($uniqueidref:\"" + process.getUniqueID() + "\") ";
        }

        // invoice.total
        if (invoiceTotal != 0) {
            // format form and to with at least one digit
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            query += " AND (invoice.total:" + decimalFormat.format(invoiceTotal) + ")";

        }

        // invoice.date
        if (invoiceDate != null) {
            query += " AND (invoice.date:" + CustomSearchController.getRangeDay(invoiceDate) + ")";

        }

        // invoice.duedate
        if (dueDate != null) {
            query += " AND (invoice.duedate:" + CustomSearchController.getRangeDay(dueDate) + ")";

        }

        // invoice.closingdate
        if (closingDate != null) {
            query += " AND ($lasteventdate:" + CustomSearchController.getRangeMonth(closingDate) + ")";
        }

        if (invoiceNumber != null && !invoiceNumber.isEmpty()) {
            query += " AND (invoice.number:" + invoiceNumber + ")";
        }

        if (paymentType != null && !paymentType.isEmpty()) {
            query += " AND (payment.type:" + paymentType + ")";
        }
        if (sequenceNumber != null && !sequenceNumber.isEmpty()) {
            query += " AND (sequencenumber:" + sequenceNumber + ")";
        }

        if (invoiceCurrency != null && !invoiceCurrency.isEmpty()) {
            query += " AND (invoice.currency:" + invoiceCurrency + ")";
        }

        // Rechnungsart
        if (invoiceType != null && !"0".equals(invoiceType)) {
            if ("1".equals(invoiceType)) {
                query += " AND ($workflowgroup:\"Rechnungseingang\" AND NOT payment.type:credit)";
            }
            if ("2".equals(invoiceType)) {
                query += " AND ($workflowgroup:Sachrechnung)";
            }
            if ("3".equals(invoiceType)) {
                query += " AND (($workflowgroup:Rechnungseingang) AND (payment.type:credit))";
            }
            if ("4".equals(invoiceType)) {
                query += " AND ($workflowgroup:\"Gutschrift Abgleich\")";
            }
        }

        // dbtr.number
        if (cdtrNumber != null && !cdtrNumber.isEmpty()) {
            cdtrNumber = cdtrNumber.trim().toUpperCase();
            if (!cdtrNumber.startsWith("K") && !cdtrNumber.startsWith("D")) {
                query += " AND (cdtr.number:K" + cdtrNumber + " OR dbtr.number:" + cdtrNumber + ")";
            } else {
                if (cdtrNumber.startsWith("K")) {
                    // suche nach Kreditor (Eingangsrechnung)
                    query += " AND (cdtr.number:" + cdtrNumber + ")";
                } else {
                    // suche nach Debitor (Ausgangsrechnung)
                    if (cdtrNumber.startsWith("D")) {
                        cdtrNumber = cdtrNumber.substring(1);
                    }
                    query += " AND (dbtr.number:" + cdtrNumber + ")";
                }
            }
        }

        logger.fine("Custom Query=" + query);
        // Udpate query
        searchEvent.setQuery(query);

    }

    /**
     * Sonder AGL Lösung um im Archiv zu bleiben.
     * 
     */
    public String refreshAGLArchive() {
        String phrase = searchController.getSearchFilter().getItemValueString("phrase");

        searchController.getSearchFilter().setItemValue("Type", "workitemarchive");
        try {
            phrase = URLEncoder.encode(phrase, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.severe("unable to encode search phrase!");
            e.printStackTrace();
        }
        String action = "/pages/workitems/agl_archive.xhtml?faces-redirect=true&phrase=" + phrase;
        searchController.setPageIndex(0);
        return action;
    }

    /**
     * This method reset the search filter and the search pageIndex and creates a
     * new bookmarkable search link to the worklist including the current search
     * phrase.
     * 
     */
    public String resetSearch() {
        searchController.reset();
        return refreshAGLArchive();
    }

    private static String getRangeDay(Date dueDate) {
        // Setze die Uhrzeit auf Mitternacht (00:00)
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(dueDate);
        startCalendar.set(Calendar.HOUR_OF_DAY, 0);
        startCalendar.set(Calendar.MINUTE, 0);
        startCalendar.set(Calendar.SECOND, 0);
        startCalendar.set(Calendar.MILLISECOND, 0);

        Date startDate = startCalendar.getTime();

        // Setze die Uhrzeit auf 23:59:59.999
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(dueDate);
        endCalendar.set(Calendar.HOUR_OF_DAY, 23);
        endCalendar.set(Calendar.MINUTE, 59);
        endCalendar.set(Calendar.SECOND, 59);
        endCalendar.set(Calendar.MILLISECOND, 999);

        Date endDate = endCalendar.getTime();
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMddHHmm");
        String dateRange = "[" + dateformat.format(startDate) + " TO "
                + dateformat.format(endDate) + "]";

        return dateRange;
    }

    private static String getRangeMonth(Date dueDate) {
        // Setze die Uhrzeit auf Mitternacht (00:00)
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(dueDate);
        startCalendar.set(Calendar.HOUR_OF_DAY, 0);
        startCalendar.set(Calendar.MINUTE, 0);
        startCalendar.set(Calendar.SECOND, 0);
        startCalendar.set(Calendar.MILLISECOND, 0);
        startCalendar.set(Calendar.DAY_OF_MONTH, 1);

        Date startDate = startCalendar.getTime();

        // Setze die Uhrzeit auf 23:59:59.999
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(dueDate);
        endCalendar.set(Calendar.HOUR_OF_DAY, 23);
        endCalendar.set(Calendar.MINUTE, 59);
        endCalendar.set(Calendar.SECOND, 59);
        endCalendar.set(Calendar.MILLISECOND, 999);
        endCalendar.set(Calendar.DAY_OF_MONTH, 1);
        endCalendar.add(Calendar.MONTH, 1);
        endCalendar.add(Calendar.DAY_OF_MONTH, -1);

        Date endDate = endCalendar.getTime();
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMddHHmm");
        String dateRange = "[" + dateformat.format(startDate) + " TO "
                + dateformat.format(endDate) + "]";

        return dateRange;
    }
}
