package com.fp.frontend.controller.armas.funcionalidad;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

import com.fp.dto.AbstractDataTransport;
import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.query.SubQuery;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.alfresco.AlfrescoController;
import com.fp.frontend.controller.armas.parametros.CashManagementHistoryController;
import com.fp.frontend.controller.armas.solicitud.SolicitudArmasController;
import com.fp.frontend.controller.armas.solicitud.SolicitudTramiteController;
import com.fp.frontend.controller.pcustomer.lov.PersonLovController;
import com.fp.frontend.controller.pgeneral.date.TgeneNotAccountingDayController;
import com.fp.frontend.controller.pgeneral.gene.ParametersController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.frontend.utility.Utilidades;
import com.fp.persistence.parmas.fun.TarmCashManagementHistory;
import com.fp.persistence.parmas.soli.CashManagementDTO;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.parmas.soli.TarmSolicitudTramite;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;

/**
 * @author Christian Pazmino Cash management
 */
@ManagedBean
@ViewScoped
public class ReporteCashManagmentController extends AbstractController<AbstractDataTransport> {

    public ReporteCashManagmentController() throws Exception {
        super(AbstractDataTransport.class);
        // TODO Auto-generated constructor stub
    }

    private static final long serialVersionUID = 1L;
    // Fecha inicial
    private Date fechainicial;
    // Fecha final
    private Date fechafinal;
    // Fecha inicial con mascara
    private String fechaInicialStr;
    // Fecha final con mascara
    private String fechaFinalStr;
    // Lista con informacion de los tramites habilitados para realizar los depositos en la cuenta
    private List<CashManagementDTO> cashManagementList = new ArrayList<CashManagementDTO>();
    // Fecha del ultimo reporte generado
    private String fechaUltReporte;
    // Autor del ultimo reporte generado
    private String autorUltReporte;
    // Path del reporte en el alfresco
    private String xpathReporte;
    // Controlador de Solicitud Tramite
    @ManagedProperty(value = "#{solicitudTramiteController}")
    private SolicitudTramiteController solicitudTramiteController;
    // Controlador del alfresco
    @ManagedProperty(value = "#{alfrescoController}")
    private AlfrescoController alfrescoController;
    // Nombre identificador del archivo cash management generado
    private String nombreArchivo;

    private File archivo;
    /**
     * Controlador que maneja los datos de generacion ultima vez del reporte
     */
    @ManagedProperty(value = "#{cashManagementHistoryController}")
    private CashManagementHistoryController cashManagementHistoryController;

    @PostConstruct
    private void postconstruct() {
        this.init();
        // Inicializa autoconsulta
    }

    /**
     * Incializa el controlador, cuando se esta utilizando una pagina que utliza
     * el controlador.
     */
    private void init() {
        try {
            TarmCashManagementHistory ultimoReporteObj = CashManagementHistoryController.findUltimoReporteGenerado();
            if (ultimoReporteObj != null) {
                SimpleDateFormat sdfUltimaFecha = new SimpleDateFormat("dd/MM/yyyy HH:mm");
                fechaUltReporte = sdfUltimaFecha.format(ultimoReporteObj.getDatefrom());
                autorUltReporte = ultimoReporteObj.getModifiedData().get("personname") != null ? ultimoReporteObj.getModifiedData().get("personname").toString() : null;
            }
            this.beanalias = "CASHMANAGEMENT";
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
            int diasLaborablesPermitidos = ParametersController.find("DIASDEPOSITO", "1").getNumbervalue().intValue();
            // La fecha inicial se calcula en funcion del numero de dias laborables permitidos para el deposito
            fechainicial = TgeneNotAccountingDayController.diasLaborablesPreviosAUnaFecha(new Date(), diasLaborablesPermitidos);
            // La fecha final es la fecha actual      	
            Calendar fechaFinalCldr = Calendar.getInstance();
            System.out.println("Fecha final " + fechaFinalCldr.getTime());
            fechaFinalStr = sdf.format(fechaFinalCldr.getTime());
            System.out.println("Fecha inicial " + fechainicial);
            fechaInicialStr = sdf.format(fechainicial);
            querydatabase();
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    protected void querydatabase() {
        try {
            System.out.println("Ejecuta querydatabase cash managment...");
            Request request = this.callerhelper.getRequest();
            DtoQuery dto = super.getDtoQuery(true);
            HashMap<String, DtoQuery> mtables = new HashMap<String, DtoQuery>();
            mtables.put(this.beanalias, dto); // permite adicionar mas de una tabla.
            request.setQueryTables(mtables);
            request.put("queryalias", "CASHMANAGEMENT");
            request.put("querytype", "P");
            request.put("fechaInicialStr", fechaInicialStr);
            request.put("fechaFinalStr", fechaFinalStr);
            Response resp = this.callerhelper.executeQuery(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                this.lrecord = new ArrayList<AbstractDataTransport>();
                MessageHelper.setMessageError(resp);
            } else {
                this.lrecord = (List<AbstractDataTransport>) resp.get(this.beanalias);
                List<Object[]> lCashManagement = (List<Object[]>) resp.get("CASHMANAGEMENTLIST");
                construirListaCashDTO(lCashManagement);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void construirListaCashDTO(List<Object[]> lCashManagement) {
        for (Object[] cashObj : lCashManagement) {
            CashManagementDTO cashManagementDTO = new CashManagementDTO();
            // Codigo orientacion
            cashManagementDTO.setCodigoServicio(cashObj[0] != null ? cashObj[0].toString() : null);
            // Contra partida
            cashObj[1] = Integer.parseInt(cashObj[1].toString().substring(4, cashObj[1].toString().length()));
            cashManagementDTO.setContrato(cashObj[1] != null ? cashObj[1].toString() : null);
            // Moneda
            cashManagementDTO.setMoneda(cashObj[2] != null ? cashObj[2].toString() : null);
            // Valor
            String valorDosDecimalesStr = null;
            if (cashObj[3] != null) {
                BigDecimal valorDosDecimales = ((BigDecimal) cashObj[3]).setScale(2);
//				valorDosDecimales.setScale(2, BigDecimal.ROUND_HALF_UP);
                valorDosDecimalesStr = valorDosDecimales.toString().replace(".", "");
            }
            cashManagementDTO.setValorapagar(valorDosDecimalesStr);
            // Forma de cobro, forma de pago
            cashManagementDTO.setFormaCobro(cashObj[4] != null ? cashObj[4].toString() : null);
            // Tipo de cuenta
            cashManagementDTO.setTipoCuenta(cashObj[5] != null ? cashObj[5].toString() : null);
            // NUmero de cuenta
            cashManagementDTO.setNumeroCuenta(cashObj[6] != null ? cashObj[6].toString() : null);
            // Referencia
            cashManagementDTO.setReferencia(cashObj[7] != null ? Utilidades.reemplazaAcentosCaractEspeciales(cashObj[7].toString()) : null);
            // Tipo ID cliente
            cashManagementDTO.setTipoIDCliente(cashObj[8] != null ? cashObj[8].toString() : null);
            // Nombre del cliente
            cashManagementDTO.setNumeroIDCliente(cashObj[9] != null ? cashObj[9].toString() : null);
            // Si el nombre del cliente es mayor a 41 caracteres
            if (cashObj[10] != null && cashObj[10].toString().length() > 41) {
                cashObj[10] = cashObj[10].toString().substring(0, 41);
            }
            // Nombre del cliente
            cashManagementDTO.setNombreCliente(cashObj[10] != null ? Utilidades.reemplazaAcentosCaractEspeciales(cashObj[10].toString()) : null);
            // Base Imponible
            cashManagementDTO.setBaseImponible(cashObj[11] != null ? cashObj[11].toString() : null);
            // Csolicitud
            cashManagementDTO.setCsolicitud(cashObj[12] != null ? cashObj[12].toString() : null);
            cashManagementList.add(cashManagementDTO);
        }
    }

    /**
     * Graba los registros en la base de datos
     */
    @Override
    public void save() {

    }

    /**
     * Obtiene el reporte de cash management
     */
    public void generarReporte(String filename) {
        try {
            
            if (cashManagementList.isEmpty()) {
                MessageHelper.setMessageInfo("NO EXISTEN DATOS PARA GENERAR EL REPORTE...");
//        		return null;
            }
            archivo = File.createTempFile(filename, ".txt");
//			File archivo = File.createTempFile("cashmanagement"+fechaFinalStr,".txt");
            PrintWriter escribir = new PrintWriter(archivo);
            for (CashManagementDTO cashManagementDTO : cashManagementList) {
                escribir.print(cashManagementDTO.getCodigoServicio() != null ? cashManagementDTO.getCodigoServicio() + "\t" : "\t");
                escribir.print(cashManagementDTO.getContrato() != null ? cashManagementDTO.getContrato() + "\t" : "\t");
                escribir.print(cashManagementDTO.getMoneda() != null ? cashManagementDTO.getMoneda() + "\t" : "\t");
                escribir.print(cashManagementDTO.getValorapagar() != null ? cashManagementDTO.getValorapagar() + "\t" : "\t");
                escribir.print(cashManagementDTO.getFormaCobro() != null ? cashManagementDTO.getFormaCobro() + "\t" : "\t");
                escribir.print(cashManagementDTO.getTipoCuenta() != null ? cashManagementDTO.getTipoCuenta() + "\t" : "\t");
                escribir.print(cashManagementDTO.getNumeroCuenta() != null ? cashManagementDTO.getNumeroCuenta() + "\t" : "\t");
                escribir.print(cashManagementDTO.getReferencia() != null ? cashManagementDTO.getReferencia() + "\t" : "\t");
                escribir.print(cashManagementDTO.getTipoIDCliente() != null ? cashManagementDTO.getTipoIDCliente() + "\t" : "\t");
                escribir.print(cashManagementDTO.getNumeroIDCliente() != null ? cashManagementDTO.getNumeroIDCliente() + "\t" : "\t");
                escribir.print(cashManagementDTO.getNombreCliente() != null ? cashManagementDTO.getNombreCliente() + "\r\n" : "\r\n");
                TarmSolicitudTramite solicitudTramiteObj = SolicitudTramiteController.findByCSolicitud(cashManagementDTO.getCsolicitud());
                solicitudTramiteObj.setIncashreport("S");
                solicitudTramiteController.updateSimple(solicitudTramiteObj);
                // escribir.println(cashManagementDTO.getBaseImponible());

            }
            solicitudTramiteController.save();
            escribir.flush();
            escribir.close();
//			return archivo;
        } catch (Exception ex) {
            MessageHelper.setMessageError(ex);
//            return null;
        }

    }

    /**
     * Llama a la construccion del metodo para recargar
     */
    public void descargarArchivo() {
//		File archivoTemporal=generarReporte();		
        try {
            obtenerSecuencialSolicitud();
            this.xpathReporte = this.getRutaDocumento();
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sdfFechaParaNombre = new SimpleDateFormat("ddMMyyyyHHmm");
            String fechaParaNombre = sdfFechaParaNombre.format(calendar.getTime());
            String filename = "COMACO" + fechaParaNombre + this.nombreArchivo;

            generarReporte(filename);
            filename = filename + ".txt";

//			if(archivoTemporal==null){
            if (archivo == null) {
                return;
            }
            InputStream inputStream = new FileInputStream(archivo);	//(archivoTemporal);							

            HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            response.addHeader("Content-disposition", "attachment; filename=" + filename);
            OutputStream out = response.getOutputStream();

            int read = 0;
            byte[] bytes = new byte[1024];

            while ((read = inputStream.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            out.flush();

            FacesContext.getCurrentInstance().responseComplete();

            generarReporte(filename);
            InputStream inputStream2 = new FileInputStream(archivo);

//            if(!this.alfrescoController.uploadFile(inputStream, filename, this.xpathReporte)){ 
            if (!this.alfrescoController.uploadFile(inputStream2, filename, this.xpathReporte)) {
                throw new Exception("ERROR AL CARGAR EL REPORTE");
            }

            inputStream.close();
            inputStream2.close();

            // Guardar datos ultima generacion del archivo
            TarmCashManagementHistory actualCashManagementHistory = new TarmCashManagementHistory();
            actualCashManagementHistory.setDatefrom(new Timestamp(calendar.getTimeInMillis()));
            actualCashManagementHistory.setDateto(Utilidades.getFechaExpiracion());
            actualCashManagementHistory.setIsnew(true);
            actualCashManagementHistory.setNombrearchivo(filename);
            actualCashManagementHistory.setPathreporte(this.xpathReporte + "/cm:" + filename);
            actualCashManagementHistory.setPk(nombreArchivo);

            TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
            actualCashManagementHistory.setUsercode(tsafeUserDetail.getPk().getUsercode());

            cashManagementHistoryController.update(actualCashManagementHistory);

            List<TarmCashManagementHistory> ultimoCashManagementHistoryList = CashManagementHistoryController.findReportesGeneradosVigentes();
            if (ultimoCashManagementHistoryList != null) {
                for (TarmCashManagementHistory ultimoCashManagementHistory : ultimoCashManagementHistoryList) {
                    ultimoCashManagementHistory.setDateto(new Timestamp(calendar.getTimeInMillis()));
                    ultimoCashManagementHistory.setIsnew(Boolean.FALSE);
                    cashManagementHistoryController.update(ultimoCashManagementHistory);
                }
            }
            cashManagementHistoryController.save();

        } catch (Exception e) {
            // TODO: handle exception
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Arma la petici&oacute;n al core para solicitar un n&uacute;mero de
     * secuencial para la solicitud antes de guardarla
     *
     * @throws Throwable
     */
    private void obtenerSecuencialSolicitud() throws Throwable {
        Request request = callerhelper.getRequest();
        DtoQuery dtoQuery = super.getDtoQuery(true);
        HashMap<String, DtoQuery> mapQuery = new HashMap<String, DtoQuery>();
        mapQuery.put(beanalias, dtoQuery);
        request.put("querytype", "T");
        request.setQueryTables(mapQuery);
        Response response = callerhelper.executeQuery(request);
        if (response.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
            MessageHelper.setMessageError(response);
        } else {
            nombreArchivo = response.get("CASHHISTORICOSEQUENCE").toString();
        }
    }

    /**
     * Metodo para armar la ruta del documento
     *
     * @return
     */
    public String getRutaDocumento() {
        Calendar calendar = Calendar.getInstance();
        StringBuilder ruta = new StringBuilder("cm:CashManagement");
        ruta = ruta.append("/cm:A-").append(calendar.get(Calendar.YEAR));
        ruta = ruta.append("/cm:M-").append(
                (calendar.get(Calendar.MONTH) + 1) <= 9 ? "0" + (calendar.get(Calendar.MONTH) + 1) : (calendar.get(Calendar.MONTH) + 1));
        ruta = ruta.append("/cm:D-").append(
                (calendar.get(Calendar.DAY_OF_MONTH)) <= 9 ? "0" + (calendar.get(Calendar.DAY_OF_MONTH)) : (calendar.get(Calendar.DAY_OF_MONTH)));
        return ruta.toString();
    }

    public Date getFechainicial() {
        return fechainicial;
    }

    public void setFechainicial(Date fechainicial) {
        this.fechainicial = fechainicial;
    }

    public Date getFechafinal() {
        return fechafinal;
    }

    public void setFechafinal(Date fechafinal) {
        this.fechafinal = fechafinal;
    }

    public String getFechaInicialStr() {
        return fechaInicialStr;
    }

    public void setFechaInicialStr(String fechaInicialStr) {
        this.fechaInicialStr = fechaInicialStr;
    }

    public String getFechaFinalStr() {
        return fechaFinalStr;
    }

    public void setFechaFinalStr(String fechaFinalStr) {
        this.fechaFinalStr = fechaFinalStr;
    }

    public String getFechaUltReporte() {
        return fechaUltReporte;
    }

    public void setFechaUltReporte(String fechaUltReporte) {
        this.fechaUltReporte = fechaUltReporte;
    }

    public String getAutorUltReporte() {
        return autorUltReporte;
    }

    public void setAutorUltReporte(String autorUltReporte) {
        this.autorUltReporte = autorUltReporte;
    }

    public CashManagementHistoryController getCashManagementHistoryController() {
        return cashManagementHistoryController;
    }

    public void setCashManagementHistoryController(
            CashManagementHistoryController cashManagementHistoryController) {
        this.cashManagementHistoryController = cashManagementHistoryController;
    }

    public String getXpathReporte() {
        return xpathReporte;
    }

    public void setXpathReporte(String xpathReporte) {
        this.xpathReporte = xpathReporte;
    }

    public AlfrescoController getAlfrescoController() {
        return alfrescoController;
    }

    public void setAlfrescoController(AlfrescoController alfrescoController) {
        this.alfrescoController = alfrescoController;
    }

    public String getNombreArchivo() {
        return nombreArchivo;
    }

    public void setNombreArchivo(String nombreArchivo) {
        this.nombreArchivo = nombreArchivo;
    }

    public SolicitudTramiteController getSolicitudTramiteController() {
        return solicitudTramiteController;
    }

    public void setSolicitudTramiteController(
            SolicitudTramiteController solicitudTramiteController) {
        this.solicitudTramiteController = solicitudTramiteController;
    }

}