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

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
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.pcustomer.gene.TcustPersonAddress;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetailKey;
import com.fp.sessionbeans.helper.Sequence;

/**
 * Realiza el mantenimiento de totales y maestro detalle del ingreso
 * @author fpazmino
 *
 */
public class Inventarios 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)";
	
	/* (non-Javadoc)
	 * @see com.fp.dto.rules.TransactionRule#normalProcess(com.fp.dto.save.SaveRequest)
	 */
	@Override
	@SuppressWarnings("unchecked")
	public SaveRequest normalProcess(SaveRequest pSaveRequest) throws Exception {
		try {
			System.out.println("INGRESA A INGRESO DE INVENTARIOS");
			List<TarmArmas> listaArmas=(ArrayList<TarmArmas>)pSaveRequest.get("LISTAARMAS");
			List<TarmArmas> listaArmasEliminadas=(ArrayList<TarmArmas>)pSaveRequest.get("LISTAARMASELIMINADAS");
			String tipoRegistro = pSaveRequest.get("TIPOREGISTRO").toString();
			TarmRegistroArmas registroArmas=(TarmRegistroArmas)pSaveRequest.get("REGISTRO");
			String personCode=pSaveRequest.get("PERSONCODE").toString();
//			Boolean esNuevaImportacion=(Boolean) pSaveRequest.get("ESNUEVAIMPORTACION");
			EntityManager pEntityManager=PersistenceHelper.getEntityManager();
			if(registroArmas.isnew){
				generarRegistroArmas(pEntityManager,registroArmas,tipoRegistro);
			}
			System.out.println("tipoRegistro" + tipoRegistro);
			System.out.println("cantidad armas" + listaArmas.size());
			System.out.println("registroArmas" + registroArmas.getPk());
			// Registramos la carga
			TarmCarga carga = (TarmCarga)pSaveRequest.get("TARMCARGA");
			if(carga.isnew){
				carga.setTipocarga("INV");
				carga.setAucp(registroArmas.getSolicitudnum());			
				carga.setEsdesaduanizado("N");
				carga.setFecha(new Timestamp(new Date().getTime()));
				carga.setPersoncode(Integer.valueOf(personCode));
				carga.setCregistro(registroArmas.getPk());
				carga.setPk(getCodigoCarga());
				pEntityManager.persist(carga);
				pEntityManager.flush();					
			}
			TcustPersonAddress direccionPrincipal = obtenerDireccionPrincipal(Integer.valueOf(personCode));
			// Fecha de registro comun a todas las armas ingresadas
			java.sql.Date fechaRegistro = new java.sql.Date(new Date().getTime());
			for(TarmArmas armasObj : listaArmas){			
				TarmTipoArmaExplosivo tipoArmaExplosivoObj = findTipoArmaExpByCTipoArmaExp(pEntityManager, armasObj.getCtipoarmaexplosivo());
				if(armasObj.isnew){
					armasObj = generarArma(pEntityManager,registroArmas, armasObj, direccionPrincipal, tipoRegistro, armasObj.getCantidad(), fechaRegistro);
				}
				else{
					pEntityManager.merge(armasObj);
				}
				// Afectacion en la tabla de totales en el caso de registro de produccion
				if(tipoRegistro.equals("PRO")){
//					new BigDecimal(getCantidad()):armasObj.getPeso())
					BigDecimal cantidadPeso = BigDecimal.ZERO;
					TgeneCatalogDetailKey unidadPK= new TgeneCatalogDetailKey();
					unidadPK.setCatalog(tipoArmaExplosivoObj.getUnidadmedidapeso());
					unidadPK.setCatalogcode(tipoArmaExplosivoObj.getUnidadmedidapesocodigo());
					TgeneCatalogDetail unidadesCatalog = TgeneCatalogDetail.find(pEntityManager, unidadPK); 
					if(unidadesCatalog!=null && unidadesCatalog.getLegalcode().equals("CANTIDAD")){
						cantidadPeso = new BigDecimal(armasObj.getCantidad());
					}else{
						cantidadPeso = armasObj.getPeso();
					}
					actualizarTotalPersona(pEntityManager, tipoArmaExplosivoObj, personCode, cantidadPeso);
				}	
				// Registramos el detalle de la carga
				if(armasObj.isnew){
					TarmCargaDetalle cargaDetalle = new TarmCargaDetalle();
					cargaDetalle.setPk(getCodigoCargaDetalle());
					cargaDetalle.setCarma(armasObj.getPk());
					cargaDetalle.setCcarga(carga.getPk());
					pEntityManager.persist(cargaDetalle);
				}

			}
			
			for(TarmArmas armasObj : listaArmasEliminadas){	
				// Borra registro de la tabla TarmCargaDetalle
				Query q = pEntityManager.createQuery("delete from TarmCargaDetalle where ccarga= :ccarga and carma= :carma");
		        q.setParameter("ccarga", carga.getPk());
		        q.setParameter("carma", armasObj.getPk());
		        q.executeUpdate();
		        // Borra registro de la tabla TarmCargaDetalle
		        TarmArmas armaAEliminarse = TarmArmas.find(pEntityManager, armasObj.getPk());
		        pEntityManager.remove(armaAEliminarse);        
			}
		} catch (Exception e) {
			return pSaveRequest;
			// TODO: handle exception
		}
		return pSaveRequest;		
	}
	
	public void generarRegistroArmas(EntityManager pEntityManager, TarmRegistroArmas registroArmas, String tipoRegistro){
		try {
			Sequence sequence = new Sequence();
			String cRegistro = sequence.getNextValue("CREGISTRO").toString();
			registroArmas.setPk(Long.parseLong(cRegistro));
			registroArmas.setTiporegistro("CARINV");
			pEntityManager.persist(registroArmas);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}         
	}
	
	public TarmArmas generarArma(EntityManager pEntityManager, TarmRegistroArmas registroArmas, TarmArmas armaParam, TcustPersonAddress direccionPrincipal, String tipoRegistro, Integer cantidad, java.sql.Date fechaRegistro){
		try {
			TarmArmas arma = (TarmArmas) armaParam.cloneMe();
			// Setear el estado del arma
			if(tipoRegistro.equals("IMP")){
				arma.setEstado("IMPO");
			}else if(tipoRegistro.equals("PRO")){
				arma.setEstado("REG");
			}
			arma.setCregistro(registroArmas.getPk());
			arma.setCantidad(cantidad);
			String carma = getCodigoArmas();
			arma.setPk(carma);
			arma.setCodigoarma(carma);
			
			// Poner datos de la Ubicacion del arma
			if(direccionPrincipal!=null){
				arma.setCountrycode(direccionPrincipal.getCountrycode());
				arma.setProvincecode(direccionPrincipal.getProvincecode());
				arma.setCantoncode(direccionPrincipal.getCantoncode());
				arma.setParroquiacode(direccionPrincipal.getParroquiacode());
				arma.setCitycode(direccionPrincipal.getCitycode());
				arma.setDireccion(direccionPrincipal.getAddress());
			}			
			arma.setColorcodigo("COLOR");
			arma.setUnidadmedidacantidadcodigo("UNIDADMEDIDA");
			arma.setFecharegistro(fechaRegistro);
			arma.setCpaisorigen(registroArmas.getPaisorigen());
			pEntityManager.persist(arma);
			return arma;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}         
	}		

	@Override
	public SaveRequest reverseProcess(SaveRequest arg0) throws Exception {

		return arg0;
	}
	
	/**
	 * 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(Inventarios.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(Inventarios.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
     * @return
     * @throws Exception
     */
    private String getCodigoCarga() throws Exception {
        Sequence sequence = new Sequence();
        String cCarga = sequence.getNextValue("CARGA").toString();        
        return cCarga;    	
    }
    
    /**
     * 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;    	
    }


}