package com.rjconsultores.ventaboletos.dao.hibernate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.sql.DataSource;

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 org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.SapDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.FechamentoCntcorrente;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.enums.StatusIntegracaoSap;
import com.rjconsultores.ventaboletos.exception.BusinessRuntimeException;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.vo.integracao.FechamentoCntCorrenteVO;

@Repository("sapDAO")
public class SapHibernateDAO extends GenericHibernateDAO<FechamentoCntcorrente, Long> implements SapDAO {
	
	@Autowired
    public SapHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
        setSessionFactory(factory);
    }
	
	@Autowired
	@Qualifier("dataSourceWrite")
	DataSource scoDs;
	
	@Override
	@Transactional
	public List<FechamentoCntCorrenteVO> obtenerTodosParaRemessa(Empresa empresa, Date dataDe, Date dataAte, String status) {
		return obtenerTodosParaRemessa(empresa, dataDe, dataAte, status, null);
	}

	@Override
	@Transactional
	public List<FechamentoCntCorrenteVO> obtenerTodosParaRemessa(Empresa empresa, Date dataDe, Date dataAte, String status, PuntoVenta puntoVenta) {
		
		StringBuilder sb = new StringBuilder();
		sb.append(" SELECT   ");
		sb.append("     fc.fechamentocntcorrente_id, ");
		sb.append("     to_char(fc.fecfechamento, 'yyyy-mm-DD'), ");
		sb.append("     fc.total, ");
		sb.append("     es.cveestado, ");
		sb.append("     pv.numpuntoventa, ");
		sb.append("     pv.numdocpuntoventa, ");
		sb.append("     pv.nombpuntoventa, ");
		sb.append("     fc.empresa_id, ");
		sb.append("     emp.nombempresa, ");
		sb.append("     fc.indintegradosap, ");
		sb.append("     to_char(fc.fecfechamento, 'yyyy'), ");
		sb.append("     to_char(fc.fecfechamento, 'mm'), ");
		sb.append("     CASE to_char(fc.fecfechamento, 'D') ");
		sb.append("     WHEN '6' THEN to_char(fc.fecfechamento+3, 'yyyy-mm-DD') ");
		sb.append("     WHEN '7' THEN to_char(fc.fecfechamento+2, 'yyyy-mm-DD') ");
		sb.append("     ELSE to_char(fc.fecfechamento+1, 'yyyy-mm-DD') END as feclancamento ");
		sb.append(" FROM ");
		sb.append("     fechamento_cntcorrente fc ");
		sb.append("     INNER JOIN punto_venta   	 pv ON pv.puntoventa_id = fc.puntoventa_id AND pv.activo = 1 ");
		sb.append("     INNER JOIN empresa       	 emp ON emp.empresa_id = fc.empresa_id AND emp.activo = 1 ");				
		sb.append("     INNER JOIN fechamento_boleto fb ON fc.fechamentocntcorrente_id = fb.fechamentocntcorrente_id ");
		sb.append("     LEFT JOIN ciudad         	 ci ON ci.ciudad_id = emp.ciudad_id AND ci.activo = 1 ");
		sb.append("     LEFT JOIN plaza          	 pl ON pl.plaza_id = ci.plaza_id AND pl.activo = 1 ");
		sb.append("     LEFT JOIN estado         	 es ON es.estado_id = ci.estado_id AND es.activo = 1 ");
		sb.append(" WHERE ");
		sb.append("     fc.activo = 1 ");
		sb.append("     AND fb.tipo_pagamento = 'B' ");
		sb.append("     AND fc.fecfechamento BETWEEN :dataDe AND :dataAte ");
		
		if( empresa != null ) {
			sb.append("     AND fc.EMPRESA_ID = :empresaId ");
		}
		
		if( puntoVenta != null ) {
			sb.append("     AND pv.puntoventa_id = :puntoVentaId ");
		}
		
		if(status != null && !status.isEmpty()){
			sb.append(" AND fc.indintegradosap in ("+status+")");
		}

		sb.append(" ORDER BY ");
		sb.append("     pv.nombpuntoventa, fc.fecfechamento ");
		
		Query query = getSession().createSQLQuery(sb.toString());
		
		if( empresa != null ) {
			query.setInteger("empresaId", empresa.getEmpresaId());
		}
		
		if( puntoVenta != null ) {
			query.setInteger("puntoVentaId", puntoVenta.getPuntoventaId());
		}
		
		if(dataDe != null && dataAte != null){			
			query.setDate("dataDe", DateUtil.normalizarToFecha(dataDe));
			query.setDate("dataAte", DateUtil.normalizarToFecha(dataAte));
		}		
		
		query.setMaxResults(300);

		@SuppressWarnings("unchecked")
		List<Object[]> list = query.list();
		List<FechamentoCntCorrenteVO> retorno = new ArrayList<>();
		
		for(Object[] tupla : list){
			
			FechamentoCntCorrenteVO fcc = new FechamentoCntCorrenteVO();
			fcc.setFechamentocntcorrenteId( Long.valueOf(tupla[0].toString()));
			fcc.setFecfechamento( tupla[1].toString() );
			fcc.setTotal( (BigDecimal)tupla[2] );
			fcc.setUfEmpresa(tupla[3].toString());
			fcc.setNumPuntoVenta(tupla[4].toString());
			
			try {
				String cnpj = tupla[5].toString().replaceAll("\\D", "");
				fcc.setCnpjPuntoVenta(cnpj);
			}catch (Exception e) {
				throw new BusinessRuntimeException( "CNPJ fora do padrao no ponto de venda: %s ", tupla[6]  );
			}
			fcc.setNombpuntoventa(tupla[6].toString());

			fcc.setEmpresaId( Integer.valueOf( tupla[7].toString() ));
			fcc.setNombEmpresa( tupla[8].toString());
			
			fcc.setIntegradoSap( StatusIntegracaoSap.getStatusIntegracaoSap( tupla[9]==null?0:Integer.valueOf(tupla[9].toString()) ));
			
			fcc.setAnofechamento(tupla[10].toString());
			fcc.setMesfechamento(tupla[11].toString());
			fcc.setFeclancamento(tupla[12].toString());
			
			//empresa enviada nula apenas no processo automatico
			if(empresa == null) {
				fcc.setEnviar(true);
			}
			
			retorno.add(fcc);
		}

		return retorno;
	}

	@Override
	@Transactional
	public boolean atualizaFechamento(Long fechamentocntcorrenteId, int status) throws Exception {
		
		if(fechamentocntcorrenteId == null ) {
			return false;
		}
		
		getSession().flush();
	
		StringBuilder qry = new StringBuilder();
		qry.append(" UPDATE FECHAMENTO_CNTCORRENTE ");
		qry.append(" SET INDINTEGRADOSAP = :status "); 
		qry.append(" WHERE FECHAMENTOCNTCORRENTE_ID = :fechamentoId ");
		
		Query query = getSession().createSQLQuery(qry.toString());
		query.setInteger("status", status);
		query.setLong("fechamentoId", fechamentocntcorrenteId);
		
		query.executeUpdate();
	
		return Boolean.TRUE;
	}
	
}