/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.taxiservicios.beans.admin;

import com.arrebol.taxiservicios.beans.Datatable;
import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.BitacoraController;
import com.arrebol.taxiservicios.controller.admin.ClosingDayController;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
import com.arrebol.taxiservicios.controller.util.DateWrapper;
import com.arrebol.taxiservicios.model.admin.ClosingDay;
import com.arrebol.taxiservicios.model.admin.ClosingDayDetail;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.primefaces.event.ReorderEvent;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
@Named("historicalClosingDayBean")
@ViewScoped
public class HistoricalClosingDayBean extends TaxiGenericBean implements Serializable, Datatable {

    public void imprimir() {
        Document document = new Document(PageSize.LETTER);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            PdfWriter.getInstance(document, baos);
            List<ClosingDayDetail> results = new ArrayList<>();
            results = getController().findDetailsFromClosingDayID(new ClosingDay(selectedRow.getId()));
            User userTmp = getController().getUserById(selectedRow.getUser().getId());
            document.open();

            DateFormat formatter = new SimpleDateFormat("dd/MM/yy");

            Paragraph printDate = new Paragraph("Fecha de impresión: " + formatter.format(new Date()), FontFactory.getFont("arial", 10, Font.BOLD, BaseColor.DARK_GRAY));
            printDate.setAlignment(Element.ALIGN_RIGHT);
            document.add(printDate);

            Paragraph title = new Paragraph("Corte del día", FontFactory.getFont("arial", 18, Font.BOLD, BaseColor.DARK_GRAY));
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);

            String date = formatter.format(selectedRow.getCreatedOn());
            document.add(new Paragraph("Fecha de creación: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph(date, FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));
            document.add(new Paragraph("Usuario: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph(userTmp.getPerson().getFirstName() + " " + userTmp.getPerson().getSecondName() + " " + userTmp.getPerson().getLastName() + " " + userTmp.getPerson().getMiddleName(), FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));

            document.add(new Paragraph("Monto esperado: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph("$" + selectedRow.getAmountExpected().toString(), FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));

            document.add(new Paragraph("Monto pagado: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph("$" + selectedRow.getAmountPaid().toString(), FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));

            document.add(new Paragraph("Monto depositado: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph("$" + selectedRow.getAmountTransfer().toString(), FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));

            document.add(new Paragraph("Comentarios: ", FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            document.add(new Paragraph(selectedRow.getComments(), FontFactory.getFont("arial", 8, Font.PLAIN, BaseColor.BLACK)));

            document.add(Chunk.NEWLINE);

            PdfPTable table = new PdfPTable(4);
            table.setTotalWidth(new float[]{60, 60,170,100});

            table.setLockedWidth(true);
            PdfPCell cell = new PdfPCell(new Paragraph("Detalles del corte",
                    FontFactory.getFont("arial", 10, Font.BOLD, BaseColor.WHITE)));

            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setBackgroundColor(BaseColor.BLUE);
            cell.setColspan(7);
            table.addCell(cell);

            cell = new PdfPCell(new Paragraph("Tipo",
                    FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setColspan(1);
            table.addCell(cell);

            cell = new PdfPCell(new Paragraph("Monto",
                    FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setColspan(1);
            table.addCell(cell);

            

            cell = new PdfPCell(new Paragraph("Comentarios",
                    FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setColspan(1);
            table.addCell(cell);

            

            cell = new PdfPCell(new Paragraph("Persona",
                    FontFactory.getFont("arial", 8, Font.BOLD, BaseColor.BLACK)));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setColspan(1);
            table.addCell(cell);

            for (ClosingDayDetail tmp : results) {

                cell = new PdfPCell(new Paragraph(tmp.getType(),
                        FontFactory.getFont("arial", 6, Font.PLAIN, BaseColor.BLACK)));
                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
                cell.setColspan(1);
                table.addCell(cell);

                cell = new PdfPCell(new Paragraph(tmp.getAmount() != null ? "$" + tmp.getAmount().toString() : "$0.00",
                        FontFactory.getFont("arial", 6, Font.PLAIN, BaseColor.BLACK)));
                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
                cell.setColspan(1);
                table.addCell(cell);

                cell = new PdfPCell(new Paragraph(tmp.getComments(),
                        FontFactory.getFont("arial", 6, Font.PLAIN, BaseColor.BLACK)));
                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
                cell.setColspan(1);
                table.addCell(cell);

               

                cell = new PdfPCell(new Paragraph(tmp.getPerson() != null ? tmp.getPerson().getFirstName() + " " + tmp.getPerson().getSecondName() + " " + tmp.getPerson().getLastName() + " " + tmp.getPerson().getMiddleName() : "",
                        FontFactory.getFont("arial", 6, Font.PLAIN, BaseColor.BLACK)));
                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
                cell.setColspan(1);
                table.addCell(cell);
            }

            document.add(table);

            document.add(Chunk.NEWLINE);
            document.add(Chunk.NEWLINE);
            document.add(Chunk.NEWLINE);
            document.add(Chunk.NEWLINE);

            document.add(new Paragraph("                  __________________________                 __________________________"));
            document.add(new Paragraph("                                      Firma                                      Nombre y firma cajero responsable"));
            document.add(new Paragraph("                     " + userTmp.getPerson().getFirstName() + " " + userTmp.getPerson().getSecondName() + " " + userTmp.getPerson().getLastName() + " " + userTmp.getPerson().getMiddleName()));

        } catch (Exception e) {
            System.out.print("Error 1: " + e.getMessage());
        }

        document.close();
        FacesContext context = FacesContext.getCurrentInstance();
        Object response = context.getExternalContext().getResponse();
        if (response instanceof HttpServletResponse) {
            HttpServletResponse hrs = (HttpServletResponse) response;
            hrs.setContentType("application/pdf");
            hrs.setHeader("Content-disposition", "attachment");
            hrs.setContentLength(baos.size());
            try {
                ServletOutputStream out = hrs.getOutputStream();
                baos.writeTo(out);
                out.flush();

            } catch (IOException e) {
                System.out.print("Error 2: " + e.getMessage());
            }
            context.responseComplete();
        }
    }

    public List<ClosingDayDetail> getDetailsByClosinfDayId(String id) {
        logger.info("getDetailsByClosinfDayId");

        List<ClosingDayDetail> results = new ArrayList<>();
        try {
            if (null != id && id.length() == 36) {
                results = getController().findDetailsFromClosingDayID(new ClosingDay(id));
            }
        } catch (Exception e) {
            logger.error("getDetailsByClosinfDayId" + e);
            showMessage(FacesMessage.SEVERITY_ERROR,
                    getBundlePropertyFile().getString("cash.daily.cut"),
                    getBundlePropertyFile().getString("find.closing.day.details.error"));
        }
        return results;
    }

    /**
     * Update expense company list between start date and end date.
     */
    public void updateHistoricalList() {
        logger.info("updateHistoricalList");
        try {
            if (getGenericStartDate().after(getGenericEndDate())) {
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("cash.daily.cut"),
                        getBundlePropertyFile().getString("start.date.after.error"));
            } else {
                setGenericUpDates(false);
                setHistoricalClosingList(
                        getController().findClosingDailyListBetweenDates(
                                getGenericStartDate(),
                                getGenericEndDate(),
                                getLoggedUser().getLocation().getId())
                );
            }
        } catch (Exception e) {
            logger.error("updateHistoricalList", e);
        }
    }

    @Override
    public void editRow(RowEditEvent event) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onRowCancel(RowEditEvent event) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onRowReorder(ReorderEvent event) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void addRow() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void deleteRow() {
        logger.info("deleteRow");
        if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden eliminar más registros porque ya existe un cuadre de caja general del día");
            return;
        }

        if (getGenericController().existStableSmallBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden eliminar más registros porque ya existe un cuadre de caja chica del día");
            return;
        }
        try {
            if (getController().existNextPaidClosingDayByCreatedOn(getSelectedRow().getCreatedOn())) {
                showMessage(FacesMessage.SEVERITY_WARN,
                        getBundlePropertyFile().getString("cash.daily.cut"),
                        getBundlePropertyFile().getString("cash.daily.cut.not.allow.exception.desc"));
            } else {
                if (getController().updateClosingDailyById(getSelectedRow().getId(), BasicType.DISABLED, getLoggedUser())) {

                    if (null == getCommentsBitacora() || getCommentsBitacora().trim().equals("")) {
                        setCommentsBitacora("El usuario " + getLoggedUser().getUserName() + " no agrego comentarios a la hora de borrar este gasto administrativo");
                    }

                    String actionBitacora = "Eliminar corte del día";
                    String descBitacora = "Se eliminó el corte del asesor " + getSelectedRow().getUser().getUserName()
                            + ", monto a reportar " + currencyFormatNumber(getSelectedRow().getAmountPaid())
                            + ", monto reportado " + currencyFormatNumber(getSelectedRow().getAmountExpected())
                            + ", monto diferencia " + currencyFormatNumber(getSelectedRow().getAmountExpected().subtract(getSelectedRow().getAmountPaid()))
                            + " y fecha " + getSelectedRow().getCreatedOn();

                    getBitacoraController().saveNewRecordInBitacora(createNewRecordInBitacora(UUID.randomUUID().toString(), actionBitacora, getCommentsBitacora(), descBitacora),
                            getLoggedUser().getLocation().getId());
                    getHistoricalClosingList().remove(getSelectedRow());

                    setSelectedRow(null);
                    setCommentsBitacora("");

                    showMessage(FacesMessage.SEVERITY_INFO,
                            getBundlePropertyFile().getString("cash.daily.cut"),
                            getBundlePropertyFile().getString("cash.daily.cut.delete.success.desc"));
                } else {
                    showMessage(FacesMessage.SEVERITY_ERROR,
                            getBundlePropertyFile().getString("cash.daily.cut"),
                            getBundlePropertyFile().getString("cash.daily.cut.delete.exception.desc"));
                }
            }
        } catch (Exception e) {
            logger.error("deleteRow", e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("cash.daily.cut"),
                    getBundlePropertyFile().getString("cash.daily.cut.delete.exception.desc"));
        }
    }

    @PostConstruct
    public void init() {
        logger.info("init");
        try {
            loadBundlePropertyFile();
            setGenericUpDates(true);
            setController(new ClosingDayController());
            setGenericController(new GenericValidationController());
            setBitacoraController(new BitacoraController());
            setLastStableSmallBox(getGenericController().lastStableSmallBoxByDate(getLoggedUser()));
            setHayCuadre(getGenericController().existStableSmallBoxByCurdate(getLoggedUser()));

            setHistoricalClosingList(getController().findClosingDailyListBetweenDates(
                    getGenericStartDate(),
                    getGenericEndDate(),
                    getLoggedUser().getLocation().getId()
            ));

        } catch (Exception e) {
            logger.error(e);
        }
    }

    private ClosingDayController controller;
    private BitacoraController bitacoraController;
    private List<ClosingDay> historicalClosingList;
    private ClosingDay selectedRow;
    private String commentsBitacora;
    private GenericValidationController genericController;
    private Date lastStableSmallBox;
    private boolean hayCuadre;

    public Date getLastStableSmallBox() {
        return lastStableSmallBox;
    }

    public void setLastStableSmallBox(Date lastStableSmallBox) {
        this.lastStableSmallBox = lastStableSmallBox;
    }

    public boolean isHayCuadre() {
        return hayCuadre;
    }

    public void setHayCuadre(boolean hayCuadre) {
        this.hayCuadre = hayCuadre;
    }

    public GenericValidationController getGenericController() {
        return genericController;
    }

    public void setGenericController(GenericValidationController genericController) {
        this.genericController = genericController;
    }

    public ClosingDayController getController() {
        return controller;
    }

    public void setController(ClosingDayController controller) {
        this.controller = controller;
    }

    public void setBitacoraController(BitacoraController bitacoraController) {
        this.bitacoraController = bitacoraController;
    }

    public BitacoraController getBitacoraController() {
        return bitacoraController;
    }

    public List<ClosingDay> getHistoricalClosingList() {
        if (null == historicalClosingList) {
            historicalClosingList = new ArrayList<>();
        }
        return historicalClosingList;
    }

    public void setHistoricalClosingList(List<ClosingDay> historicalClosingList) {
        this.historicalClosingList = historicalClosingList;
    }

    public ClosingDay getSelectedRow() {
        return selectedRow;
    }

    public void setSelectedRow(ClosingDay selectedRow) {
        this.selectedRow = selectedRow;
    }

    public String getCommentsBitacora() {
        return commentsBitacora;
    }

    public void setCommentsBitacora(String commentsBitacora) {
        this.commentsBitacora = commentsBitacora;
    }

    private static final long serialVersionUID = 4957512825973535277L;
    final Logger logger = LogManager.getLogger(HistoricalClosingDayBean.class);
}
