package com.mx.dla.dda.contrato.transaccion.terminos.bos;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.mx.dla.dda.contrato.fees.daos.FeesContratoDAO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.contrato.transaccion.terminos.daos.TerminosTransaccionDAO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.ComunTerminosDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.SeccionesTerminos;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.TerminosPaisDTO;
import com.mx.dla.dda.excelMapper.bos.ExcelMapperTransform;
import com.mx.dla.dda.excelMapper.constants.ExcelMapperDataType;
import com.mx.dla.dda.excelMapper.dtos.ExcelEntityResult;
import com.mx.dla.dda.excelMapper.dtos.ExcelMapper;
import com.mx.dla.dda.excelMapper.dtos.ExcelRule;
import com.mx.dla.dda.excelMapper.exceptions.ExcelMapperException;
import com.mx.dla.global.bos.BaseBO;
import com.mx.dla.global.dtos.FilaExcelDTO;

@Component
public class TerminosTransaccionBO extends BaseBO{
		
	@Autowired
	private ExcelMapperTransform excelTransform;

	@Autowired
	private FeesContratoDAO     feesContratoDAO;
	
	@Autowired
	private TerminosTransaccionDAO dao;

	@Value("${uri.file.carga.fees}")
	private String        uriCarga;
	private String   nombreArchivo;
	private ComunTerminosDTO comun;		
					
	public ComunTerminosDTO obtenerDatosComun(Long idContrato) throws TransaccionException{
		try{
						
			comun       = dao.obtenerComun(idContrato);
			if(comun == null)
				comun = new ComunTerminosDTO();
						
			comun.setTiposCambio(dao.obtenerTiposCambio());			
			comun.setFechaInicio(feesContratoDAO.fechaInicio(idContrato));			
			comun.setFechaFin(feesContratoDAO.fechaFin   (idContrato));
			
			List<TerminosPaisDTO> formatos = dao.obtenerFormatos();
			
			String formatosS[] = new String[formatos.size()];
			for(int i=0; i<formatos.size(); i++)
				formatosS[i] = formatos.get(i).getDescripcion();
			
			comun.setFormatos(formatosS);
			comun.setPestana(this.pestanaInicial(idContrato));	
			
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Se genero un error", e);
		}
		
		return comun;
	}

	public String pestanaInicial(Long idContrato){
		  String pestana = null;
		  List<String> items = dao.obtenerPestanaActual(idContrato);
		  
		  if(items == null || items.isEmpty())
			  pestana = "premium";
		  else
		  {
			pestana = this.encontarItem(items, SeccionesTerminos.RentaPremium.getDesc()) != null ? "premium" :null;
			if(pestana == null && this.encontarItem(items, SeccionesTerminos.RentaPremier.getDesc()) != null)
				pestana = "premier";			
			if(pestana ==null && this.encontarItem(items, SeccionesTerminos.RentaLibreria.getDesc()) != null)  
				pestana = "libreria";
			if(pestana ==null && this.encontarItem(items, SeccionesTerminos.VentaMovies.getDesc()) != null)  
				pestana = "movies";
			if(pestana ==null && this.encontarItem(items, SeccionesTerminos.VentaSeries.getDesc()) != null)
				pestana = "series";					
		  }
		  return pestana;
	}
	
	public String encontarItem(List<String> items, String item){
		String pestana = null;
		for(int i=0; i<items.size();i++)
		{
			if(items.get(i).equals(item))
			   pestana = item;
		}
		return pestana;
	}
	
	public void guardarDatosComun(ComunTerminosDTO c, Long idContrato){
		dao.eliminarDatosComun(idContrato);
		dao.guardarComun(idContrato, c.getTipoCambio().longValue(), c.getInflacion());
	}

	public byte[] descargarArchivoExcel(String seccion, String operacion, List<List<String>> datos, List<String> encabezados) throws TransaccionException{
		byte[] archivo = null;
		
		try
		{
			String seccionNombre = "";
			
			if(seccion.compareTo("premium") == 0)			
				seccionNombre = "premium";															
			else if(seccion.compareTo("premier") == 0)			
				seccionNombre = "premier";
			else if(seccion.compareTo("libreria") == 0)			
				seccionNombre = "libreria";
			else if(seccion.compareTo("movies") == 0)			
				seccionNombre = "ventaPremier";
			else if(seccion.compareTo("series") == 0)			
				seccionNombre = "ventaSeries";
								
			switch(operacion)
			{
				case "min_cat":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"MGC_";						
				break;
				case "min_anio":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"MGA_";																		
				break;
				case "release":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"RD_";						
				break;
				case "precio":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"PPE_";						
				break;
				case "precio movies":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"MoviesPPE_";						
				break;
				case "precio series":
					nombreArchivo = "templateFees/dda_"+seccionNombre+"SeriesPPE_";						
				break;
			}
				
			if(datos == null)													
			   archivo = this.getFile(nombreArchivo+".xlsx");							
			else						
			   archivo = excelTransform.transformMapToExcel2(datos,encabezados);			
						
			return archivo;
			
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error al descargar el arhivo.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Se genero un error al descargar el arhivo.", e);
		} catch (IOException e) {
			throw new TransaccionException("Se genero un error al descargar el arhivo.", e);
		} catch (ExcelMapperException e) {
			throw new TransaccionException("Se genero un error al descargar el arhivo.", e);
		}
	}
		
	private byte[] getFile(String fileName) throws IOException{				  		
		  ClassLoader classLoader = getClass().getClassLoader();		  		  
		  InputStream stream = classLoader.getResourceAsStream(fileName);		  
		  byte[] byteArr = IOUtils.toByteArray(stream);
		  return byteArr;			  
	}
	
	public List<FilaExcelDTO> obtenerDatosExcel(File fileUpload, String fileName, String expediente, Long idContrato ) throws IOException, ExcelMapperException{		
		String nombreArchivo = uriCarga + idContrato + expediente + fileName;
		byte [] f = FileUtils.readFileToByteArray(fileUpload);
		File d    = new File(nombreArchivo);
		
		d.setExecutable(true, false);
		d.setReadable(true, false);
		d.setWritable(true, false);
		
		logger.debug("Absolute path [{}]  -  [{}]",d.getCanonicalPath() , d.getPath());
		FileUtils.writeByteArrayToFile(d, f);		
		
		List<FilaExcelDTO>datos = this.obtenerDatosExcel(nombreArchivo);
		
		FileUtils.deleteQuietly(d);
		logger.debug(datos.toString());
		return datos;	
	}

	public List<FilaExcelDTO> obtenerDatosExcel(String nombreArchivo) throws ExcelMapperException{
		   List<FilaExcelDTO> datos = new ArrayList<FilaExcelDTO>();

		   ExcelMapper mapper = new ExcelMapper();
		   mapper.setClassName("com.mx.dla.global.dtos.FilaExcelDTO");
		   mapper.setFirstRow(1);
			
		   List<ExcelRule> rules = new ArrayList<ExcelRule>();
		   ExcelRule er = new ExcelRule();
		   
		   er.setType(ExcelMapperDataType.string);			
		   er.setAttribute("fila");
		   rules.add(er);
		   
		   mapper.setRules(rules);			
						
		   ExcelEntityResult<Object> res = excelTransform.readExcelToObject(nombreArchivo, mapper);					   
		   
		   for(int i=0; i<res.getResult().size(); i++)
		   {
			   FilaExcelDTO fila = (FilaExcelDTO)res.getResult().get(i);
			  datos.add(fila);			  
		   }
		   
		   return datos;
	}
	
	public void calculaPagoMinGarantizado(Long idContrato){
		logger.info("inicia calculaPagoMinGarantizado: {}", idContrato);
		dao.calculaPagoMinGarantizado(idContrato);
		logger.info("termina calculaPagoMinGarantizado: {}", idContrato);

	}
	
	public String getNombreArchivo()   { return nombreArchivo; }		
	public ComunTerminosDTO getComun() { return comun; }
}