package com.rjconsultores.ventaboletos.relatorios.impl;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

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

import com.rjconsultores.ventaboletos.entidad.Cliente;
import com.rjconsultores.ventaboletos.entidad.ClienteDescuento;
import com.rjconsultores.ventaboletos.entidad.ClienteDireccion;
import com.rjconsultores.ventaboletos.entidad.ClienteFidelidad;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.ArrayDataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

public class RelatorioCarteirinha extends Relatorio {
	
	private static Logger log = LogManager.getLogger(RelatorioCarteirinha.class);
	
	public enum TipoLayout { LAYOUT_1, LAYOUT_2, LAYOUT_CLIENTE }
	
	private List<Cliente> clientes;
	private TipoLayout tipoLayout;
	
	public RelatorioCarteirinha(Map<String, Object> parametros, final List<Cliente> lsClienteSelecionados,
			TipoLayout tipoLayout, Connection conexao) throws Exception {
		super(parametros, conexao);
		this.clientes = lsClienteSelecionados;
		this.tipoLayout = tipoLayout;
		this.setCustomDataSource(new ArrayDataSource(this) {
			public void initDados() throws Exception {
				Connection conexao = this.relatorio.getConexao();
				buscarDados(conexao, this.dados, this.resultSet);
			}
		});
	}
	
	@Override
	public String getNome() {
		String layoutCamelCase = StringUtils.remove(WordUtils.capitalizeFully(tipoLayout.name(), new char[] {'_'}), "_");
		return this.getClass().getSimpleName() + layoutCamelCase;
	}

	@Override
	protected void processaParametros() throws Exception {
	}
	
	private void buscarDados(Connection conexao, List<Map<String, Object>> dados, ResultSet resultSet) throws SQLException {		
		StringBuilder sqlLogoEmpresa = new StringBuilder();	
		sqlLogoEmpresa.append(" SELECT IE.NUMINSCRICAOESTADUAL, M.LOGOTIPOMARCA, E.LOGRADOURO, M.DESCMARCA, E.BAIRRO, ");
		sqlLogoEmpresa.append(" C.NOMBCIUDAD, ES.NOMBESTADO, E.CEP, E.NUMTELEFONO, E.NUMERO, E.CNPJ ");	
		sqlLogoEmpresa.append(" FROM MARCA M ");	
		sqlLogoEmpresa.append(" INNER JOIN EMPRESA E ON M.EMPRESA_ID = E.EMPRESA_ID ");
		sqlLogoEmpresa.append(" INNER JOIN CIUDAD C ON E.CIUDAD_ID = C.CIUDAD_ID ");
		sqlLogoEmpresa.append(" INNER JOIN ESTADO ES ON ES.ESTADO_ID = C.ESTADO_ID ");
		sqlLogoEmpresa.append(" INNER JOIN INSCRICAO_ESTADUAL IE ON IE.EMPRESA_ID = E.EMPRESA_ID ");		
		sqlLogoEmpresa.append(" WHERE M.EMPRESA_ID = :empresaId ");	
		sqlLogoEmpresa.append(" AND C.ESTADO_ID = IE.ESTADO_ID ");
		sqlLogoEmpresa.append(" AND LOGOTIPOMARCA IS NOT NULL ");
		
		NamedParameterStatement stmt = new NamedParameterStatement(conexao, sqlLogoEmpresa.toString());		
		stmt.setInt("empresaId", Integer.valueOf(parametros.get("EMPRESA_ID").toString()));
		ResultSet rset = stmt.executeQuery();
		if (rset.next()) {
			InputStream blob = rset.getBinaryStream("LOGOTIPOMARCA");
			BufferedImage image = null;
			try {
				image = ImageIO.read(blob);
			} catch (IOException e) {
				log.error("", e);
			}
			for (Cliente cliente : clientes) {
				if(tipoLayout.equals(TipoLayout.LAYOUT_CLIENTE) || validadeDescuentoValida(cliente)){
					Map<String, Object> dataResult = new HashMap<String, Object>();	
					preencherDadosCliente(cliente, dataResult);	
					preencherDadosEmpresa(dados, rset, image, dataResult);
				}
			}
		}		
		resultSet = rset;
	}
	
	private boolean validadeDescuentoValida(Cliente c){
		boolean b = false; 
		if(c.getLsClienteDescuento() != null && !c.getLsClienteDescuento().isEmpty()){
			for(ClienteDescuento cd : c.getLsClienteDescuento()){
				if(cd.getFecFin().after(Calendar.getInstance().getTime())){
					b = true;
				}
			}
		}
		return b;
	}

	private void preencherDadosEmpresa(List<Map<String, Object>> dados, ResultSet rset, BufferedImage image, Map<String, Object> dataResult) throws SQLException {
		dataResult.put("logomarca", image);
		dataResult.put("nomeEmpresa", rset.getString("DESCMARCA") != null ? rset.getString("DESCMARCA") : "");
		dataResult.put("enderecoEmpresa" , construirStringEnderecoCompletoEmpresa(rset));
		dataResult.put("cepTelefoneEmpresa", construirStringCepTelefoneEmpresa(rset));
		dataResult.put("cnpjIEstadualEmpresa", contruirStringCnpjIEstadual(rset));
		dataResult.put("local", rset.getString("NOMBCIUDAD") != null ? rset.getString("NOMBCIUDAD") + "," : "");	
		dados.add(dataResult);
	}

	private void preencherDadosCliente(Cliente cliente, Map<String, Object> dataResult) {
		
		String numeroFidelidade = null;
		
		for(ClienteFidelidad clienteFidelidad : cliente.getListClienteFidelidadActivos()){
			clienteFidelidad.getEmpresa().getEmpresaId().equals(cliente);
		}	
		
		if(cliente.getListClienteFidelidadActivos() != null && cliente.getListClienteFidelidadActivos().size() > 0){
			numeroFidelidade = cliente.getListClienteFidelidadActivos().get(0).getTarjetaFidelidad().getNumTarjeta().toString();
		}
		
		dataResult.put("numeroCliente", numeroFidelidade != null? numeroFidelidade : "");
		dataResult.put("nomeCliente", cliente.getNombcliente());	
		
		if(cliente.getLsClienteDireccion() != null && cliente.getLsClienteDireccion().size() > 0){
			ClienteDireccion clienteDireccion =  cliente.getLsClienteDireccion().get(0);
			dataResult.put("enderecoCliente", construirStringEnderecoCompletoCliente(clienteDireccion));
		}else{
			dataResult.put("enderecoCliente", "");
		}
		
		if(cliente.getEscola() != null){
			dataResult.put("escola", cliente.getEscola().getNombescola());
		}else{
			dataResult.put("escola", "");
		}
		Date validadeDate = null; 
		if(cliente.getLsClienteDescuento() != null && !cliente.getLsClienteDescuento().isEmpty() &&
				cliente.getLsClienteDescuento().get(0) != null){
			validadeDate = cliente.getLsClienteDescuento().get(0).getFecFin();
		}
		
		for(ClienteDescuento cd : cliente.getLsClienteDescuento()){
			if(validadeDate != null && cd.getFecFin().after(validadeDate) ){
				validadeDate = cd.getFecFin();
			}
		}
		
		if(validadeDate != null ){
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			dataResult.put("validade", sdf.format(validadeDate));
		}else{
			dataResult.put("validade", "" );
		}
		
		if(cliente.getLsClienteDescuento() != null && cliente.getLsClienteDescuento().size() > 0){
			StringBuilder trechosDescuento = new StringBuilder();
			for(ClienteDescuento clienteDescuento : cliente.getLsClienteDescuento()){
				if(tipoLayout.equals(TipoLayout.LAYOUT_2) && clienteDescuento.getOrigem().getParadaId().intValue() != -1 ){
					trechosDescuento.append(clienteDescuento.getOrigem().getCveparada());
				}else{
					trechosDescuento.append(clienteDescuento.getOrigem().getDescparada());
				}
								
				trechosDescuento.append(" >> ");
				if(tipoLayout.equals(TipoLayout.LAYOUT_2) && clienteDescuento.getDestino().getParadaId().intValue() != -1 ){
					trechosDescuento.append(clienteDescuento.getDestino().getCveparada());
				}else{
					trechosDescuento.append(clienteDescuento.getDestino().getDescparada());
				}
				
				trechosDescuento.append(",");
			}			
			trechosDescuento.deleteCharAt(trechosDescuento.length()-1);
			dataResult.put("trajeto", trechosDescuento.toString());
		}else{
			dataResult.put("trajeto", "");
		}
		
		preecherDataAtual(dataResult);		
	}

	private void preecherDataAtual(Map<String, Object> dataResult) {
		Calendar calendarDataAtual = Calendar.getInstance();
		Integer diaAtual = calendarDataAtual.get(Calendar.DAY_OF_MONTH);	
		Integer anoAtual = calendarDataAtual.get(Calendar.YEAR);
		String meses[] = {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro",
						 "Novembro", "Dezembro"};
		String mesAtual = meses[calendarDataAtual.get(Calendar.MONTH)];
		dataResult.put("dia", diaAtual.toString());
		dataResult.put("mes", mesAtual);
		dataResult.put("ano", anoAtual.toString());
	}

	private String construirStringEnderecoCompletoCliente(ClienteDireccion clienteDireccion) {
		StringBuilder enderecoCompletoCliente = new StringBuilder();
		enderecoCompletoCliente.append(clienteDireccion.getDesccallecomp() != null ? clienteDireccion.getDesccallecomp(): "");
		enderecoCompletoCliente.append("");
		enderecoCompletoCliente.append(clienteDireccion.getDesccalle() != null ? clienteDireccion.getDesccalle(): " " );
		enderecoCompletoCliente.append("");
		enderecoCompletoCliente.append(", Nº ");
		enderecoCompletoCliente.append(clienteDireccion.getNumexterior() != null ? clienteDireccion.getNumexterior(): " ");
		enderecoCompletoCliente.append(", BAIRRO ");
		enderecoCompletoCliente.append(clienteDireccion.getDesccolonia() != null ? clienteDireccion.getDesccolonia(): " " );
		enderecoCompletoCliente.append(", ");
		enderecoCompletoCliente.append(clienteDireccion.getDesciudad() != null ? clienteDireccion.getDesciudad(): " ");
		enderecoCompletoCliente.append("-");
		enderecoCompletoCliente.append(clienteDireccion.getDesestado() != null ? clienteDireccion.getDesestado() : " ");
		return enderecoCompletoCliente.toString();
	}

	private String contruirStringCnpjIEstadual(ResultSet rset) throws SQLException {
		String cnpj = rset.getString("CNPJ");
		String inscEstadual = rset.getString("NUMINSCRICAOESTADUAL");
		return String.format("CNPJ %s - Inscr. Estadual %s", cnpj, inscEstadual);
	}

	private String construirStringCepTelefoneEmpresa(ResultSet rset) throws SQLException {
		String cep = rset.getString("CEP");
		String fone = rset.getString("NUMTELEFONO");
		return String.format("CEP %s - Fone %s", cep, fone);
	}

	private String construirStringEnderecoCompletoEmpresa(ResultSet rset) throws SQLException {
		String logradouro = rset.getString("LOGRADOURO");
		String numero = rset.getString("NUMERO");
		String bairro = rset.getString("BAIRRO");
		String ciudad = rset.getString("NOMBCIUDAD");
		String estado = rset.getString("NOMBESTADO");
		return String.format("%s, %s - %s - %s - %s", logradouro, numero, bairro, ciudad, estado);
	}

}
