package com.rjconsultores.ventaboletos.relatorios.impl;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.rjconsultores.ventaboletos.constantes.Constantes.FiltroEnviadosSefaz;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.ArrayDataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

public class RelatorioVendaEmbarcada extends Relatorio {
	
	private static final String STATUSSEFAZ = "statussefaz";
	private Date datInicial;
	private Date datFinal;
	private Integer estadoId;
	private Integer empresaId;
	private Integer puntoVendaId;
	private Integer orgaoConcedenteId;
	private Integer usuarioId;	
	private String linhaIds;
	private String serie;
	private String numBpe;
	private Boolean bloqueado;
	private FiltroEnviadosSefaz envioSefaz;
	private FiltroEnviadosSefaz vendaEmbarcada;
	private boolean quebraSequencia;
	private boolean ultimoBpe;

	private static Logger log = LogManager.getLogger(RelatorioVendaEmbarcada.class);

	public RelatorioVendaEmbarcada(Map<String, Object> parametros, Connection conexao) throws Exception {
		super(parametros, conexao);

		this.setCustomDataSource(new ArrayDataSource(this) {

			@Override
			public void initDados() throws Exception {
				try {
					SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
					
					Connection conexao = this.relatorio.getConexao();	
					
					Map<String, Object> parametros = this.relatorio.getParametros();
					
					estadoId = (Integer)parametros.get("ESTADO_ID");
					empresaId = (Integer)parametros.get("EMPRESA_ID");
					puntoVendaId = (Integer)parametros.get("PUNTOVENTA_ID");
					usuarioId = (Integer)parametros.get("usuarioId");
					orgaoConcedenteId = (Integer)parametros.get("orgaoConcedenteId");
					serie = (String)parametros.get("SERIE");
					numBpe = (String)parametros.get("NUMBPE");
					linhaIds = (String)parametros.get("linhaIds");
					bloqueado = (boolean)parametros.get("BLOQUEADO");
					envioSefaz = (FiltroEnviadosSefaz)parametros.get("ENVIOSEFAZ");
					vendaEmbarcada = (FiltroEnviadosSefaz)parametros.get("VENDAEMBARCADA");
					quebraSequencia = (Boolean)parametros.get("QUEBRASEQ");
					ultimoBpe = (boolean)parametros.get("ULTIMOBPE");
			
					String sql = getSql();
					
					Date dtInicio = sdf.parse(DateUtil.getStringDate((Date) parametros.get("DATA_INICIAL"), "dd/MM/yyyy") + " 00:00:00");
					Date dtFim = sdf.parse(DateUtil.getStringDate((Date) parametros.get("DATA_FINAL"), "dd/MM/yyyy") + " 23:59:59");
			
					NamedParameterStatement ps = new NamedParameterStatement(conexao, sql.toString());
					ps.setTimestamp("fecInicio", new java.sql.Timestamp(dtInicio.getTime()));
					ps.setTimestamp("fecFinal", new java.sql.Timestamp(dtFim.getTime()));
					
					if (estadoId != null){
						ps.setLong("estadoId", estadoId);
					}
					
					if (empresaId != null){
						ps.setLong("empresaId", empresaId);
					}
					
					if (puntoVendaId != null){
						ps.setLong("puntoventaId", puntoVendaId);
					}
					
					if (orgaoConcedenteId != null){
						ps.setLong("orgaoConcedenteId", orgaoConcedenteId);
					}
					
					if (usuarioId != null){
						ps.setLong("usuarioId", usuarioId);
					}
					
					if (puntoVendaId != null){
						ps.setLong("puntoventaId", puntoVendaId);
					}
					
					if (StringUtils.isNotBlank(serie)){
						ps.setString("serie", serie);
					}
					
					if (StringUtils.isNotBlank(numBpe)){
						ps.setString("bpe", numBpe);
					}
					
					if (bloqueado != null && bloqueado){
						ps.setInt("bloqueado", 1);
					}
					
					ResultSet rset = ps.executeQuery();
			
					Map<String, Object> dataResult = null;
					Map<String, Object> aux = null;
					while (rset.next()) {
						if (ultimoBpe){
							if (dataResult == null){
								dataResult = extractRow(rset);
							} else {
								aux = extractRow(rset);
								if (aux.get("cveestado").equals(dataResult.get("cveestado"))){
									if (aux.get("numserie_bpe").equals(dataResult.get("numserie_bpe"))){
										if (Integer.parseInt(aux.get("num_bpe").toString()) > Integer.parseInt(dataResult.get("num_bpe").toString())){
											dataResult = aux;
										}
									} else {
										this.dados.add(dataResult);
										dataResult = aux;
									}
								} else {
									this.dados.add(dataResult);
									dataResult = aux;
								}
							}
						} else {
							dataResult = extractRow(rset);
							this.dados.add(dataResult);
						}
					}
				} catch (Exception e){
					log.error("", e);
				}
			}
		});
	}
	
	private Map<String, Object> extractRow(ResultSet rset) throws SQLException{
		Map<String, Object> dataResult = new HashMap<String, Object>();

		dataResult.put("nombempresa", rset.getString("nombempresa"));
		dataResult.put("puntoventa_id", rset.getString("puntoventa_id"));
		dataResult.put("nombpuntoventa", rset.getString("nombpuntoventa"));
		dataResult.put("cveusuario", rset.getString("cveusuario"));
		dataResult.put("nombusuario", rset.getString("nombusuario"));
		dataResult.put("numserie_bpe", rset.getString("numserie_bpe"));
		dataResult.put("num_bpe", rset.getString("num_bpe"));
		dataResult.put("cveestado", rset.getString("cveestado"));
		dataResult.put("ruta_id", rset.getString("ruta_id"));
		dataResult.put("numruta", rset.getString("numruta"));
		dataResult.put("descruta", rset.getString("descruta"));
		dataResult.put("origenId", rset.getString("origenId"));
		dataResult.put("origen", rset.getString("origen"));
		dataResult.put("destinoId", rset.getString("destinoId"));
		dataResult.put("destino", rset.getString("destino"));		
		dataResult.put("corrida_id", rset.getString("corrida_id"));
		dataResult.put("tarifa", rset.getDouble("tarifa"));
		dataResult.put("seguro", rset.getDouble("seguro"));
		dataResult.put("taxaembarque", rset.getDouble("taxaembarque"));
		dataResult.put("importepedagio", rset.getDouble("importepedagio"));
		dataResult.put("tpp", rset.getDouble("tpp"));
		dataResult.put("total", rset.getDouble("total"));
		
		try {
			dataResult.put("feccorte", new Date(rset.getDate("feccorte").getTime()));
		}catch (Exception e) {
			dataResult.put("feccorte", null);
		}
		dataResult.put("fechorventa", new Date(rset.getDate("fechorventa").getTime()));
		dataResult.put("fechorviaje", new Date(rset.getDate("fechorviaje").getTime()));
		
		Integer codstat = rset.getInt(STATUSSEFAZ);
		if (codstat == -1){
			dataResult.put(STATUSSEFAZ, "Pendente");
		} else if (codstat == 100 || codstat == 102 ){
			dataResult.put(STATUSSEFAZ, "Enviado");
		} else if (codstat == 150){
			dataResult.put(STATUSSEFAZ, "Enviado em contingência");
		}					
		dataResult.put("chbpe", rset.getString("chbpe"));
		dataResult.put("nprot", rset.getString("nprot"));
		
		return dataResult;
	}

	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSql() {

		StringBuilder sql = new StringBuilder();	
		if (quebraSequencia){
			sql.append("select * from ( ");
		}
		sql.append("select ");
		sql.append("    e.nombempresa, ");
		sql.append("    p.puntoventa_id, ");
		sql.append("    p.nombpuntoventa, ");
		sql.append("    u.cveusuario, ");
		sql.append("    u.nombusuario, ");
		sql.append("    c.feccorte, ");
		sql.append("    b.numserie_bpe, ");
		sql.append("    b.num_bpe as num_bpe, ");
		sql.append("    est.cveestado, ");
		sql.append("    b.ruta_id, ");
		sql.append("    r.numruta, ");
		sql.append("    r.descruta, ");
		sql.append("    ori.parada_id origenId, ");
		sql.append("    ori.descparada origen, ");
		sql.append("    dest.parada_id destinoId, ");
		sql.append("    dest.descparada destino, ");
		sql.append("    b.fechorventa, ");
		sql.append("    b.fechorviaje, ");
		sql.append("    b.corrida_id, ");
		sql.append("    b.preciopagado as tarifa, ");
		sql.append("    b.importeseguro as seguro, ");
		sql.append("    b.importetaxaembarque as taxaembarque, ");
		sql.append("    b.importepedagio, ");
		sql.append("    b.importetpp as tpp, ");
		sql.append("    b.preciopagado + nvl(b.importeoutros,0) + nvl(b.importepedagio,0) + nvl(b.importeseguro,0) + nvl(b.importetaxaembarque,0) + nvl(b.importetpp,0) as total, ");
		sql.append("    bp.codstat as statussefaz, ");
		sql.append("    bp.chbpe, ");
		sql.append("    bp.nprot ");
		sql.append("from  ");
		sql.append("    boleto b  ");
		sql.append("    inner join marca m on m.marca_id = b.marca_id ");
		sql.append("    inner join empresa e on e.empresa_id = m.empresa_id ");
		sql.append("    inner join punto_venta p on p.puntoventa_id = b.puntoventa_id ");
		sql.append("    inner join usuario u on u.usuario_id = b.usuario_id ");
		sql.append("    inner join caja c on c.transacao_id = b.boleto_id ");
		sql.append("    inner join bpe bp on bp.boleto_id = b.boleto_id ");
		sql.append("    left join colonia col on col.colonia_id = p.colonia_id  ");
		sql.append("	left join ciudad cid on cid.ciudad_id = col.ciudad_id ");
		sql.append("	left join estado est on cid.estado_id = est.estado_id     ");
		sql.append("    inner join ruta r on r.ruta_id = b.ruta_id ");
		sql.append("    inner join parada ori on ori.parada_id = b.origen_id ");
		sql.append("    inner join parada dest on dest.parada_id = b.destino_id ");
		sql.append("    left join dispositivo_embarcada disp on disp.imei = b.IMEI_DISPOSITIVO_EMBARCADA ");
		sql.append("where  ");
		sql.append("    b.fechorventa between :fecInicio and :fecFinal ");
		sql.append("    and b.motivocancelacion_id is null ");
		sql.append("    and bp.TIPOSUBSTITUICAO is  null ");
		
		if (empresaId != null){
			sql.append("    and e.empresa_id = :empresaId ");
		}
		
		if (puntoVendaId != null){
			sql.append("    and p.puntoventa_id = :puntoventaId ");
		}
		
		if (orgaoConcedenteId != null){
			sql.append("    and r.ORGAOCONCEDENTE_ID = :orgaoConcedenteId ");
		}
		
		if (usuarioId != null){
			sql.append("    and u.usuario_id = :usuarioId ");
		}
		
		if (StringUtils.isNotBlank(linhaIds)){
			sql.append("    and r.ruta_id in ( ").append(linhaIds).append(")");
		}
		
		if (estadoId != null){
			sql.append("    and est.estado_id = :estadoId ");
		}
		
		if (StringUtils.isNotBlank(serie)){
			sql.append("    and b.numserie_bpe = :serie ");
		}
		if (StringUtils.isNotBlank(numBpe)){
			sql.append("    and b.num_bpe = :bpe ");
		}
		if (bloqueado != null && bloqueado){
			sql.append("    and disp.ind_disp_bloqueado = :bloqueado ");
		} else {
			sql.append("    and (disp.ind_disp_bloqueado = 0 or disp.ind_disp_bloqueado is null) ");
		}
		if (envioSefaz == FiltroEnviadosSefaz.SIM) {
			sql.append("	and bp.codstat in (100, 102, 150) ");			
		} else if (envioSefaz == FiltroEnviadosSefaz.NAO) {
			sql.append("	and bp.codstat = -1 ");
		} else {
			sql.append("	and bp.codstat in (-1, 100, 102, 150) ");
		}
		if (vendaEmbarcada == FiltroEnviadosSefaz.SIM) {
			sql.append("	and b.tipoventa_id in (99) ");			
		} else if (vendaEmbarcada == FiltroEnviadosSefaz.NAO) {
			sql.append("	and b.tipoventa_id not in (99) ");
		} 
		if (quebraSequencia){
			sql.append("union  ");
			sql.append("select  ");
			sql.append("    null as nombempresa,  ");
			sql.append("    null as puntoventa_id,  ");
			sql.append("    null as nombpuntoventa,  ");
			sql.append("    null as cveusuario,  ");
			sql.append("    null as nombusuario,  ");
			sql.append("    null as feccorte,  ");
			sql.append("    bd.serie as numserie_bpe, ");
			sql.append("    bd.numero as num_bpe,  ");
			sql.append("    bd.cveestado as cveestado,  ");
			sql.append("    null as ruta_id,  ");
			sql.append("    null as numruta,  ");
			sql.append("    null as descruta,  ");
			sql.append("    null as  origenId,  ");
			sql.append("    null as  origen,  ");
			sql.append("    null as  destinoId,  ");
			sql.append("    null as  destino,  ");
			sql.append("    null as fechorventa,  ");
			sql.append("    null as fechorviaje,  ");
			sql.append("    null as corrida_id,  ");
			sql.append("    null as tarifa,  ");
			sql.append("    null as seguro,  ");
			sql.append("    null as taxaembarque, "); 
			sql.append("    null as importepedagio,  ");
			sql.append("    null as tpp,  ");
			sql.append("    null as total,  ");
			sql.append("    null as statussefaz, "); 
			sql.append("    null as chbpe,  ");
			sql.append("    null as nprot  ");
			sql.append("from  ");
			sql.append("    boleto b ");  
			sql.append("    inner join marca m on m.marca_id = b.marca_id "); 
			sql.append("    inner join empresa e on e.empresa_id = m.empresa_id "); 
			sql.append("    inner join punto_venta p on p.puntoventa_id = b.puntoventa_id "); 
			sql.append("    inner join usuario u on u.usuario_id = b.usuario_id  ");
			sql.append("    inner join caja c on c.transacao_id = b.boleto_id  ");
			sql.append("    inner join bpe bp on bp.boleto_id = b.boleto_id  ");
			sql.append("    left join colonia col on col.colonia_id = p.colonia_id ");  
			sql.append("	left join ciudad cid on cid.ciudad_id = col.ciudad_id  ");
			sql.append("	left join estado est on cid.estado_id = est.estado_id      ");
			sql.append("    inner join ruta r on r.ruta_id = b.ruta_id  ");
			sql.append("    inner join parada ori on ori.parada_id = b.origen_id "); 
			sql.append("    inner join parada dest on dest.parada_id = b.destino_id  ");
			sql.append("    left join dispositivo_embarcada disp on disp.imei = b.IMEI_DISPOSITIVO_EMBARCADA "); 
			sql.append("    inner join bpe_ctrl_disponibilidade bd on bd.serie = b.numserie_bpe  ");
			sql.append("where   ");
			sql.append("    b.fechorventa between :fecInicio and :fecFinal ");
			sql.append("    and b.motivocancelacion_id is null ");
			sql.append("    and bp.TIPOSUBSTITUICAO is  null ");
			
			if (empresaId != null){
				sql.append("    and e.empresa_id = :empresaId ");
			}
			
			if (puntoVendaId != null){
				sql.append("    and p.puntoventa_id = :puntoventaId ");
			}
			
			if (estadoId != null){
				sql.append("    and est.estado_id = :estadoId ");
			}
			
			if (orgaoConcedenteId != null){
				sql.append("    and r.ORGAOCONCEDENTE_ID = :orgaoConcedenteId ");
			}
			
			if (usuarioId != null){
				sql.append("    and u.usuario_id = :usuarioId ");
			}
			
			if (linhaIds != null){
				sql.append("    and r.ruta_id in ( ").append(linhaIds).append(")");
			}
			
			if (StringUtils.isNotBlank(serie)){
				sql.append("    and b.numserie_bpe = :serie ");
			}
			if (StringUtils.isNotBlank(numBpe)){
				sql.append("    and b.num_bpe = :bpe ");
			}
			if (bloqueado != null && bloqueado){
				sql.append("    and disp.ind_disp_bloqueado = :bloqueado ");
			} else {
				sql.append("    and (disp.ind_disp_bloqueado = 0 or disp.ind_disp_bloqueado is null) ");
			}
			if (envioSefaz == FiltroEnviadosSefaz.SIM) {
				sql.append("	and bp.codstat in (100, 102, 150) ");			
			} else if (envioSefaz == FiltroEnviadosSefaz.NAO) {
				sql.append("	and bp.codstat = -1 ");
			} else {
				sql.append("	and bp.codstat in (-1, 100, 102, 150) ");
			}
			if (vendaEmbarcada == FiltroEnviadosSefaz.SIM) {
				sql.append("	and b.tipoventa_id in (99) ");
			} else if (vendaEmbarcada == FiltroEnviadosSefaz.NAO) {
				sql.append("	and b.tipoventa_id not in (99) ");
			}
			sql.append(") ");
		}
		sql.append("order by ");
		sql.append("    cveestado, ");
		sql.append("	to_number(numserie_bpe), ");
		sql.append("	to_number(num_bpe) ");
		return sql.toString();
	}

	public Date getDatInicial() {
		return datInicial;
	}

	public void setDatInicial(Date datInicial) {
		this.datInicial = datInicial;
	}

	public Date getDatFinal() {
		return datFinal;
	}

	public void setDatFinal(Date datFinal) {
		this.datFinal = datFinal;
	}

	public Integer getEstadoId() {
		return estadoId;
	}

	public void setEstadoId(Integer estadoId) {
		this.estadoId = estadoId;
	}

	public Integer getEmpresaId() {
		return empresaId;
	}

	public void setEmpresaId(Integer empresaId) {
		this.empresaId = empresaId;
	}

	public Integer getPuntoVendaId() {
		return puntoVendaId;
	}

	public void setPuntoVendaId(Integer puntoVendaId) {
		this.puntoVendaId = puntoVendaId;
	}

	public String getSerie() {
		return serie;
	}

	public void setSerie(String serie) {
		this.serie = serie;
	}

	public String getNumBpe() {
		return numBpe;
	}

	public void setNumBpe(String numBpe) {
		this.numBpe = numBpe;
	}

	public Boolean getBloqueado() {
		return bloqueado;
	}

	public void setBloqueado(Boolean bloqueado) {
		this.bloqueado = bloqueado;
	}

	public FiltroEnviadosSefaz getEnvioSefaz() {
		return envioSefaz;
	}

	public void setEnvioSefaz(FiltroEnviadosSefaz envioSefaz) {
		this.envioSefaz = envioSefaz;
	}

	public Boolean getQuebraSequencia() {
		return quebraSequencia;
	}

	public void setQuebraSequencia(Boolean quebraSequencia) {
		this.quebraSequencia = quebraSequencia;
	}

	public Boolean getUltimoBpe() {
		return ultimoBpe;
	}

	public void setUltimoBpe(Boolean ultimoBpe) {
		this.ultimoBpe = ultimoBpe;
	}	
}