package com.mx.dla.dda.admin.catalogos.tipoCambio.bos;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
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.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mx.dla.dda.admin.catalogos.tipoCambio.daos.TipoCambioDAO;
import com.mx.dla.dda.admin.catalogos.tipoCambio.dtos.MesTiposCTDTO;
import com.mx.dla.dda.admin.catalogos.tipoCambio.dtos.TipoCambioDTO;
import com.mx.dla.dda.admin.catalogos.tipoCambio.dtos.TipoCambioPaisDTO;
import com.mx.dla.dda.catalogos.daos.CatalogosDAO;
import com.mx.dla.dda.catalogos.dtos.PaisVentaDTO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.general.constants.MesesAnio;
import com.mx.dla.global.bos.BaseBO;

@Service
public class TipoCambioBO extends BaseBO {
	
	@Autowired
	private CatalogosDAO catalogosDAO;
	
	@Autowired
	private TipoCambioDAO tipoCambioDAO;
	
	
	public List<Integer> obtenerAnnios() {
		
		List<Integer> annios = new ArrayList<Integer>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		int annio = calendar.get(Calendar.YEAR) - 2;
		
		for(int i = 0; i < 4; i++) {
			annios.add(annio++);
		}
		
		return annios;
	}
	
	public List<PaisVentaDTO> obtenerPaises() throws TransaccionException{
		List<PaisVentaDTO> paises = null;
		
		try {
			paises = catalogosDAO.getPaises();
		}catch(Exception ex){
			throw new TransaccionException("Error al obtener paises.", ex);
		}
		
		return paises;
	}
	
	public List<TipoCambioDTO> obtenerNombreTipos() throws TransaccionException{
		
		List<TipoCambioDTO> nombreTipos = new ArrayList<TipoCambioDTO>();
		nombreTipos.add(new TipoCambioDTO());
		try {
			nombreTipos.addAll(tipoCambioDAO.consultaTiposCambio());
		}catch(Exception ex){
			throw new TransaccionException("Error al obtner nombres de tipos.", ex);
		}
		
		return nombreTipos;
	}
	
	public List<MesTiposCTDTO> obtenerMesTipo(Integer annio, PaisVentaDTO pais, List<TipoCambioDTO> nombreTipos) throws TransaccionException {
		
		List<MesTiposCTDTO> mesesTipo = new ArrayList<MesTiposCTDTO>();
		MesTiposCTDTO aux = null;
		MesesAnio ma = null;
		
		for(int i = 12; i > 0; i--) {
			aux = new MesTiposCTDTO();
			ma =  MesesAnio.parse("" + i);
			aux.setNombre(ma.getDesc());
			aux.setTipos(completaMesTipos(i, annio, pais.getIdPais(), nombreTipos));
			mesesTipo.add(aux);
		}
		
		return mesesTipo;
	}
	
	public List<TipoCambioPaisDTO> completaMesTipos(Integer mes, Integer annio, Long idPais, List<TipoCambioDTO> nombreTipos) throws TransaccionException{
		
		List<TipoCambioPaisDTO> mesTipos = null;
		Map<Long, TipoCambioPaisDTO> mesTiposM = new HashMap<Long, TipoCambioPaisDTO>();
		TipoCambioPaisDTO tcpDto = null;
		try{
			
			mesTipos = tipoCambioDAO.obtnerMesTipos("01/"+ mes +"/" + annio, idPais);
			Calendar calendar = Calendar.getInstance();
			calendar.set(Calendar.YEAR, annio);
			calendar.set(Calendar.MONTH, mes-1);
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			
			//logger.info("mes : [{}] -- date [{}]", mes, calendar.getTime());
			
			if(mesTipos != null){
				
				for(TipoCambioPaisDTO mt : mesTipos) {
					mesTiposM.put(mt.getIdTipoCambio(), mt);
				}
			}
			
			mesTipos = new ArrayList<TipoCambioPaisDTO>();

			for(TipoCambioDTO tc: nombreTipos){
				
				if(tc.getDescripcion() != null){
					if(mesTiposM.get(tc.getIdTipoCambio()) != null){
						tcpDto = mesTiposM.get(tc.getIdTipoCambio());				
						tcpDto.setRecuperado(true);
						tcpDto.setValor(numberFormatter(tcpDto.getValor()));
						mesTipos.add(mesTiposM.get(tc.getIdTipoCambio()));
					}else{
						tcpDto = new TipoCambioPaisDTO();
						tcpDto.setIdPais(idPais);
						tcpDto.setIdTipoCambio(tc.getIdTipoCambio());
						tcpDto.setMes(calendar.getTime());
						tcpDto.setRecuperado(false);
						mesTipos.add(tcpDto);
					}
				}
			}
			
		}catch(Exception ex){
			throw new TransaccionException("Error al obtener los meses por tipo.", ex);
		}
		
		return mesTipos;
	}
	
	private String numberFormatter(String numberS){
		NumberFormat formatter = new DecimalFormat("#0.000000");	
		String numberD = "";
		try{
			numberD = formatter.format(Double.parseDouble(numberS));
		}catch(NumberFormatException nfe){
			numberD = numberS;
		}
		return numberD;
	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean guardarCambios(List<MesTiposCTDTO> mesesTipos) throws TransaccionException{
		
		boolean respuesta = false;
		
		try{
			
			if(mesesTipos != null) {
				for(MesTiposCTDTO mt : mesesTipos) {
					
					logger.info("mes : [{}]", mt.getNombre());
					
					for(TipoCambioPaisDTO tcp : mt.getTipos()){
						
						if(tcp.getRecuperado()){
							tipoCambioDAO.actualizaTipoCambio(tcp);
						}else {
							if(tcp.getValor() != null)
								tipoCambioDAO.creaTipoCambio(tcp);
						}
					}
					
				}
				
				respuesta = true;
			}
			
		}catch(Exception ex){
			throw new TransaccionException("Error al actualizar los valores.", ex);
		}
		
		return respuesta;
	}
	
	
}