package com.mx.dla.dda.carga.suscriptor.bos;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.mx.dla.dda.admin.presupuestos.dtos.PlantillaDTO;
import com.mx.dla.dda.carga.suscriptor.daos.CargaSuscriptorDAO;
import com.mx.dla.dda.carga.suscriptor.dtos.CargaSuscripcionBD;
import com.mx.dla.dda.carga.suscriptor.dtos.CargaSuscripcionDTO;
import com.mx.dla.dda.carga.suscriptor.dtos.ParamCalculoCostoSuscriptoresDTO;
import com.mx.dla.dda.carga.suscriptor.dtos.ResponseCalculoCostoSuscriptoresDTO;
import com.mx.dla.dda.catalogos.daos.CatalogosDAO;
import com.mx.dla.dda.catalogos.dtos.EmpresaVentaDTO;
import com.mx.dla.dda.catalogos.dtos.PaisVentaDTO;
import com.mx.dla.dda.catalogos.dtos.RegionVentaDTO;
import com.mx.dla.dda.excelMapper.bos.ExcelMapperTransform;
import com.mx.dla.dda.excelMapper.context.ExcelMapperContext;
import com.mx.dla.dda.excelMapper.dtos.ExcelMapper;
import com.mx.dla.dda.excelMapper.exceptions.ExcelMapperException;
import com.mx.dla.dda.restClient.bos.DLARestClient;
import com.mx.dla.dda.restClient.bos.DLARestClientFactory;
import com.mx.dla.dda.restClient.constants.DLARestServices;
import com.mx.dla.global.bos.BaseBO;
import com.mx.dla.global.bos.ReadExcelBO;
import com.mx.dla.global.dtos.FilaExcelDTO;


@Component
public class CargaSuscriptorBO extends BaseBO{
	
	private final String []meses = {"Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"};
	
	private final DecimalFormat formateador = new DecimalFormat("###,###");
	
	@Autowired
	private CargaSuscriptorDAO cargaSuscriptorDAO;
	
	@Autowired
	private CatalogosDAO       catalogosDAO;
	
	@Autowired
	public DLARestClientFactory dlaRestClientFactory;
	
	@Autowired
	private ReadExcelBO readExcelBO;
	
	@Value("${uri.file.carga.suscriptores}")
	protected String uriCarga;
	
	private Map<Integer,Integer> mesesMap = new HashMap<Integer,Integer>();
	
	@Autowired
	protected ExcelMapperTransform excelMapperTransform;
	
	@Autowired
	private ExcelMapperContext excelMapperContext;
	
	/*@See Metodo que regresa dada un mes y año los datos de susctipones actual y de 5 meses atras.
	 * 
	 */
	public List<CargaSuscripcionDTO>  getDatosSuscripcion(Integer mes, Integer anio) throws Exception{
				  			  		
		  List<String> fechas = new ArrayList<String>();
		  CargaSuscripcionDTO suscripcion = new CargaSuscripcionDTO();
		  List<CargaSuscripcionDTO> listado = new ArrayList<CargaSuscripcionDTO>();
		  
		  try{
			  Date inicio = crearFecha("01/" + mes + "/"+ anio); 
			  for(int i=0; i<= 5; i++)
			  {
				  mesesMap.put(i, getMesFecha(inicio, i));
				  fechas.add(restarMesFecha(inicio, i));					  
				  switch(i)
				  {
				  	case 1:
					  suscripcion.setMes1(getFechaFormato(inicio,i));
					break;
				  	case 2:
					  suscripcion.setMes2(getFechaFormato(inicio,i));
					break;
				  	case 3:
					  suscripcion.setMes3(getFechaFormato(inicio,i));
					break;
				  	case 4:
					  suscripcion.setMes4(getFechaFormato(inicio,i));
					break;
				  	case 5:
					  suscripcion.setMes5(getFechaFormato(inicio,i));
					break;
				  	case 0:
					  suscripcion.setMesActual(getFechaFormato(inicio,i));
					break;
				  }	
			   }
			  			  
			  listado.add(suscripcion);
			  
			  List<EmpresaVentaDTO>    empresas     = catalogosDAO.getEmpresasVenta();			  
			  List<CargaSuscripcionBD> resultado    = cargaSuscriptorDAO.obtenerCargaSuscripciones(fechas);			  
			  boolean                  existeReg    = false;
			  boolean                  regActual    = false;
			  suscripcion = new CargaSuscripcionDTO();
			  
			  for(EmpresaVentaDTO empresa : empresas)
			  {
				  for(CargaSuscripcionBD carga: resultado)
				  {
					  if(empresa.getIdEmpresa().intValue() == carga.getIdEmpresa())
					  {						  				  					 
						  this.asignarValores(carga, suscripcion, mes);
						  existeReg    = true;
						  
						  if(carga.getMes().intValue() == mes)
							 regActual = true;						  
					  }
				  }				  
				  
				  if(existeReg)
				  {
					  if(!regActual){
						  suscripcion.setMesActual("");
						  suscripcion.setIdCarga(0l);
					  }					  					  
				  }
				  else
				  {
					  suscripcion.setIdEmpresa(empresa.getIdEmpresa());
					  suscripcion.setMesActual("");
					  suscripcion.setEmpresa(empresa.getDescripcion());
					  
					  PaisVentaDTO pais     = catalogosDAO.getPaisXId(empresa.getIdPais());
					  RegionVentaDTO region = catalogosDAO.getRegionXId(pais.getIdRegion());					
					  suscripcion.setRegion(region.getDescripcion());
					  suscripcion.setIdEmpresa((empresa.getIdEmpresa()));					  
				  }
				  this.formatearListado(suscripcion);
				  logger.debug("suscripcion "+suscripcion.toString());

				  listado.add(suscripcion);
				  
				  existeReg = false;
				  regActual = false;
				  suscripcion = new CargaSuscripcionDTO();
			  }			  
			  			  
		  }catch(Exception e){
			  logger.error("{}", e);			  
			  throw new Exception(e);
		  }		
		  
		  CargaSuscripcionDTO suspcionAux=listado.get(0);
		  listado.remove(0);
		  	Collections.sort(listado); 
		  	List<CargaSuscripcionDTO> listadoAux = new ArrayList<CargaSuscripcionDTO>();
		  	listadoAux.add(suspcionAux);
		  	listadoAux.addAll(listado);

		  return listadoAux;
	}
	
	private void asignarValores(CargaSuscripcionBD itemBD, CargaSuscripcionDTO itemDTO, Integer mes){
		
		   itemDTO.setEmpresa(itemBD.getEmpresa());
		   itemDTO.setRegion(itemBD.getRegion());
		   itemDTO.setIdEmpresa((itemBD.getIdEmpresa()));		   
		   logger.debug("B:"+itemBD.toString());
		   if(mes.intValue() == itemBD.getMes().intValue())
		   {			   			  
			   itemDTO.setIdCarga(itemBD.getIdCarga());			   
			   itemDTO.setMesActual(formateador.format(itemBD.getSuscriptores()));			   			     
		   }
		   else
		   {			  			  			   
			  for(int i=1; i<= 5; i++)
			  {
				  if(mesesMap.get(i).intValue() == itemBD.getMes().intValue())
				  {
					  if(i==1)					  
					  	 itemDTO.setMes1(formateador.format(itemBD.getSuscriptores()));
					  if(i==2)					  	  
					  	itemDTO.setMes2(formateador.format(itemBD.getSuscriptores()));
					  if(i==3)					  	  
					  	itemDTO.setMes3(formateador.format(itemBD.getSuscriptores()));
					  if(i==4)					   	  
					   	itemDTO.setMes4(formateador.format(itemBD.getSuscriptores()));
					  if(i==5)					   	  
					  	itemDTO.setMes5(formateador.format(itemBD.getSuscriptores()));											  			
				  }
			  }
		   }				   
		   logger.debug(itemDTO.toString());
	}
		
	public void actualizarSuscriptores(List<CargaSuscripcionDTO> suscriptores) throws Exception{
		
		String mes = "";
		try{			
			for(CargaSuscripcionDTO item : suscriptores)
			{
				if(item.getIdCarga() == 0 && item.getMesActual() != null)
				{	
					mes = item.getFecha();
					this.nuevoCargaSuscripcion(item);
				}
				else if(item.getIdCarga() != 0 && item.getMesActual() != null )
				{					
					mes = item.getFecha();
					this.updateCargaSuscripcion(item);
				}
				else if(item.getIdCarga() != 0 && item.getMesActual() == null )
				{
					logger.info("idcarga:" +item.getIdCarga());
					cargaSuscriptorDAO.eliminarCarga(item.getIdCarga());
				}
			}											
		}catch(Exception e){
			logger.error("{}", e);
			throw new Exception(e);
		}
		
		//Se acaba de actualizar o hacer la carga; se notifica al rest
		try{
			//if(mes.compareTo("") != 0)
			//{
				logger.info("Se inicia comunicacion para el calculo de costo.");

				ParamCalculoCostoSuscriptoresDTO request = new ParamCalculoCostoSuscriptoresDTO();
				request.setFechaMes(mes);
											
				DLARestClient client = dlaRestClientFactory.getClient(DLARestServices.COSTO_SUSCRIPTORES);			
				ResponseCalculoCostoSuscriptoresDTO response = client.get(request, ResponseCalculoCostoSuscriptoresDTO.class);

				logger.info("Se ha notificado Carga Suscriptores. Mensaje ["+response.getMensaje()+"]");
				logger.info("Se ha notificado Carga Suscriptores. Resultado ["+response.getResultado()+"]");
			//}
		}catch(Exception e){
			logger.error("Error al notificar Carga Suscriptores.",e);			
		}
	}
	
	private void nuevoCargaSuscripcion(CargaSuscripcionDTO suscriptor){		
		CargaSuscripcionBD itemBD = new CargaSuscripcionBD();
		itemBD.setIdEmpresa(suscriptor.getIdEmpresa());
		itemBD.setFecha((suscriptor.getFecha()));
		itemBD.setSuscriptores(Integer.parseInt(suscriptor.getMesActual().replace( ",", "")));		
		cargaSuscriptorDAO.nuevoCargaSuscripcion(itemBD);
	}
	
	private void updateCargaSuscripcion(CargaSuscripcionDTO suscriptor){
		CargaSuscripcionBD itemBD = new CargaSuscripcionBD();
		itemBD.setIdCarga(suscriptor.getIdCarga());		
		itemBD.setSuscriptores(Integer.parseInt(suscriptor.getMesActual().replace( ",", "")));		
		cargaSuscriptorDAO.updateCargaSuscripcion(itemBD);
	}

	private void formatearListado(CargaSuscripcionDTO item){		
		 if(item.getMes1() == null) item.setMes1("");	   		       
		 if(item.getMes2() == null) item.setMes2("");	   		       
		 if(item.getMes3() == null) item.setMes3("");	   		       
		 if(item.getMes4() == null) item.setMes4("");	   		       
		 if(item.getMes5() == null) item.setMes5("");	   		       		    
	}
	
	public String getFecha(Date fecha){
		DateFormat fechaHora = new SimpleDateFormat("dd/MM/yyyy");
		return fechaHora.format(fecha);		
	}

	public Date crearFecha(String valor) throws ParseException{
		DateFormat formatter1 = new SimpleDateFormat("dd/MM/yy");
		Date fecha = formatter1.parse(valor);
        return fecha;
	}
	
	public String restarMesFecha(Date fecha, int mes) throws ParseException{
		Calendar calFecha = Calendar.getInstance();
		calFecha.setTime(fecha);
		calFecha.add(Calendar.MONTH, (mes * -1));			
		return "01/" + (calFecha.get(Calendar.MONTH)+1) + "/" + calFecha.get(Calendar.YEAR);
	}
	
	public Integer getMesFecha(Date fecha, int mes) throws ParseException{
		Calendar calFecha = Calendar.getInstance();
		calFecha.setTime(fecha);
		calFecha.add(Calendar.MONTH, (mes * -1));			
		return calFecha.get(Calendar.MONTH)+1;
	}
	
	public String getFechaFormato(Date fecha, int mes){		
		Calendar calFecha = Calendar.getInstance();
		calFecha.setTime(fecha);
		calFecha.add(Calendar.MONTH, (mes * -1));		
		return meses[calFecha.get(Calendar.MONTH)] + "-" + calFecha.get(Calendar.YEAR);				
	}

	 public  List<CargaSuscripcionDTO> ordenar(List<CargaSuscripcionDTO> lista) {
		 try {
			  for(int j=1;j<lista.size()-1;j++) {
		             for(int i=1;i<lista.size()-1-j;i++) {
		            	// if(lista.get(i)!=null){
		            		  if (lista.get(i).getRegion().compareTo(lista.get(i+1).getRegion())>0) {
				                     String aux;
				                     aux=lista.get(i).getRegion();
				                     lista.set(i, lista.get(i+1));
				                     lista.get(i+1).setRegion(aux);
				                     
				                 } 
		            	// }
		               
		             }
		         }
		} catch (Exception e) {
			logger.error("{}", e);
		}
      
        return lista;
    }
	 
	 public Map<String, String> obtenInformacionExcel(File fileUpload, String fileName){
		 Map<String, String> informacionExcel = new HashMap<String, String>();
		 List<FilaExcelDTO> listaInformacionExcel = null;
		 try {
			 
			 listaInformacionExcel = readExcelBO.obtenerDatosExcel(uriCarga, fileUpload, fileName);
			 for(FilaExcelDTO fila:listaInformacionExcel){
				 logger.debug("[{}] -- [{}]", fila.getFila().get(0), fila.getFila().get(1));
				 informacionExcel.put(fila.getFila().get(0), fila.getFila().get(1));
			 }	 
			 
		} catch (IOException e) {
			logger.error("[{}]", e);
			logger.debug("[{}]", e);
		} catch (ExcelMapperException e) {
			logger.error("[{}]", e);
			logger.debug("[{}]", e);
		
		}		
		return informacionExcel;
	 }
	 
	 
	 public byte[] obtenPlantilla(String[] empresas) {
		 
		 byte[] plantilla = null;
		 List<PlantillaDTO> lista = new ArrayList<PlantillaDTO>();
		 ExcelMapper mapper = null;
		 
		 for(String emp:empresas){
			 PlantillaDTO li = new PlantillaDTO();
			 li.setEmpresa(emp);
			// li.setCantidad("\t");
			 lista.add(li);
		 }
		 
		 try {
			 
			 mapper = excelMapperContext.getExcelMapper("plantillaCargaSuscriptores");
			 plantilla = excelMapperTransform.transformObjectToExcel(lista, mapper, PlantillaDTO.class);
			 
		 }catch(Exception ex) {
			 logger.error("[{}]", ex);
		 }
		 

		 return plantilla;
	 }
}