package com.rjconsultores.ventaboletos.dao.hibernate;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.rjconsultores.ventaboletos.dao.MonitoramentoCRZDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Estado;
import com.rjconsultores.ventaboletos.entidad.FiscalImpressora;
import com.rjconsultores.ventaboletos.entidad.MonitoramentoCRZ;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.Usuario;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

@Repository("monitoramentoCRZDAO")
public class MonitoramentoCRZHibernateDAO extends GenericHibernateDAO<MonitoramentoCRZ, Integer>
implements MonitoramentoCRZDAO {
	private static final Logger log = LogManager.getLogger(MonitoramentoCRZHibernateDAO.class);
	Boolean jaexiste;
	
	@Autowired
	public MonitoramentoCRZHibernateDAO(
			@Qualifier("sessionFactory") SessionFactory factory) {
		setSessionFactory(factory);
	}
	
	private String getSQL(){
		StringBuilder sql = new StringBuilder();

		sql.append(" SELECT ");
		sql.append(" * ");
		sql.append(" FROM ");
		sql.append(" 	(SELECT  ");
		sql.append(" 	 	R2.crz, ");
		sql.append("     	R2.numserie20 AS numserie20,  ");
		sql.append("     	fi.numserie AS numserie,  ");
		sql.append("     	fi.fiscalimpressora_id AS fiscalimpressora_id,  ");
		sql.append("     	R2.datamov AS datamov,  ");
		sql.append("     	R2.COOINICIAL AS COOINICIAL,  ");
		sql.append("     	R2.COOFINAL AS COOFINAL,  ");
		sql.append("     	fi.estadolocal_id AS estadolocal_id,  ");
		sql.append("     	fi.empresa_id AS empresa_id,  ");
		sql.append("     	R2.puntoventa_id AS puntoventa_id,  ");
		sql.append("     	R2.USUARIO_ID AS USUARIO_ID ");
		sql.append(" 	FROM  ");
		sql.append(" 		FISCAL_R2 R2 ");
		sql.append("     	inner join fiscal_impressora fi on fi.numserie20 = R2.numserie20  ");
		sql.append(" 	WHERE R2.NUMSERIE20 = :numserie and R2.datamov != '20000000' ");
		sql.append("	ORDER BY r2.crz desc) ");
		sql.append(" where rownum <= 5 ");

		return sql.toString();
	}
	
	public List<String> buscaImpressoras(){
		final List<String> result = new ArrayList<String>();
		try{
			getSession().doWork(new Work() {
		        public void execute(Connection connection) throws SQLException 
		        { 
		        	NamedParameterStatement stmt = null;
		        	ResultSet rset = null;
		        	try{
			        	stmt = new NamedParameterStatement(connection, "select distinct numserie20 from fiscal_impressora where activo = 1");
						
			        	rset = stmt.executeQuery();
				
						while (rset.next()) {				
							result.add(rset.getString(1));
						}
		        	} finally {
                        if(stmt != null) {
                        	stmt.close();
                        }
                        if(rset != null) {
                        	rset.close();
                        }
                        if(connection != null) {
                        	//connection.close();
                        }
                    }
		        }
			});
		} catch (Exception e){
			log.error("", e);
		} 
		return result;
	}
	
	public List<MonitoramentoCRZ> buscaQuebraCRZ(final Date data){
		final List<MonitoramentoCRZ> result = new ArrayList<MonitoramentoCRZ>();
		final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		try{
			getSession().doWork(new Work() {
		        public void execute(Connection connection) throws SQLException 
		        { 
		        	NamedParameterStatement stmt = null;
		        	ResultSet rset = null;
		        	try{
			        	stmt = new NamedParameterStatement(connection, getSQL());
						for (String s : buscaImpressoras()){
							stmt.setString("numserie", s);
							rset = stmt.executeQuery();
					
							while (rset.next()) {
								Integer empresaId = rset.getInt("empresa_id");
								Integer estadoId = rset.getInt("estadolocal_id");
								PuntoVenta puntoVenta = new PuntoVenta(rset.getInt("puntoventa_id"));
								Usuario usuario = new Usuario(rset.getInt("usuario_id"));
								FiscalImpressora fiscalImpressora = new FiscalImpressora(rset.getInt("fiscalimpressora_id"));
								Integer crz = rset.getInt("CRZ");
								Date dataRegistro = sdf.parse(rset.getString("datamov"));
								Integer crz2 = null;
								
								
								if (rset.next()){
									crz2 = rset.getInt("CRZ");
									Date aux = dataRegistro;
									if (crz - crz2 > 1){ // crz é maior que crz2 pois esta ordenado decrescente
										for (int i = crz -1; i > crz2; i--){
											Calendar c = Calendar.getInstance();
											c.setTime(aux);
											c.add(Calendar.DATE, -1);
											aux = c.getTime();
											
											MonitoramentoCRZ m = new MonitoramentoCRZ();
											m.setDataMonitoramento(new Date());											
											m.setDataReducaoZFaltante(aux);											
											m.setDiasAlertaAberto(new Date());
											m.setEmpresa(empresaId != null && empresaId != 0 ? new Empresa(empresaId) : null);
											m.setEstadoInstalacao(estadoId != null && estadoId != 0 ? new Estado(estadoId) : null);
											m.setPuntoventa(puntoVenta);
											m.setSequenciaCRZQuebrada(i);
											m.setUltimoUsuarioECF(usuario);
											m.setImpressora(fiscalImpressora);
											result.add(m);
										}
									}
								}
							}
						}
		        	} catch (ParseException e) {
						log.error("", e);
					} finally {
                        if(stmt != null) {
                        	stmt.close();
                        }
                        if(rset != null) {
                        	rset.close();
                        }
                        if(connection != null) {
                        	//connection.close();
                        }
                    }
		        }
			});
		} catch (Exception e){
			log.error("", e);
		} 
		return result;
	}
	
	private String getMonitoramentoCRZSQL(){
		StringBuilder sql = new StringBuilder();

		sql.append(" select count(*) ");
		sql.append(" from monitoramento_crz ");
		sql.append(" where SEQUENCIA_CRZ_QUEBRADA = :seq and fiscalimpressora_id = :fiscalimpressoraId ");

		return sql.toString();
	}
	
	@Override
	public MonitoramentoCRZ suscribir(final MonitoramentoCRZ entity){
		jaexiste = false;
		try{
			getSession().doWork(new Work() {
		        public void execute(Connection connection) throws SQLException 
		        { 
		        	NamedParameterStatement stmt = null;
		        	ResultSet rset = null;
		        	try{
						log.debug("salvando crz " + entity.getSequenciaCRZQuebrada() + " para impressora " + entity.getImpressora().getFiscalimpressoraId());
						stmt = new NamedParameterStatement(connection, getMonitoramentoCRZSQL());
						stmt.setInt("seq", entity.getSequenciaCRZQuebrada());
						stmt.setInt("fiscalimpressoraId", entity.getImpressora().getFiscalimpressoraId());
						rset = stmt.executeQuery();
						if (rset.next()){
							if (rset.getInt(1) > 0){
								jaexiste = true;
								return;
							}
						}	
		        	} finally {
                        if(stmt != null) {
                        	stmt.close();
                        }
                        if(rset != null) {
                        	rset.close();
                        }
                        if(connection != null) {
                        	//connection.close();
                        }
                    }
		        }
			});
			if (!jaexiste) {
				return super.suscribir(entity);
			} else {
				return entity;
			}
		} catch (Exception e){
			log.error("", e);
			return entity;
		} 
	}
	
	@Override
	public List<MonitoramentoCRZ> obtenerTodos(){
		StringBuilder hql = new StringBuilder();
		hql.append("SELECT m FROM MonitoramentoCRZ m ");
		hql.append("left join m.empresa ");
		hql.append("ORDER BY m.empresa, m.impressora.numserie20, m.sequenciaCRZQuebrada ");
		Query query = getSession().createQuery(hql.toString());
		
		return query.list();
	}
}
