package com.fp.armas.rules.save.solicitudimportacion;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.fp.common.helper.Constant;
import com.fp.dto.rules.TransactionRule;
import com.fp.dto.save.SaveRequest;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.commondb.helper.FormatDates;
import com.fp.persistence.parmas.fun.TarmCarga;
import com.fp.persistence.parmas.fun.TarmCargaDetalle;
import com.fp.persistence.parmas.fun.TarmRegistroArmas;
import com.fp.persistence.parmas.fun.TarmTotalPersona;
import com.fp.persistence.parmas.param.TarmTipoArmaExplosivo;
import com.fp.persistence.parmas.soli.TarmArmas;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.parmas.soli.TarmSolicitudArmas;
import com.fp.persistence.parmas.soli.TarmSolicitudArmasKey;
import com.fp.persistence.pcustomer.gene.TcustPersonAddress;
import com.fp.sessionbeans.helper.Sequence;

/**
 * Realiza el mantenimiento de totales y maestro detalle del ingreso
 * @author fpazmino
 *
 */
public class PreviaImportacionDesgloce extends TransactionRule {

	
	private static final long serialVersionUID = 1L;
	private static final String JPQL_TIPOARMAEXPLOSIVO = "from TarmTipoArmaExplosivo tae" + " where tae.pk = :pk";
	private static final String JPQL_DIRECCION_PRINCIPAL="from TcustPersonAddress o WHERE o.pk.personcode=:personcode AND o.pk.dateto=:dateto AND o.principal=:principal";
	private static final String JPQL_ULTIMO_TOTAL_PERSONA = "from TarmTotalPersona o where o.personcodigo=:personcode AND o.clase=:clase AND o.tipoarmaexplosivo=:tipoarmaexplosivo AND o.unidadmedidapeso=:unidadmedidapeso AND o.fecha = (Select max(tp.fecha) from TarmTotalPersona tp where tp.personcodigo=:personcode AND tp.clase=:clase AND tp.tipoarmaexplosivo=:tipoarmaexplosivo AND tp.unidadmedidapeso=:unidadmedidapeso)";
	private static final String JPQL_ARMAS_CARGA_IMPORTACION = "from TarmArmas arm WHERE arm.pk in (Select cd.carma from TarmCargaDetalle cd where cd.ccarga = (Select c.pk from TarmCarga c where c.aucp=:aucp))";
	private static final String JPQL_CARGA = "from TarmCarga c WHERE c.aucp=:aucp";
	
	/**
	 * Completa desgloce de las armas de fuego y armas no letales. Afecta totales.
	 */
	@Override
	@SuppressWarnings("unchecked")
	public SaveRequest normalProcess(SaveRequest pSaveRequest) throws Exception {
		try {
			System.out.println("INGRESA A DESGLOCE DESADUANIZACION");
			Boolean requiereDesgloce = (Boolean) pSaveRequest.get("REQUIEREDESGLOCE");
			if(requiereDesgloce){
				EntityManager pEntityManager=PersistenceHelper.getEntityManager();
				TarmSolicitud solicitud = (TarmSolicitud) pSaveRequest.get("SOLICITUD");
				String aucp = solicitud.getAucp();
				List<TarmArmas> listaArmas=consultarArmasPorAucp(pEntityManager, aucp);
				String personcode = solicitud.getPersoncode().toString();
				// Actualiza el estado de desaduanizacion
				TarmCarga carga = actualizarEstadoCarga(pEntityManager, aucp);
				// Desglozar armas
				for(TarmArmas armasObj : listaArmas){
					TarmTipoArmaExplosivo tipoArmaExplosivoObj = findTipoArmaExpByCTipoArmaExp(pEntityManager, armasObj.getCtipoarmaexplosivo());
					Integer cantidadArmas = armasObj.getCantidad();
					// Afectacion en la tabla de totales
					actualizarTotalPersona(pEntityManager, tipoArmaExplosivoObj, personcode, new BigDecimal(cantidadArmas));
					// 0010000001	ARMA DE FUEGO, 0010000008	ARMAS NO LETALES
					if((tipoArmaExplosivoObj.getClase().equals("0010000001") || tipoArmaExplosivoObj.getClase().equals("0010000008")) && armasObj.getCantidad()>1){
						// Grabamos 1 registro un total de N veces segun determine la cantidad					
						for(int i=0; i<cantidadArmas-1;i++){
							generarArma(pEntityManager,armasObj, carga, solicitud);
						}	
						armasObj.setCantidad(1);
						pEntityManager.merge(armasObj);
					}				
				}
				pEntityManager.flush();
			}			
		} catch (Exception e) {
			return pSaveRequest;
			// TODO: handle exception
		}
		return pSaveRequest;		
	}
	
	@Override
	public SaveRequest reverseProcess(SaveRequest arg0) throws Exception {

		return arg0;
	}
	
	
	
	public TarmRegistroArmas generarRegistroArmas(EntityManager pEntityManager, TarmRegistroArmas registroArmas){
		try {
			// Ingresa codigo de registro
			TarmRegistroArmas registroArmasNew = new TarmRegistroArmas();
			registroArmasNew.setPk(generarCRegistroArmas(pEntityManager));
			registroArmasNew.setAeropuertopuerto(registroArmas.getAeropuertopuerto());
			registroArmasNew.setDui(registroArmas.getDui());
			registroArmasNew.setFabricante(registroArmas.getFabricante());
			registroArmasNew.setFcreacion(registroArmas.getFcreacion());
			registroArmasNew.setFechasolicitud(registroArmas.getFechasolicitud());
			registroArmasNew.setPaisorigen(registroArmas.getPaisorigen());
			registroArmasNew.setPersoncode(registroArmas.getPersoncode());
			registroArmasNew.setSolicitudnum(registroArmas.getSolicitudnum());
			registroArmasNew.setTiporegistro(registroArmas.getTiporegistro());
			registroArmasNew.setTiporegistrocodigo(registroArmas.getTiporegistrocodigo());
			registroArmasNew.setTotalfob(registroArmas.getTotalfob());
			registroArmasNew.setTramite(registroArmas.getTramite());		
			pEntityManager.persist(registroArmasNew);
			return registroArmasNew;
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}         
	}
	
	public Long generarCRegistroArmas(EntityManager pEntityManager){ //, TarmRegistroArmas registroArmas, String tipoRegistro
		try {
			Sequence sequence = new Sequence();
			String cRegistro = sequence.getNextValue("CREGISTRO").toString();
			return Long.parseLong(cRegistro);        
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}         
	}
	
	public void generarArma(EntityManager pEntityManager, TarmArmas armaParam, TarmCarga carga, TarmSolicitud solicitud){
		try {
			TarmArmas armaNew = new TarmArmas();
			String carma = getCodigoArmas();
			armaNew.setCantidad(1);
			armaNew.setCantoncode(armaParam.getCantoncode());
			armaNew.setCitycode(armaParam.getCitycode());
			armaNew.setCodigoarma(carma);
			armaNew.setColor(armaParam.getColor());
			armaNew.setColorcodigo(armaParam.getColorcodigo());
			armaNew.setCountrycode(armaParam.getCountrycode());
			armaNew.setCpaisorigen(armaParam.getCpaisorigen());
			armaNew.setCregistro(armaParam.getCregistro());
			armaNew.setCtipoarmaexplosivo(armaParam.getCtipoarmaexplosivo());
			armaNew.setDireccion(armaParam.getDireccion());
			armaNew.setEstado(armaParam.getEstado());
			armaNew.setEstadocodigo(armaParam.getEstadocodigo());
			armaNew.setFdesaduanizacion(armaParam.getFdesaduanizacion());
			armaNew.setFechacaducidad(armaParam.getFechacaducidad());
			armaNew.setFecharegistro(armaParam.getFecharegistro());
			armaNew.setFemisionpermiso(armaParam.getFemisionpermiso());
			armaNew.setLote(armaParam.getLote());
			armaNew.setMarca(armaParam.getMarca());
			armaNew.setMarcacodigo(armaParam.getMarcacodigo());
			armaNew.setModelo(armaParam.getModelo());
			armaNew.setParroquiacode(armaParam.getParroquiacode());
			armaNew.setPeso(armaParam.getPeso());
			armaNew.setPk(carma);
			armaNew.setProvincecode(armaParam.getProvincecode());
			armaNew.setSeriecanon(armaParam.getSeriecanon());
			armaNew.setTipofabricacion(armaParam.getTipofabricacion());
			armaNew.setTipofabricacioncodigo(armaParam.getTipofabricacioncodigo());
			armaNew.setUnidadmedidacantidad(armaParam.getUnidadmedidacantidad());
			armaNew.setUnidadmedidacantidadcodigo(armaParam.getUnidadmedidacantidadcodigo());
			armaNew.setValorAux(armaParam.getValorAux());				
			pEntityManager.persist(armaNew);	
			// Actualizamos la tabla TarmCargadetalle
			TarmCargaDetalle cargaDetalle = new TarmCargaDetalle();
			cargaDetalle.setPk(getCodigoCargaDetalle());
			cargaDetalle.setCarma(armaNew.getPk());
			cargaDetalle.setCcarga(carga.getPk());
			pEntityManager.persist(cargaDetalle);
			// Actualizamos la tabla tarmsolicitudarma
			TarmSolicitudArmas solicitudArmas = new TarmSolicitudArmas();
			TarmSolicitudArmasKey solicitudArmasKey = new TarmSolicitudArmasKey();
			solicitudArmasKey.setPersoncode(carga.getPersoncode());
			solicitudArmasKey.setCarma(carma);
			solicitudArmasKey.setCsolicitud(solicitud.getPk());
			solicitudArmas.setPk(solicitudArmasKey);
			pEntityManager.persist(solicitudArmas);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}         
	}
	
	/**
	 * Encuentra una lista de articulos por codigo de importacion (aucp)
	 * @param pEntityManager
	 * @param aucp
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static List<TarmArmas> consultarArmasPorAucp(EntityManager pEntityManager, String aucp) throws Exception {
	    Query qry = pEntityManager.createQuery(PreviaImportacionDesgloce.JPQL_ARMAS_CARGA_IMPORTACION);
	    qry.setParameter("aucp", aucp);
	    List<TarmArmas>resultList = qry.getResultList();	    
	    if(resultList!=null && resultList.size()>0){
	    	return (List<TarmArmas>) qry.getResultList();
	    }else{
	    	return null;
	    }	    
	}
	
	/**
	 * Encuentra una lista de articulos por codigo de importacion (aucp)
	 * @param pEntityManager
	 * @param aucp
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static TarmCarga actualizarEstadoCarga(EntityManager pEntityManager, String aucp) throws Exception {
	    Query qry = pEntityManager.createQuery(PreviaImportacionDesgloce.JPQL_CARGA);
	    qry.setParameter("aucp", aucp);
	    List<TarmCarga>resultList = qry.getResultList();	    
	    TarmCarga carga = null;
	    if(resultList!=null && resultList.size()>0){
		    carga = resultList.get(0);
		    carga.setEsdesaduanizado("S");
		    pEntityManager.merge(carga);    	
	    }
	    return carga;
	}
	
	
	/**
	 * Encuentra una lista de tipo de armas y explosivos
	 * @param pEntityManager
	 * @param pk
	 * @return
	 * @throws Exception
	 */
	public static TarmTipoArmaExplosivo findTipoArmaExpByCTipoArmaExp(EntityManager pEntityManager, String pk) throws Exception {
	    Query qry = pEntityManager.createQuery(PreviaImportacionDesgloce.JPQL_TIPOARMAEXPLOSIVO);
	    qry.setParameter("pk", pk);
	    List<TarmTipoArmaExplosivo>resultList = qry.getResultList();	    
	    if(resultList!=null && resultList.size()>0){
	    	return (TarmTipoArmaExplosivo) qry.getResultList().get(0);
	    }else{
	    	return null;
	    }	    
	}
	
	/**
	 * Actualizar tabla TarmTotalPersona
	 * @param pEntityManager
	 * @param EntityManager pEntityManager, TarmTipoArmaExplosivo tipoArmaExplosivo, String personcode, BigDecimal cantidadPeso
	 * @return void
	 * @throws Exception
	 */
	public void actualizarTotalPersona(EntityManager pEntityManager, TarmTipoArmaExplosivo tipoArmaExplosivo, String personcode, BigDecimal cantidadPeso) throws Exception {
	    Query qry = pEntityManager.createQuery(PreviaImportacionDesgloce.JPQL_ULTIMO_TOTAL_PERSONA);
	    qry.setParameter("personcode", Integer.valueOf(personcode));
	    qry.setParameter("clase", tipoArmaExplosivo.getClase());
	    qry.setParameter("tipoarmaexplosivo", tipoArmaExplosivo.getTipoarmaexplosivo());
	    qry.setParameter("unidadmedidapeso", tipoArmaExplosivo.getUnidadmedidapeso());	    
	    List<TarmTotalPersona>resultList = qry.getResultList();	
	    String cTotalPersona = getCodigoTotalPersona();
	    if(resultList!=null && resultList.size()>0){
	    	TarmTotalPersona totalPersonaAnterior = resultList.get(0);
	    	// Actualiza la tabla de totales cuando existen datos anteriores
	    	TarmTotalPersona totalPersona = new TarmTotalPersona();
	    	totalPersona.setClase(tipoArmaExplosivo.getClase());
	    	totalPersona.setClasecodigo("CLASE");
	    	totalPersona.setTipoarmaexplosivo(tipoArmaExplosivo.getTipoarmaexplosivo());
	    	totalPersona.setTipoarmaexplosivocodigo("TIPOARMAEXPLOSIVO");
	    	totalPersona.setUnidadmedidapeso(tipoArmaExplosivo.getUnidadmedidapeso());
	    	totalPersona.setUnidadmedidapesocodigo("UNIDADMEDIDA");
	    	totalPersona.setPersoncodigo(Integer.valueOf(personcode));	    	
	    	totalPersona.setSaldoanterior(totalPersonaAnterior.getTotal());
	    	totalPersona.setCantidadmovimiento(cantidadPeso);
	    	totalPersona.setTotal(totalPersonaAnterior.getTotal().add(cantidadPeso));
	    	totalPersona.setFecha(new Timestamp(new Date().getTime()));
	    	totalPersona.setIngresoegreso("ING");
	    	totalPersona.setIngresoegresocodigo("ESINGRESOEGRESO");	    	
	    	totalPersona.setPk(cTotalPersona);
	    	pEntityManager.detach(totalPersona);
	    	pEntityManager.persist(totalPersona);
	    	System.out.println("Saldoanterior,"+totalPersona.getSaldoanterior()+",Cantidadmovimiento,"+totalPersona.getCantidadmovimiento()+",Total,"+totalPersona.getTotal()+",fecha,"+totalPersona.getFecha());
	    }else{
	    	// Actualiza la tabla de totales cuando NO existen datos anteriores
	    	TarmTotalPersona totalPersona = new TarmTotalPersona();
	    	totalPersona.setClase(tipoArmaExplosivo.getClase());
	    	totalPersona.setClasecodigo("CLASE");
	    	totalPersona.setTipoarmaexplosivo(tipoArmaExplosivo.getTipoarmaexplosivo());
	    	totalPersona.setTipoarmaexplosivocodigo("TIPOARMAEXPLOSIVO");
	    	totalPersona.setUnidadmedidapeso(tipoArmaExplosivo.getUnidadmedidapeso());
	    	totalPersona.setUnidadmedidapesocodigo("UNIDADMEDIDA");
	    	totalPersona.setPersoncodigo(Integer.valueOf(personcode));
	    	totalPersona.setSaldoanterior(BigDecimal.ZERO);
	    	totalPersona.setCantidadmovimiento(cantidadPeso);
	    	totalPersona.setTotal(cantidadPeso);
	    	totalPersona.setFecha(new Timestamp(new Date().getTime()));
	    	totalPersona.setIngresoegreso("ING");
	    	totalPersona.setIngresoegresocodigo("ESINGRESOEGRESO");
	    	totalPersona.setPk(cTotalPersona);
	    	pEntityManager.persist(totalPersona);
	    	System.out.println("Saldoanterior,"+totalPersona.getSaldoanterior()+",Cantidadmovimiento,"+totalPersona.getCantidadmovimiento()+",Total,"+totalPersona.getTotal()+",fecha,"+totalPersona.getFecha());
	    }	    
	}	
	
	/**
	 * Obtiene la direcci&oacute;n principal de la persona
	 * @param personcode
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public TcustPersonAddress obtenerDireccionPrincipal(Integer personcode) throws Exception {
		TcustPersonAddress tcustPersonAddress = null;
		Query query = PersistenceHelper.getEntityManager().createQuery(JPQL_DIRECCION_PRINCIPAL);
		query.setParameter("personcode", personcode);
		query.setParameter("dateto", FormatDates.getDefaultExpiryTimestamp());
		query.setParameter("principal", Constant.STR_Y);
		List<TcustPersonAddress> ltcustPersonAddresses = query.getResultList();
		if(ltcustPersonAddresses != null && !ltcustPersonAddresses.isEmpty()){
			tcustPersonAddress = ltcustPersonAddresses.iterator().next();
		}
		return tcustPersonAddress;
	}
  
    /**
     * Metodo que devuelve el codigo de un arma
     * @return
     * @throws Exception
     */
    private String getCodigoArmas() throws Exception {
        Sequence sequence = new Sequence();
        String codigoArma = sequence.getNextValue("CARMA").toString();        
        return codigoArma;    	
    }
    
    /**
     * Metodo que devuelve el codigo de un totalpersona
     * @return
     * @throws Exception
     */
    private String getCodigoTotalPersona() throws Exception {
        Sequence sequence = new Sequence();
        String cTotalPersona = sequence.getNextValue("TARMTOTALPERSONA").toString();        
        return cTotalPersona;    	
    }
    
    /**
     * Metodo que devuelve el codigo de una carga detalle
     * @return
     * @throws Exception
     */
    private String getCodigoCargaDetalle() throws Exception {
        Sequence sequence = new Sequence();
        String cCarga = sequence.getNextValue("CARGADETALLE").toString();        
        return cCarga;    	
    }


}