package com.rjconsultores.ventaboletos.web.gui.controladores.pricing;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.zkoss.util.media.Media;
import org.zkoss.util.resource.Labels;
import org.zkoss.zhtml.Messagebox;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.Filedownload;

import com.rjconsultores.ventaboletos.entidad.PricingEspecifico;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.service.PricingEspecificoService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.web.gui.controladores.tarifas.ModificacionMasivaAliasUploadController;
import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;

@Controller("modificacionMasivaPricingEspecificoUploadController")
@Scope("prototype")
public class ModificacionMasivaPricingEspecificoUploadController extends MyGenericForwardComposer {

	private static final long serialVersionUID = 1L;

	private static final int CELL_ID_PRICING_ESPECIFICO = 0;
	private static final int CELL_NOME_PRICING_ESPECIFICO = 1;
	private static final int CELL_SERVICO = 2;
	private static final int CELL_CANAL_VENDA = 3;
	private static final int CELL_TIPO_PASSAGEIRO = 4;
	private static final int CELL_TIPO_CLASSE = 5;
	private static final int CELL_MARCA = 6;
	private static final int CELL_ORIGEM = 7;
	private static final int CELL_DESTINO = 8;
	private static final int CELL_DATA_HORA_INICIO = 9;
	private static final int CELL_DATA_HORA_INICIO_SIMULADO = 10;
	private static final int CELL_DATA_HORA_FIM = 11;
	private static final int CELL_DATA_HORA_FIM_SIMULADO = 12;
	private static final int CELL_CANCELAR = 13;

	private Media mExcel;

	int registrosAlterados = 0;
	int registrosCancelados = 0;

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


	@Autowired
	private PricingEspecificoService pricingEspecificoService;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		mExcel = (Media) Executions.getCurrent().getArg().get("mExcel");
	}

	public void onClick$btnSalvar(Event ev) throws IOException, InterruptedException, ParseException {
		atualizaPricingEspecifico();
	}

	public void atualizaPricingEspecifico() throws IOException, InterruptedException, ParseException {
		InputStream isMExcel = null;
		try {
			isMExcel = mExcel.getStreamData();
		} catch (IllegalStateException ex) {
			Messagebox.show(Labels.getLabel("modificacionMasivaPricingEspecificoController.msg.formatoInvalido"),
					Labels.getLabel("modificacionMasivaPricingEspecificoController.erro.title"),
					Messagebox.OK, Messagebox.ERROR);
			closeWindow();
			return;
		}
		Sheet sheet;
		if (mExcel.getFormat().equals("xls")) {
			HSSFWorkbook wb = new HSSFWorkbook(isMExcel);
			sheet = wb.getSheetAt(0);
		} else if (mExcel.getFormat().equals("xlsx")) {
			XSSFWorkbook wb = new XSSFWorkbook(isMExcel);
			sheet = wb.getSheetAt(0);
		} else {
			closeWindow();
			return;
		}

		int rows = sheet.getPhysicalNumberOfRows();
		List<PricingEspecifico> pricingEspecificoToUpdate = new ArrayList<PricingEspecifico>();
		StringBuilder erro = new StringBuilder();

		if (!validaSheet(sheet)) {
			Messagebox.show(Labels.getLabel("modificacionMasivaPricingEspecificoController.msg.planilhaInvalida"),
					Labels.getLabel("modificacionMasivaPricingEspecificoController.erro.title"),
					Messagebox.OK, Messagebox.ERROR);
			closeWindow();
			return;
		}

		for (int r = 1; r < rows; r++) {
			Row row = sheet.getRow(r);

			if (row == null
					|| row.getCell(0) == null
					|| (row.getCell(0).getCellType() == Cell.CELL_TYPE_STRING && (row.getCell(0).getStringCellValue().isEmpty()))
					|| (row.getCell(0).getCellType() == Cell.CELL_TYPE_STRING && row.getCell(0).getStringCellValue().equalsIgnoreCase("id alias origem"))
					|| (row.getCell(0).getCellType() == Cell.CELL_TYPE_BLANK)) {
				continue;
			}

			StringBuilder erroEntidadeNaoExistente = new StringBuilder();

			PricingEspecifico pricingEspecifico = getPrincingEspecificoPorRow(row, CELL_ID_PRICING_ESPECIFICO, erroEntidadeNaoExistente);
			Boolean cancelar = isCancelar(row);

			if (!cancelar) {
				Date dataInicialSimulada = getDatePorRow(row, CELL_DATA_HORA_INICIO_SIMULADO, erroEntidadeNaoExistente);
				Date dataFinalSimulada = getDatePorRow(row, CELL_DATA_HORA_FIM_SIMULADO, erroEntidadeNaoExistente);

				if (dataInicialSimulada == null && dataFinalSimulada == null) {
					erroEntidadeNaoExistente.append(Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraInicioSimulado")
							+ " e " + Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraFimSimulado")
							+ " Não foram informados.\n");
				}else {
					if(dataInicialSimulada!=null) {
						pricingEspecifico.setFechorinicio(dataInicialSimulada);						
					}
					if(dataFinalSimulada!=null) {
						pricingEspecifico.setFechorfin(dataFinalSimulada);
					}
				}
			} else {
				registrosCancelados++;
			}

			if (!erroEntidadeNaoExistente.toString().isEmpty()) {
				String descricaoErro = "Linha " + (row.getRowNum() + 1) + ": \n";
				log.info("Erro: \n" + descricaoErro);

				erro.append(descricaoErro);
				erro.append(erroEntidadeNaoExistente.toString());
			} else {
				pricingEspecifico.setActivo(!cancelar);
				pricingEspecificoToUpdate.add(pricingEspecifico);
			}
		}
		try {
			for (PricingEspecifico pricingEspecifico : pricingEspecificoToUpdate) {
				atualizar(pricingEspecifico);
			}
		} catch (BusinessException e) {
			e.printStackTrace();
		}

		String nomeArquivo = UsuarioLogado.getUsuarioLogado().getNombusuario()
				+ "_" + Calendar.getInstance().getTime().getTime()
				+ "_" + "retorno";
		File fNomeArquivo = File.createTempFile(nomeArquivo, ".tmp");
		FileOutputStream fos = new FileOutputStream(fNomeArquivo);

		StringBuilder textoFinal = new StringBuilder();
		textoFinal.append(registrosAlterados + " ");
		textoFinal.append(Labels.getLabel("modificacionMasivaAliasTarifasController.msg.registroSalvos"));
		textoFinal.append(" " + Labels.getLabel("modificacionMasivaPricingEspecificoController.msg.registrosCancelados1")
				+ " " + registrosCancelados + " "
				+ Labels.getLabel("modificacionMasivaPricingEspecificoController.msg.registrosCancelados2") + "\n");

		if (!erro.toString().isEmpty()) {
			textoFinal.append("--------------- ERRORS ----------------\n");
			textoFinal.append(erro.toString());
			textoFinal.append("\n---------------------------------------\n");
		}

		fos.write(textoFinal.toString().getBytes());
		fos.close();

		InputStream is = null;
		is = new FileInputStream(fNomeArquivo);
		Filedownload.save(is, "application/txt", "RetornoModMasivaPricingEspecifico.txt");
		fNomeArquivo.delete();
		closeWindow();
	}

	private void atualizar(PricingEspecifico pricingEspecifico) throws BusinessException {
		pricingEspecificoService.actualizacion(pricingEspecifico);
		registrosAlterados++;
	}

	private Date getDatePorRow(Row row, int numeroCell, StringBuilder erro) throws ParseException {
		Cell cell = row.getCell(numeroCell);
		String nome = getNomeCell(numeroCell);
		Date date =null;
		try {

			if (cell == null) {
				return null;
			}
			
			if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
				 date = cell.getDateCellValue();
			}else{
				if (cell.getStringCellValue() == null) {
					return null;
				}
				DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
				date = format.parse(cell.getStringCellValue());
			}
		
		} catch (ParseException ex) {
			erro.append("Coluna '" + nome + "' da linha " + row.getRowNum() + " esta fora do formato.\n");
			return null;
		} catch (IllegalStateException ex) {
			erro.append("Coluna '" + nome + "' da linha " + row.getRowNum() + ". Tipo da coluna divergente com dado informado. Ex.: Número no lugar do texto\n");
			return null;
		} catch (Exception ex) {
			erro.append("Coluna '" + nome + "' da linha " + row.getRowNum() + ". Erro desconhecido\n");
			return null;
		}
		return date;
	}

	private Boolean isCancelar(Row row) {
		Cell cell = row.getCell(CELL_CANCELAR);

		return cell != null && cell.getStringCellValue() != null && !cell.getStringCellValue().isEmpty();
	}

	private PricingEspecifico getPrincingEspecificoPorRow(Row row, int numeroCell, StringBuilder erro) {
		Cell cell = row.getCell(numeroCell);
		String nome = getNomeCell(numeroCell);

		if (cell == null) {
			erro.append("Coluna '" + nome + "' da linha " + row.getRowNum() + " esta vazia.");
			return null;
		}

		BigDecimal bdId = new BigDecimal(cell.getNumericCellValue());
		Integer idPricingEspecifico = bdId.intValue();
		PricingEspecifico parada = pricingEspecificoService.obtenerID(idPricingEspecifico.longValue());
		if (parada == null) {
			erro.append(nome + " : " + idPricingEspecifico + " não existe.\n");
		}
		return parada;
	}

	private String getNomeCell(int num) {

		String nome = "";
		switch (num) {
		case 0:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblIdPricingEspecifico");
			break;
		case 1:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblNomePricingEspecifico");
			break;
		case 2:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblServico");
			break;
		case 3:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblCanalVenda");
			break;
		case 4:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblTipoPassageiro");
			break;
		case 5:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblTipoClasse");
			break;
		case 6:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblMarca");
			break;
		case 7:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblOrigem");
			break;
		case 8:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDestino");
			break;
		case 9:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraInicio");
			break;
		case 10:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraInicioSimulado");
			break;
		case 11:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraFim");
			break;
		case 12:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblDataHoraFimSimulado");
			break;
		case 13:
			nome = Labels.getLabel("modificacionMasivaPricingEspecificoController.lblCancelar");
			break;
		}

		return nome;
	}

	public Media getmExcel() {
		return mExcel;
	}

	public void setmExcel(Media mExcel) {
		this.mExcel = mExcel;
	}

	private Boolean validaSheet(Sheet sheet) {

		Row header = sheet.getRow(0);

		Cell cell0 = header.getCell(CELL_ID_PRICING_ESPECIFICO);
		Cell cell1 = header.getCell(CELL_NOME_PRICING_ESPECIFICO);
		Cell cell2 = header.getCell(CELL_SERVICO);
		Cell cell3 = header.getCell(CELL_CANAL_VENDA);
		Cell cell4 = header.getCell(CELL_TIPO_PASSAGEIRO);
		Cell cell5 = header.getCell(CELL_TIPO_CLASSE);
		Cell cell6 = header.getCell(CELL_MARCA);
		Cell cell7 = header.getCell(CELL_ORIGEM);
		Cell cell8 = header.getCell(CELL_DESTINO);
		Cell cell9 = header.getCell(CELL_DATA_HORA_INICIO);
		Cell cell10 = header.getCell(CELL_DATA_HORA_INICIO_SIMULADO);
		Cell cell11 = header.getCell(CELL_DATA_HORA_FIM);
		Cell cell12 = header.getCell(CELL_DATA_HORA_FIM_SIMULADO);
		Cell cell13 = header.getCell(CELL_CANCELAR);

		if (cell0 == null
				|| cell1 == null
				|| cell2 == null
				|| cell3 == null
				|| cell4 == null
				|| cell5 == null
				|| cell6 == null
				|| cell7 == null
				|| cell8 == null
				|| cell9 == null
				|| cell10 == null
				|| cell11 == null
				|| cell12 == null
				|| cell13 == null
				|| !cell0.toString().equals(getNomeCell(CELL_ID_PRICING_ESPECIFICO))
				|| !cell1.toString().equals(getNomeCell(CELL_NOME_PRICING_ESPECIFICO))
				|| !cell2.toString().equals(getNomeCell(CELL_SERVICO))
				|| !cell3.toString().equals(getNomeCell(CELL_CANAL_VENDA))
				|| !cell4.toString().equals(getNomeCell(CELL_TIPO_PASSAGEIRO))
				|| !cell5.toString().equals(getNomeCell(CELL_TIPO_CLASSE))
				|| !cell6.toString().equals(getNomeCell(CELL_MARCA))
				|| !cell7.toString().equals(getNomeCell(CELL_ORIGEM))
				|| !cell8.toString().equals(getNomeCell(CELL_DESTINO))
				|| !cell9.toString().equals(getNomeCell(CELL_DATA_HORA_INICIO))
				|| !cell10.toString().equals(getNomeCell(CELL_DATA_HORA_INICIO_SIMULADO))
				|| !cell11.toString().equals(getNomeCell(CELL_DATA_HORA_FIM))
				|| !cell12.toString().equals(getNomeCell(CELL_DATA_HORA_FIM_SIMULADO))
				|| !cell13.toString().equals(getNomeCell(CELL_CANCELAR))) {
			return false;
		}
		return true;
	}

}
