package com.rjconsultores.ventaboletos.service.impl;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.util.resource.Labels;

import com.rjconsultores.ventaboletos.dao.TarifaGrupoContratoDAO;
import com.rjconsultores.ventaboletos.entidad.GrupoContrato;
import com.rjconsultores.ventaboletos.entidad.TarifaGrupoContrato;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.service.MudancaMassivaContratoService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.configuracioneccomerciales.TarifaGrupoContratoVO;

@Service("mudancaMassivaContratoService")
public class MudancaMassivaContratoServiceImpl implements MudancaMassivaContratoService {
	
	@Autowired
	private TarifaGrupoContratoDAO tarifaDAO;
	
	private static final Logger log = LogManager.getLogger(MudancaMassivaContratoServiceImpl.class);

	@Override
	@Transactional
	public String lerArquivo(String stream, String numContrato, GrupoContrato grupo){	
		
		StringBuilder resultado = new StringBuilder();
		StringBuilder detalhado = new StringBuilder();		

		Integer atualizados = 0;
		Integer erros = 0;

		try {
			 
			List<TarifaGrupoContratoVO> arquivosEnviados = processaArquivoEnviado(stream);
			
			if( arquivosEnviados == null ) {
				throw new BusinessException("mudancaMassivaContrato.MSG.arquivoSemTarifa");
			}
			
			Integer usuarioId = UsuarioLogado.getUsuarioLogado().getUsuarioId();
			for (TarifaGrupoContratoVO tarifa : arquivosEnviados) {
				
				try {
					if( tarifa.getNumContrato() == null && tarifa.getGrupoContratoId() == null ) {
						erros++;						
						detalhado.append(Labels.getLabel("mudancaMassivaContrato.MSG.semContratoGrupo"))
						.append(tarifa.getTarifaGrupoContratoId()).append(".\n");
					}else
						if( !tarifa.getNumContrato().equals(numContrato) && 
								!tarifa.getGrupoContratoId().equals(grupo.getGrupoContratoId())) {
							erros++;
							detalhado.append(Labels.getLabel("mudancaMassivaContrato.MSG.contratoGrupoDiferente"))
							.append(tarifa.getTarifaGrupoContratoId()).append(".\n");
					}else 
					 if( salvarTarifaVO( tarifa, usuarioId )) {
						atualizados++;
						detalhado.append(Labels.getLabel("label.processado"))
						.append(tarifa.getTarifaGrupoContratoId()).append(".\n");
					}else {
						erros++;						
						detalhado.append(Labels.getLabel("label.naoProcessado"))
						.append(tarifa.getTarifaGrupoContratoId()).append(".\n");
					}
				} catch (SQLException se) {
					detalhado.append(Labels.getLabel("mudancaMassivaContrato.MSG.dbErro"))
					.append(tarifa.getTarifaGrupoContratoId()).append(".\n");
					log.error(se);
					erros++;
				}
			}
			
			resultado.append(Labels.getLabel("label.arquivoProcessado"));
			if(erros > 0) {
				resultado.append(Labels.getLabel("label.comRessalva")).append(".\n");
			}else {
				resultado.append(Labels.getLabel("label.comSucesso")).append(".\n");
			}
			resultado.append(Labels.getLabel("label.processado")).append(atualizados).append(".\n");
			resultado.append(Labels.getLabel("label.naoProcessado")).append(erros).append(".\n");
			resultado.append(detalhado);
			return resultado.toString();

		} catch (IOException ioe) {
			resultado.append(Labels.getLabel("MSG.Error.processarArquivo"));
			log.error(ioe);
			return resultado.toString();
		} catch (RuntimeException re) {
			resultado.append( re.getMessage() );
			log.error(re);
			return resultado.toString();			
		} catch (Exception e) {
			resultado.append(Labels.getLabel("MSG.Error.processarArquivo"));
			log.error(e);
			return resultado.toString();			
		}
	}

	private List<TarifaGrupoContratoVO> processaArquivoEnviado(String stream) throws IOException  {
		String linha = null;
		List<TarifaGrupoContratoVO> arquivo = new ArrayList<TarifaGrupoContratoVO>();
		
		InputStream inputStream = converterInputStream(stream);
		
		try( BufferedReader leitor = new BufferedReader(new InputStreamReader(inputStream))){

			while ((linha = leitor.readLine()) != null) {
					TarifaGrupoContratoVO tarifa = new TarifaGrupoContratoVO();
					String[] split = linha.split(";");
					tarifa.setTarifaGrupoContratoId( split[0] );
					tarifa.setNumContrato(split[1]);
					tarifa.setGrupoContratoId(split[2]);
					tarifa.setCveOrigem(split[3]);
					tarifa.setDescOrigem(split[4]);
					tarifa.setCveDestino(split[5]);
					tarifa.setDescDestino(split[6]);
					tarifa.setTarifa(split[7]);
					arquivo.add(tarifa);
			}
		}
		
		return arquivo;
	}

	
	@Override
	@Transactional(readOnly = false)
	public boolean salvarTarifaVO(TarifaGrupoContratoVO tarifaVO, Integer usuarioId) throws SQLException{
		TarifaGrupoContrato tarifa = tarifaDAO.obterTarifaPeloVo( tarifaVO );
	
		tarifa.setActivo(false);
		tarifa.setUsuarioId(usuarioId);
		tarifa.setFecModif(Calendar.getInstance().getTime());		
		tarifaDAO.actualizacion(tarifa);
		
		TarifaGrupoContrato tarifanew = duplicaTarifa(tarifa);
		tarifanew.setActivo(true);
		tarifanew.setTarifa(tarifaVO.getTarifa());
		tarifanew.setUsuarioId(usuarioId);
		tarifanew.setFecModif(Calendar.getInstance().getTime());
		tarifaDAO.suscribir(tarifanew);
				
		return tarifanew.getTarifaGrupoContratoId()!=null;

	}
	
	private TarifaGrupoContrato duplicaTarifa(TarifaGrupoContrato tarifa) {
		TarifaGrupoContrato novo = new TarifaGrupoContrato();
		novo.setTarifa(tarifa.getTarifa());
		novo.setOrigem(tarifa.getOrigem());
		novo.setDestino(tarifa.getDestino());
		novo.setIndCobertura(tarifa.isIndCobertura());
		novo.setGrupoContrato(tarifa.getGrupoContrato());
		novo.setClaseServicio(tarifa.getClaseServicio());
		novo.setActivo(tarifa.isActivo());
		novo.setUsuarioId(tarifa.getUsuarioId());
		novo.setFecModif(Calendar.getInstance().getTime());
		return novo;
	}

	private InputStream converterInputStream(String in) throws IOException {
		byte[] buff = in.getBytes(StandardCharsets.UTF_8);
		return new ByteArrayInputStream(buff);
	}
	

}
