/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.qsoft.wmp.services.rest;

import com.qsoft.dao.exception.DaoException;
import com.qsoft.util.constantes.CodigoRespuesta;
import com.qsoft.util.constantes.ErrorTipo;
import com.qsoft.util.ms.pojo.HeaderMS;
import com.qsoft.erp.constantes.DominioConstantes;
import com.qsoft.erp.constantes.EntidadEnum;
import com.qsoft.erp.dominio.AccionGenerica;
import com.qsoft.erp.dominio.exception.DominioExcepcion;
import com.qsoft.erp.dominio.util.AuditoriaUtil;
import com.qsoft.erp.dto.AuditoriaDTO;
import com.qsoft.wmp.services.util.ServiceUtil;
import com.qsoft.wmp.services.xsd.EntradaAccion;
import com.qsoft.wmp.services.xsd.SalidaAccion;
import com.stripe.exception.StripeException;
import java.io.IOException;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

/**
 * REST Web Service
 *
 * @author james
 */
@Path("accion")
public class AccionResource {

    @Inject
    private AccionGenerica accion;

    @Inject
    private AuditoriaUtil auditoria;
    
    @Context
    private HttpServletRequest request;

    @PostConstruct
    public void postConstructor() {
    }

    /**
     *
     * @return an instance of java.lang.String
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public SalidaAccion getJson() {
        SalidaAccion salida = ServiceUtil.crearSalidaAccionError(CodigoRespuesta.CODIGO_ERROR_GENERICO,
                "Acción no soportada por favor ejecute la consulta via POST");
        return salida;
    }

    /**
     * PUT method for updating or creating an instance of ConsultaResource
     *
     * @param entrada
     * @return
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public SalidaAccion postJson(EntradaAccion entrada) {
        SalidaAccion salida = null;
        Long time = System.currentTimeMillis();
        EntidadEnum entidad = null;
        if (entrada == null) {
            salida = ServiceUtil.crearSalidaAccionError(ErrorTipo.WARNING, CodigoRespuesta.CODIGO_IN_NULO, "La entrada no puede ser nula");
        } else {
            AuditoriaDTO dto = ServiceUtil.crearAuditoria(entrada.getHeaderIn(), entrada.getBodyIn().getEntidad(),
                    super.getClass().getName() + ".posJson", request.getRequestURL().toString(),
                    AccionGenerica.class.getName() + ".accionGenerica", ServiceUtil.REQUEST,
                    "" + entrada.getBodyIn().getTipoAccion(), 0, ServiceUtil.getJson(entrada));
            this.auditoria.AddAuditoria(dto);
            entidad = Enum.valueOf(EntidadEnum.class, entrada.getBodyIn().getEntidad());
            if (entidad == null) {
                salida = ServiceUtil.crearSalidaAccionError(ErrorTipo.ERROR, CodigoRespuesta.CODIGO_VALOR_NULO, "No se puede identificar la entidad a la cual se desea acceder");
            } else {
                try {
                    salida = ejecutarAccion(entrada, entidad);
                } catch (DominioExcepcion ex) {
                    salida = ServiceUtil.crearSalidaAccionError(ex.getTipo(), ex.getCodigo(), ex.getMensaje());
                } catch (Exception ex) {
                    System.out.println("============ ERROR NO CONTROLADO ==============");
                    ex.printStackTrace(System.err);
                    String msg = getCauses(ex, new StringBuilder());
                    if (msg.contains("Duplicate entry")) {
                        salida = ServiceUtil.crearSalidaAccionError(ErrorTipo.ERROR, CodigoRespuesta.CODIGO_ERROR_GUARDA_BDD,
                                "Error el registro " + entrada.getBodyIn().getEntidad() + " ya existe en la Base de datos");
                    } else {
                        salida = ServiceUtil.crearSalidaAccionError(ErrorTipo.ERROR, CodigoRespuesta.CODIGO_ERROR_GENERICO, "ERROR NO CONTROLADO: " + msg);
                    }
                }
            }
        }
        time = System.currentTimeMillis() - time;
        AuditoriaDTO dto = ServiceUtil.crearAuditoria(salida.getHeaderOut(), entidad.name(),
                super.getClass().getName() + ".posJson", request.getRequestURL().toString(),
                AccionGenerica.class.getName() + ".accionGenerica", ServiceUtil.RESPONSE,
                "", time.intValue(), ServiceUtil.getJson(salida.getError()));
        this.auditoria.AddAuditoria(dto);
        return salida;
    }

    /**
     * @param e
     * @param build
     * @return
     */
    private String getCauses(Throwable e, StringBuilder build) {
        build.append("\n").append(e.toString());
        for (Throwable t : e.getSuppressed()) {
            System.out.println("SUPRESS  =====> " + t);
            build.append("\n").append(t.toString());
            getCauses(t, build);
        }
        System.out.println("CAUSE =====> " + e);
        if (e.getCause() != null) {
            getCauses(e.getCause(), build);
        }
        return build.toString();
    }

    /**
     * Ejecuta la accion
     *
     * @param entrada
     * @param entidad
     * @return
     * @throws DominioExcepcion
     */
    public SalidaAccion ejecutarAccion(EntradaAccion entrada, EntidadEnum entidad) throws DominioExcepcion, IOException, StripeException, DaoException {
        List<Object> resultado = accion.accionGenerica(entrada.getHeaderIn(), entidad, entrada.getBodyIn().getEntidades(), entrada.getBodyIn().getTipoAccion());
        String msg = "A continuacion se muestra el resultado de la accion.";
        HeaderMS header = entrada.getHeaderIn();
        header.setFechaHora(DominioConstantes.getDateTime());
        SalidaAccion salida = ServiceUtil.crearSalidaAccionOk(header, msg, resultado);
        return salida;
    }

}
