package com.mx.dla.dda.contrato.transaccion.titulos.actions;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.ibatis.executor.result.ResultMapException;
import org.springframework.beans.factory.annotation.Autowired;

import com.mx.dla.admin.dtos.UsuarioDTO;
import com.mx.dla.dda.catalogos.dtos.CatalogoDTO;
import com.mx.dla.dda.contrato.common.actions.BaseContratoAction;
import com.mx.dla.dda.contrato.generales.bos.GeneralesBO;
import com.mx.dla.dda.contrato.generales.dtos.ContratoDTO;
import com.mx.dla.dda.contrato.titulo.constants.TipoCargaDocumento;
import com.mx.dla.dda.contrato.titulo.dtos.RespuestaCargaExcel;
import com.mx.dla.dda.contrato.titulo.exception.TituloException;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.contrato.transaccion.titulos.bos.TituloTranBO;
import com.mx.dla.dda.contrato.transaccion.titulos.bos.TituloTranGridBO;
import com.mx.dla.dda.excelMapper.exceptions.ExcelMapperException;
import com.opensymphony.xwork2.Action;

public class TituloTransAction extends BaseContratoAction {

	private static final long serialVersionUID = -2801098338739181070L;

	@Autowired
	private GeneralesBO generalesBO;

	@Autowired
	private TituloTranBO tituloBO;

	@Autowired
	private TituloTranGridBO tituloTranGridBO;

	private List<CatalogoDTO> filiales;
	private List<CatalogoDTO> categorias;
	private List<CatalogoDTO> generosA;
	private List<CatalogoDTO> generosB;
	private List<CatalogoDTO> tiers;
	private List<CatalogoDTO> catSeries;
	private List<CatalogoDTO> listas;
	private List<TipoCargaDocumento> tipoCargas;
	private List<Long> listasValidas;
	private String error;
	private Long idLista;
	private Integer numTitulos;

	private String inicioLista;
	private String fileFileName;
	private InputStream fileInputStream;
	private File file;
	private String tipoCarga;
	private RespuestaCargaExcel respuestaExcel;

	public String execute() throws TransaccionException {
		ContratoDTO cto = this.inicializarContrato();
		try {
			if(cto != null) {
				tituloBO.init(cto.getIdContrato(), cto.getFechaInicio(), false);
				this.tipoCargas = tituloBO.buscaTipoCargaDocumento(cto.getIdContrato());
			}
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		}
		this.getServletRequest().setAttribute("tipoCargas", this.tipoCargas);
		return SUCCESS;
	}

	public String obtenerDatosInicio() {
		try {
			Long idContrato = getContratoSesion();
			this.inicializarCatalogos(idContrato);
			this.idLista = tituloBO.buscarListaActual(idContrato, "M").getIdLista();
			this.listas = tituloBO.buscaListas(idContrato);
			this.numTitulos = tituloBO.buscarNumTitulosContratados(idContrato);

		} catch (ResultMapException e) {
			logger.error("Error : {}", e);
			error = "Ocurrio un error con la operacion";
		} catch (SQLException e) {
			logger.error("Error : {}", e);
			error = "Ocurrio un error con la operacion";
		} catch (TransaccionException e) {
			logger.error("Error : {}", e);
			error = "Ocurrio un error con la operacion";
		} catch (IOException e) {
			logger.error("Error : {}", e);
			error = "Ocurrio un error con la operacion";
		}
		return Action.SUCCESS;
	}

	public String guardarCambiosPermanente() {
		try {
			Long idContrato = getContratoSesion();
			tituloBO.guardarCambiosPermanente(idContrato);
		} catch (Exception e) {
			logger.error("Error. guardarCambiosPermanente : ", e);
			error = "Ocurrio un error con la operacion";
		}
		return SUCCESS;
	}

	public String descargar() throws ExcelMapperException, IOException {
		try {
			byte[] bytes = tituloBO.generateExcelReport(this.idLista);
			fileInputStream = new ByteArrayInputStream(bytes);
			fileFileName = tituloBO.generaNombreDescarga();
			return SUCCESS;
		} catch (Exception e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al descargar el documento";
			return ERROR;
		}
	}

	// jun-17
	public String cargaMasiva() throws ExcelMapperException, IOException {
		try {
			Date i = new Date();
			Long idContrato = getContratoSesion();
			UsuarioDTO usuario = (UsuarioDTO) getSession().get("usuario");

			logger.debug("tipo {}", tipoCarga);
			logger.debug("inicioLista {}", inicioLista);
			logger.debug("fileFileName {}", fileFileName);

			respuestaExcel = tituloBO.cargaMasivaTitulos(this.inicioLista, idContrato, this.tipoCarga, this.file,
					this.fileFileName, this.idLista, usuario.getExpediente());

			logger.debug("Tiempo  titulosBO.cargaMasivaDeTitulos  [{}]", new Date().getTime() - i.getTime());
		} catch (TituloException e) {
			logger.error("Error ", e);
			error = e.getMessage();
		} catch (ResultMapException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		} catch (ParseException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		} catch (TransaccionException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		} catch (SQLException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		}
		return SUCCESS;
	}

	public String buscarListas() {
		try {
			Long idContrato = getContratoSesion();
			this.listas = tituloBO.buscaListas(idContrato);
		} catch (TransaccionException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		} catch (ResultMapException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		} catch (SQLException e) {
			logger.error("Error ", e);
			error = "Ocurrio un error al subir el documento";
		}
		return SUCCESS;
	}

	public String descarArchivoErrores() {

		Long idContrato = getContratoSesion();

		byte[] bytes = null;
		try {
			bytes = tituloBO.buscarArchivoDeErrores(idContrato);
		} catch (IOException e) {
			logger.error("Error ", e);
			error = "No existe documento de errores";
			return ERROR;
		}
		fileInputStream = new ByteArrayInputStream(bytes);

		Date a = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		fileFileName = "errores-" + sdf.format(a) + ".xlsx";
		logger.debug("Saco el nombre", fileFileName);
		return SUCCESS;

	}

	private ContratoDTO inicializarContrato() throws TransaccionException {
		this.setIdContrato(getContratoSesion());
		ContratoDTO ct = null;
		try {
			ct = generalesBO.obtenContrato(this.getIdContrato());
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		}
		setEstatusContrato(ct != null ? ct.getIdEstatus() : 0L);
		return ct;
	}

	private Long getContratoSesion() {
		if(this.getSession().get("idContrato") != null) {
			return (Long) this.getSession().get("idContrato");
		} else {
			return 0L;
		}
	}

	private void inicializarCatalogos(Long idContrato) throws TransaccionException {
		tituloTranGridBO.obtenerCatalogos(idContrato);
		this.filiales = tituloTranGridBO.getFiliales();
		this.categorias = tituloTranGridBO.getCategorias();
		this.generosA = tituloTranGridBO.getGenerosA();
		this.generosB = tituloTranGridBO.getGenerosB();
		this.tiers = tituloTranGridBO.getTiers();
		this.catSeries = tituloTranGridBO.getCatSeries();
		try {
			this.listasValidas = tituloBO.buscaListasValidas(idContrato);
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		}

	}

	public List<CatalogoDTO> getFiliales() {
		return filiales;
	}

	public List<CatalogoDTO> getCategorias() {
		return categorias;
	}

	public List<CatalogoDTO> getGenerosA() {
		return generosA;
	}

	public List<CatalogoDTO> getGenerosB() {
		return generosB;
	}

	public List<CatalogoDTO> getTiers() {
		return tiers;
	}

	public List<CatalogoDTO> getCatSeries() {
		return catSeries;
	}

	public List<TipoCargaDocumento> getTipoCargas() {
		return tipoCargas;
	}

	public String getError() {
		return error;
	}

	public List<CatalogoDTO> getListas() {
		return listas;
	}

	public Long getIdLista() {
		return idLista;
	}

	public String getFileFileName() {
		return fileFileName;
	}

	public InputStream getFileInputStream() {
		return fileInputStream;
	}

	public RespuestaCargaExcel getRespuestaExcel() {
		return respuestaExcel;
	}

	public Integer getNumTitulos() {
		return numTitulos;
	}

	public List<Long> getListasValidas() {
		return listasValidas;
	}

	public void setIdLista(Long idLista) {
		this.idLista = idLista;
	}

	public void setFileFileName(String fileFileName) {
		this.fileFileName = fileFileName;
	}

	public void setFileInputStream(InputStream fileInputStream) {
		this.fileInputStream = fileInputStream;
	}

	public void setFile(File file) {
		this.file = file;
	}

	public void setTipoCarga(String tipoCarga) {
		this.tipoCarga = tipoCarga;
	}

	public void setInicioLista(String inicioLista) {
		this.inicioLista = inicioLista;
	}
}