package com.rjconsultores.ventaboletos.dao.hibernate;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

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

import com.rjconsultores.ventaboletos.dao.CtrlSerieBPeDAO;
import com.rjconsultores.ventaboletos.entidad.CtrlSerieBPe;

@Repository("ctrlSerieBPeDAO")
public class CtrlSerieBPeHibernateDAO extends GenericHibernateDAO<CtrlSerieBPe, Long> implements CtrlSerieBPeDAO {
	private static final Logger log = LogManager.getLogger(CtrlSerieBPeHibernateDAO.class);

	@Autowired
	private DataSource dataSource;

	@Autowired
	public CtrlSerieBPeHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
		setSessionFactory(factory);
	}
	
	public Boolean gerarSeqSerieBPe(Integer empresaId, String estado, Integer minvalue) throws RuntimeException {
		Boolean retorno = Boolean.FALSE;
		Connection conn = null;
		
		log.info(String.format("Gerando sequence empresaId:%s, estado:%s, minvalue:%s",empresaId,estado,minvalue));
		
		try {
			conn = dataSource.getConnection();

			StringBuilder seq = new StringBuilder();
			seq.append("SERIE_BPE_");
			seq.append(estado).append("_");
			seq.append(empresaId).append("_");
			seq.append("SEQ");
			
			
			boolean sequenceExiste = conn.createStatement().executeQuery("select SEQUENCE_NAME from USER_SEQUENCES where SEQUENCE_NAME like '" + seq.toString() + "%'").next();
			
			log.info(String.format("sequenceExiste:%s",sequenceExiste));
			
			if (!sequenceExiste) {
				conn.createStatement().execute("CREATE SEQUENCE " + seq.toString() + " MINVALUE 1 MAXVALUE 999 INCREMENT BY 1 START WITH " + minvalue.toString() + " ORDER NOCACHE");

				log.info("SEQUENCIA " + seq.toString() + " GERADA COM SUCESSO.");
				
				retorno = Boolean.TRUE;
			}
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		
		return retorno;
	}
	
	public Integer buscarSerieEmb(Integer empresaId, String estadoId) throws RuntimeException {
	
		log.info(String.format("Conferindo sequence empresaId:%s, estado:%s",empresaId,estadoId));
		
		try {
			StringBuilder sb = new StringBuilder();
			sb.append("select se.serie ");
			sb.append("from CtrlSerieEmbarcada se ");
			sb.append("where se.activo = 1 ");
			sb.append("and se.empresa.empresaId = :empresaId ");
			sb.append("and se.estado.estadoId = :estadoId ");
			sb.append(" order by cast(se.serie as integer) DESC ");

			Query qry = getSession().createQuery(sb.toString());
			qry.setLong("empresaId", empresaId);
			qry.setString("estadoId", estadoId);
			qry.setMaxResults(1);
			Integer serie = Integer.valueOf((String) (qry.uniqueResult() == null ? "1" : qry.uniqueResult()));
			
			return (serie == 0 ? 1 : serie);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} 
		
		return null;
	}
	
	public Integer buscarSequencia(Integer empresaId, String estado) {
		Integer retorno = null;
		
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		
		try {
			conn = dataSource.getConnection();

			StringBuilder seq = new StringBuilder();
			seq.append("SERIE_BPE_");
			seq.append(estado).append("_");
			seq.append(empresaId).append("_");
			seq.append("SEQ");
			
			StringBuilder sql = new StringBuilder();
			sql.append("select ").append(seq.toString()).append(".nextval from dual");
			
			st = conn.createStatement();
			rs = st.executeQuery(sql.toString());
			
			rs.next(); 
			
			retorno = rs.getInt(1);

		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			try { if (rs != null) rs.close(); } catch (Exception e) { log.error("", e); }
			try { if (st != null) st.close(); } catch (Exception e) { log.error("", e); }
			
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		
		return retorno;
	}
	
	public CtrlSerieBPe buscarPorEmpresaEstado(Integer empresaId, Integer estadoId) {
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT ctrl ");
		sb.append("FROM CtrlSerieBPe ctrl ");
		sb.append("WHERE ctrl.activo = 1 AND ctrl.empresa.empresaId = :empresaId AND ctrl.estado.estadoId = :estadoId ");
		sb.append("  order by cast(ctrl.serie as integer) DESC ");
		
		Query qr = getSession().createQuery(sb.toString());
		qr.setInteger("empresaId", empresaId);
		qr.setInteger("estadoId", estadoId);
		qr.setMaxResults(1);
		
		return (CtrlSerieBPe) qr.uniqueResult();
	}
}
