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

import java.math.BigDecimal;
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 java.util.Map;

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 org.primefaces.context.RequestContext;

import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.query.Filter;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.armas.parametros.CentroControlArmasController;
import com.fp.frontend.controller.armas.parametros.TarmCentroControlJurController;
import com.fp.frontend.controller.pcustomer.PersonAddressController;
import com.fp.frontend.controller.pcustomer.PersonDetailController;
import com.fp.frontend.controller.pgeneral.date.TgeneNotAccountingDayController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.controller.pgeneral.gene.ParametersController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.frontend.utility.MsgControlArmas;
import com.fp.frontend.utility.MsgGeneral;
import com.fp.persistence.parmas.param.TarmCentroControl;
import com.fp.persistence.parmas.param.TarmCentroControlJur;
import com.fp.persistence.parmas.param.TarmTramite;
import com.fp.persistence.parmas.param.TarmTramitesAtendidos;
import com.fp.persistence.parmas.soli.TarmArmas;
import com.fp.persistence.parmas.soli.TarmDocumentoHabilitante;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.parmas.soli.TarmSolicitudArmas;
import com.fp.persistence.parmas.soli.TarmSolicitudTramite;
import com.fp.persistence.pcustomer.gene.TcustPersonAddress;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;

@SuppressWarnings("serial")
@ManagedBean
@ViewScoped
public class NotificarEmisionDocumentoController extends AbstractController<TarmTramitesAtendidos> {

    private TgeneCatalogDetail detallecatalogo = new TgeneCatalogDetail();
    private TgeneCatalogDetail detallecatalogoTipoTramite = new TgeneCatalogDetail();
    private TgeneCatalogDetail usoActividad = new TgeneCatalogDetail();
    private TgeneCatalogDetail identificacion = new TgeneCatalogDetail();
    private TgeneCatalogDetail estadotramite = new TgeneCatalogDetail();
    private TarmSolicitudTramite solicitudTramite = new TarmSolicitudTramite();
    private TarmCentroControl centroControl = new TarmCentroControl();
    private TarmTramite tramite = new TarmTramite();
    private TarmSolicitud solicitud = new TarmSolicitud();
    private String codigoSolicitud = "";
    private boolean habilitarGrabar = false;
    private boolean habilitarEnviar = false;
    private boolean habilitarGeneraFecha;

    Date fechaNotificacion = null;

    @ManagedProperty(value = "#{solicitudTramiteController}")
    private SolicitudTramiteController solicitudTramiteController;

    /**
     * Controlador que maneja armas
     */
    @ManagedProperty(value = "#{armasController}")
    private ArmasController armas;

    public NotificarEmisionDocumentoController() throws Exception {
        super(TarmTramitesAtendidos.class);
    }

    private void init() {
        try {
            recperpage = 15; // Cambiar al # reg a mirar.
            lrecord = new ArrayList<>();
            beanalias = "NOTIFICAREMISIONDOCUMENTO";
            this.record = new TarmTramitesAtendidos();
            record.isnew = true;
            habilitarGeneraFecha = false;
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    @PostConstruct
    private void postconstruct() {
        startQuery();
        this.init();
        cargarDatos();
    }

    public void startQuery() {
        try {
            this.pasteBpmScreenParameters();
            //xpathflujo=super.getMfilters().get("xpath");//"cm:Decomiso/cm:A-2014/cm:M-10/cm:ENV-000000319/cm:ENV-000000319.pdf";//
            codigoSolicitud = super.getMfilters().get("csolicitud");
            super.getMfilters().clear();
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void save() {
        try {
            if (fechaNotificacion == null) {
                MessageHelper.setMessageError(MsgControlArmas.getProperty("msg_error_camponotificacion"));
                return;
            }

            record.setCcentrocontrol(centroControl.getPk());
            record.setCtramite(tramite.getPk());

            java.sql.Date sFechaActual = new java.sql.Date(Calendar.getInstance().getTimeInMillis());

            Calendar cal = Calendar.getInstance();
            cal.setTime(fechaNotificacion);
            java.sql.Date sFechaNotificacion = new java.sql.Date(cal.getTimeInMillis());

            record.setFechaatencion(sFechaNotificacion);
            record.setFecharegistro(sFechaActual);

            this.update();

            aprobarTramite();

            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            Request request = callerhelper.getRequest();

            DtoSave dtosave = super.getDtoSave();
            dtosave.setReturnpk(true);
            dtosave.setPosition(1);
            msave.put(beanalias, dtosave);

            request.setSaveTables(msave);
            Response resp = callerhelper.executeSave(request);

            habilitarEnviar = true;
            habilitarGrabar = false;

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
                RequestContext.getCurrentInstance().execute(
                        "Maia.refreshusertasks()");
                habilitarGeneraFecha = true;
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    /**
     * Metodo para finalizar la tarea del flujo
     */
    public void completarTarea() {

        try {
            Request request = callerhelper.getRequest();
            // limpiar request para finalizar la tarea.
            super.cleanRequest(request);
            // validamos si cargamos los datos cuando apruebe
            Map<String, Object> datosmail = new HashMap<String, Object>();

            TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
            TcustPersonDetail persona = PersonDetailController.find(tsafeUserDetail.getPk().getPersoncode().toString());

            SimpleDateFormat sdf1 = new SimpleDateFormat(MsgGeneral.getProperty("dateformat"));
            datosmail.put("funcionario", persona == null ? "" : ((persona.getMilitarygrade() == null) ? "" : CatalogDetailController.findxCodigoCodcatalogo(persona.getMilitarygrade(), "MILITARYGRADE").getDescription()) + " " + persona.getName());
            datosmail.put("razons", (solicitud == null || solicitud.getModifiedData().get("nombre") == null) ? "" : solicitud.getModifiedData().get("nombre"));
            datosmail.put("tramite", solicitudTramite.getNumerotramite());
            datosmail.put("centrocontrol", (centroControl == null || centroControl.getNombreinstitucion() == null || centroControl.getNombreinstitucioncodigo() == null) ? "" : CatalogDetailController.findxCodigoCodcatalogo(centroControl.getNombreinstitucion(), centroControl.getNombreinstitucioncodigo()).getDescription());
            datosmail.put("fechanotificacion", sdf1.format(fechaNotificacion));

            TarmTramite tramite = TarmTramiteController.find(String.valueOf(solicitud.getCtramite()));
            datosmail.put("tipoTramite", (tramite == null || tramite.getModifiedData().get("tipotramite") == null) ? "" : tramite.getModifiedData().get("tipotramite"));
            datosmail.put("tipoAutorizacion", (tramite == null || tramite.getModifiedData().get("tipoautorizacion") == null) ? "" : tramite.getModifiedData().get("tipoautorizacion"));
            datosmail.put("usoactividad", (tramite == null || tramite.getModifiedData().get("usoactividad") == null) ? "" : tramite.getModifiedData().get("usoactividad"));
            datosmail.put("categoria", (tramite == null || tramite.getModifiedData().get("categoria") == null) ? "" : tramite.getModifiedData().get("categoria"));

            request.modifiedData().put("TID", tid);
            request.modifiedData().put("datosmail", datosmail);
            request.modifiedData().put("BPMStatus", bpmDataStatus == null ? "A" : bpmDataStatus); // A,D,R
            request.modifiedData().put("BPMObs", bpmDataComment == null ? "OK" : bpmDataComment);

            Response resp = callerhelper.executeSave(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                MessageHelper.setMessageInfo(resp);
                ponerEstadoRegistradoArmas();
                RequestContext.getCurrentInstance().execute("Maia.refreshusertasks()");
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void ponerEstadoRegistradoArmas() {
        try {
            Boolean grabarCambioEstado = Boolean.FALSE;
            List<TarmSolicitudArmas> armasSolicitudLst = TarmSolicitudArmasController.findPorCSolicitud(codigoSolicitud);
            for (TarmSolicitudArmas armaSolicitud : armasSolicitudLst) {
                TarmArmas armaObj = ArmasController.findSimple(armaSolicitud.getPk().getCarma());
                if (armaObj.getEstado().equals("PREG")) {
                    armaObj.setIsnew(false);
                    armaObj.setEstado("APTA");
                    armas.update(armaObj);
                    grabarCambioEstado = Boolean.TRUE;
                    // Cambia el estado del arma en caso de existir un estado posterior en el historial
                    TarmArmas armaUltimoEstadoObj = ArmasController.findXCodigoArma(armaObj.getCodigoarma());
                    if (armaUltimoEstadoObj != null) {
                        armaUltimoEstadoObj.setIsnew(false);
                        armaUltimoEstadoObj.setEstado("APTA");
                        armas.update(armaUltimoEstadoObj);
                    }
                }
            }
            if (grabarCambioEstado) {
                armas.save();
            }

            DtoSave dtoArmas = armas.getDtoSave();
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            Request request = callerhelper.getRequest();
            super.cleanRequest(request);
            msave.put(armas.getBeanalias(), dtoArmas); // adicionar metadata de mantenimiento para cada tabla.

            request.setSaveTables(msave);
            Response resp = callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                armas.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
            } else {
                MessageHelper.setMessageError(resp);
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void querydatabase() {

        try {
            if (fechaNotificacion == null) {
                return;
            }

            DtoQuery dto = super.getDtoQuery(true);
            Filter filtro = new Filter();
            Calendar cal = Calendar.getInstance();
            cal.setTime(fechaNotificacion);
            java.sql.Date sFechaNotificacion = new java.sql.Date(cal.getTimeInMillis());

            dto.addFiltro(new Filter("fechaatencion", ">=", sFechaNotificacion.toString()));
            dto.addFiltro(filtro);
            HashMap<String, DtoQuery> mtables = new HashMap<String, DtoQuery>();
            mtables.put(beanalias, dto); // permite adicionar mas de una tabla.
            Request request = this.callerhelper.getRequest();
            request.setQueryTables(mtables);

            Response resp = this.callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                this.lrecord = new ArrayList<TarmTramitesAtendidos>();
                MessageHelper.setMessageError(resp);
            } else {
                this.lrecord = (List<TarmTramitesAtendidos>) resp.get(beanalias);
                super.postQuery(this.lrecord);
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }

    }

    /**
     * Metodo para cargar los datos iniciales
     */
    private void cargarDatos() {
        try {
            solicitud = SolicitudArmasController.find(codigoSolicitud);
            solicitudTramite = TarmSolicitudTramiteController.findPorCSolicitud(codigoSolicitud);
            if (solicitudTramite != null && solicitudTramite.getPk().getCtramite() != null) {
                tramite = TarmTramiteController.find(solicitudTramite.getPk().getCtramite().toString());
                estadotramite = (solicitudTramite.getEstadotramite() == null || solicitudTramite.getEstadotramitecodigo() == null) ? null : CatalogDetailController.findxCodigoCodcatalogo(solicitudTramite.getEstadotramite(), solicitudTramite.getEstadotramitecodigo());
            }

            if (tramite != null) {
                detallecatalogo = (tramite.getCategoria() == null || tramite.getCategoriacodigo() == null) ? null : CatalogDetailController.findxCodigoCodcatalogo(tramite.getCategoria(), tramite.getCategoriacodigo());
                detallecatalogoTipoTramite = (tramite.getTipoautorizacion() == null || tramite.getTipoautorizacioncodigo() == null) ? null : CatalogDetailController.findxCodigoCodcatalogo(tramite.getTipoautorizacion(), tramite.getTipoautorizacioncodigo());
                usoActividad = (tramite.getUsoactividad() == null || tramite.getUsoactividadcodigo() == null) ? null : CatalogDetailController.findxCodigoCodcatalogo(tramite.getUsoactividad(), tramite.getUsoactividadcodigo());
            }

            if (this.getLoginController() != null && 108 == this.getLoginController().getRequest().getTransactionCode() && "30".equals(getLoginController().getRequest().getTransactionModule())) {
                TarmDocumentoHabilitante documentohabilitante = DocumentoHabilitanteController.findPorSolicitud(codigoSolicitud);
                fechaNotificacion = documentohabilitante.getFechaemision();
            }
            obtenerCentroControl();
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    private void obtenerCentroControl() throws Exception {
//    	TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
//    	PersonAddressController personAddressController = new PersonAddressController();
//        TcustPersonAddress tcustPersonAddres=personAddressController.findPrincipal(tsafeUserDetail.getPk().getPersoncode().toString());
//        TarmCentroControlJur centroControlJur= TarmCentroControlJurController.findxProvincia(tcustPersonAddres.getProvincecode());
        centroControl = CentroControlArmasController.findPorCodigo(solicitud.getCcentrocontrol());
        //institucionCentroControl = CatalogDetailController.findxCodigoCodcatalogo( centroControl.getNombreinstitucion(), centroControl.getNombreinstitucioncodigo()).getDescription();
    }

    /**
     * Metodo para filtrar por centro de control
     *
     * @param ccentroControl
     * @return
     */
    public List<TarmTramitesAtendidos> findPorCentroControlFechaAtencion(String ccentroControl) {
        try {
            this.init();
            this.recperpage = 15;
            this.addFilter("ccentrocontrol", ccentroControl);
            this.querydatabase();
            if ((this.lrecord != null) && !this.lrecord.isEmpty()) {
                return this.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    @Override
    public void query() throws Exception {
        MessageHelper.setMessageError("msg_notQuery");
        super.query();
    }

    @Override
    public void next() throws Exception {
        // TODO Auto-generated method stub
        super.next();
    }

    /**
     * Metodo raiz para generar la fecha de notificacion a partir de la fecha
     * actual
     */
    public void generarFecha() {
        Calendar calendario = Calendar.getInstance();
        calendario.setTime(new Date());
        calendario.add(Calendar.DAY_OF_YEAR, 0);//adiciona los dias a partir de los cuales debe empezar la notificacion
        generarFecha(calendario.getTime());
    }

    /**
     * Metodo recursivo para generar una fecha de Notificacion, siempre y cuando
     * la fecha se encuentre disponible para ese centro de control
     *
     * @param fecha
     */
    public void generarFecha(Date fecha) {
        fechaNotificacion = TgeneNotAccountingDayController.isfechalaboral(fecha);
        List<TarmCentroControl> listaCentroControl = CentroControlArmasController.find(solicitud.getCcentrocontrol());
        int tramitesPorDia = 0;

        if (listaCentroControl != null && !listaCentroControl.isEmpty()) {
            centroControl = listaCentroControl.get(0);
            if (listaCentroControl.get(0).getTramitespordia() != null) {
                tramitesPorDia = centroControl.getTramitespordia().intValue();
            }
        }
        Calendar fNotificacion = Calendar.getInstance();
        fNotificacion.setTime(fechaNotificacion);

        Calendar fActualUnDia = Calendar.getInstance();
        fActualUnDia.setTime(new Date());
        fActualUnDia.add(Calendar.DAY_OF_YEAR, 1);
        long fechaDiferencia = (fActualUnDia.getTimeInMillis() - fNotificacion.getTimeInMillis()) / (24 * 60 * 60 * 1000);

        List<TarmTramitesAtendidos> listaTramitesAtendidos = findPorCentroControlFechaAtencion(solicitud.getCcentrocontrol());

        if (fechaDiferencia == 1L || fechaDiferencia == 0 || (listaTramitesAtendidos != null && !listaTramitesAtendidos.isEmpty() && tramitesPorDia > 0 && listaTramitesAtendidos.size() >= tramitesPorDia)) {
            Calendar calendario = Calendar.getInstance();
            calendario.setTime(fechaNotificacion);
            calendario.add(Calendar.DAY_OF_YEAR, 1);
            generarFecha(calendario.getTime());
        }

        habilitarGrabar = true;

    }

    /**
     * Metodo para anular el tramite
     *
     * @throws Exception
     */
    private void aprobarTramite() throws Exception {
        solicitudTramite = solicitudTramiteController.findByCSolicitud(codigoSolicitud);
        solicitudTramiteController.setRecord(solicitudTramite);
        solicitudTramiteController.getRecord().setEstadotramite("APB");
        solicitudTramiteController.getRecord().setEstadotramitecodigo("ESTADOSOLICITUD");
        solicitudTramiteController.update();
        solicitudTramiteController.save();
    }

    public SolicitudTramiteController getSolicitudTramiteController() {
        return solicitudTramiteController;
    }

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

    public TgeneCatalogDetail getDetallecatalogo() {
        return detallecatalogo;
    }

    public void setDetallecatalogo(TgeneCatalogDetail detallecatalogo) {
        this.detallecatalogo = detallecatalogo;
    }

    public TgeneCatalogDetail getDetallecatalogoTipoTramite() {
        return detallecatalogoTipoTramite;
    }

    public void setDetallecatalogoTipoTramite(
            TgeneCatalogDetail detallecatalogoTipoTramite) {
        this.detallecatalogoTipoTramite = detallecatalogoTipoTramite;
    }

    public TgeneCatalogDetail getUsoActividad() {
        return usoActividad;
    }

    public void setUsoActividad(TgeneCatalogDetail usoActividad) {
        this.usoActividad = usoActividad;
    }

    public TgeneCatalogDetail getIdentificacion() {
        return identificacion;
    }

    public void setIdentificacion(TgeneCatalogDetail identificacion) {
        this.identificacion = identificacion;
    }

    public TgeneCatalogDetail getEstadotramite() {
        return estadotramite;
    }

    public void setEstadotramite(TgeneCatalogDetail estadotramite) {
        this.estadotramite = estadotramite;
    }

    public TarmSolicitudTramite getSolicitudTramite() {
        return solicitudTramite;
    }

    public void setSolicitudTramite(TarmSolicitudTramite solicitudTramite) {
        this.solicitudTramite = solicitudTramite;
    }

    public TarmTramite getTramite() {
        return tramite;
    }

    public void setTramite(TarmTramite tramite) {
        this.tramite = tramite;
    }

    public TarmCentroControl getCentroControl() {
        return centroControl;
    }

    public void setCentroControl(TarmCentroControl centroControl) {
        this.centroControl = centroControl;
    }

    public TarmSolicitud getSolicitud() {
        return solicitud;
    }

    public void setSolicitud(TarmSolicitud solicitud) {
        this.solicitud = solicitud;
    }

    public Date getFechaNotificacion() {
        return fechaNotificacion;
    }

    public void setFechaNotificacion(Date fechaNotificacion) {
        this.fechaNotificacion = fechaNotificacion;
    }

    public boolean isHabilitarGrabar() {
        return habilitarGrabar;
    }

    public void setHabilitarGrabar(boolean habilitarGrabar) {
        this.habilitarGrabar = habilitarGrabar;
    }

    public boolean isHabilitarEnviar() {
        return habilitarEnviar;
    }

    public void setHabilitarEnviar(boolean habilitarEnviar) {
        this.habilitarEnviar = habilitarEnviar;
    }

    public boolean isHabilitarGeneraFecha() {
        return habilitarGeneraFecha;
    }

    public void setHabilitarGeneraFecha(boolean habilitarGeneraFecha) {
        this.habilitarGeneraFecha = habilitarGeneraFecha;
    }

    public ArmasController getArmas() {
        return armas;
    }

    public void setArmas(ArmasController armas) {
        this.armas = armas;
    }

}
