/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rjconsultores.ventaboletos.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.TarifaDAO;
import com.rjconsultores.ventaboletos.entidad.Categoria;
import com.rjconsultores.ventaboletos.entidad.ClaseServicio;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Marca;
import com.rjconsultores.ventaboletos.entidad.Moneda;
import com.rjconsultores.ventaboletos.entidad.OrgaoConcedente;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.Plaza;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.entidad.RutaCombinacion;
import com.rjconsultores.ventaboletos.entidad.Tarifa;
import com.rjconsultores.ventaboletos.entidad.TarifaCategoria;
import com.rjconsultores.ventaboletos.entidad.TarifaHist;
import com.rjconsultores.ventaboletos.entidad.TarifaMinima;
import com.rjconsultores.ventaboletos.entidad.TarifaTipoptovta;
import com.rjconsultores.ventaboletos.entidad.TipoPuntoVenta;
import com.rjconsultores.ventaboletos.entidad.Tramo;
import com.rjconsultores.ventaboletos.entidad.Via;
import com.rjconsultores.ventaboletos.entidad.VigenciaTarifa;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.service.LogAuditoriaService;
import com.rjconsultores.ventaboletos.service.MonedaService;
import com.rjconsultores.ventaboletos.service.RutaService;
import com.rjconsultores.ventaboletos.service.TarifaHistService;
import com.rjconsultores.ventaboletos.service.TarifaMinimaService;
import com.rjconsultores.ventaboletos.service.TarifaService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.comissao.TarifaVO;

/**
 * 
 * @author rodrigo
 */
@Service("tarifaService")
public class TarifaServiceImpl implements TarifaService {

	@Autowired
	private TarifaDAO tarifaDAO;
	@Autowired
	private TarifaHistService tarifaHistService;
	@Autowired
	private MonedaService monedaService;
	@Autowired
	private TarifaMinimaService tarifaMinimaService;
	@Autowired
	private RutaService rutaService;
	
	@Autowired
	private LogAuditoriaService logAuditoriaService;
	
	private static final Logger log = LogManager.getLogger(TarifaServiceImpl.class);

	public List<Tarifa> obtenerTodos() {
		return tarifaDAO.obtenerTodos();
	}

	@Transactional(readOnly = true)
	public Tarifa obtenerID(Integer id) {
		Tarifa tarifa = tarifaDAO.obtenerID(id);
		try {
			tarifa.clonar();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return tarifa;
	}

	private void cadastrarTarifaHistorico(Tarifa entidad) {
		TarifaHist th = new TarifaHist();
		th.setActivo(entidad.getActivo());
		th.setClaseServicio(entidad.getClaseServicio());
		th.setFecmodif(entidad.getFecmodif());
		th.setMarca(entidad.getMarca());
		th.setMoneda(entidad.getMoneda());
		th.setPrecio(entidad.getPrecio());
		th.setPreciooriginal(entidad.getPreciooriginal());
		th.setStatustarifa(entidad.getStatustarifa());
		th.setUsuarioId(entidad.getUsuarioId());
		th.setVigenciaTarifa(entidad.getVigenciaTarifa());

		th = tarifaHistService.suscribir(th);
	}

	@Transactional
	public Tarifa suscribir(Tarifa entidad) {
		entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.TRUE);
		if (entidad.getPrecio() != null) {
			entidad.setPrecio(entidad.getPrecio().setScale(2, RoundingMode.HALF_UP));
		}
		if (entidad.getPreciooriginal() != null) {
			entidad.setPreciooriginal(entidad.getPreciooriginal().setScale(2, RoundingMode.HALF_UP));
		}
		if (entidad.getPrecioredabierto() != null) {
			entidad.setPrecioredabierto(entidad.getPrecioredabierto().setScale(2, RoundingMode.HALF_UP));
		}
		cadastrarTarifaHistorico(entidad);
		
		logAuditoriaService.auditar(null, entidad, entidad.getMarca() != null && entidad.getMarca().getEmpresa() != null ? entidad.getMarca().getEmpresa().getEmpresaId() : null);
		
		return tarifaDAO.suscribir(entidad);
		
	}

	@Transactional
	public Tarifa actualizacion(Tarifa entidad) {
		try {
			
			entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			entidad.setFecmodif(Calendar.getInstance().getTime());
			entidad.setActivo(Boolean.TRUE);
			if (entidad.getPrecio() != null) {
				entidad.setPrecio(entidad.getPrecio().setScale(2, RoundingMode.HALF_UP));
			}
			if (entidad.getPreciooriginal() != null) {
				entidad.setPreciooriginal(entidad.getPreciooriginal().setScale(2, RoundingMode.HALF_UP));
			}
			if (entidad.getPrecioredabierto() != null) {
				entidad.setPrecioredabierto(entidad.getPrecioredabierto().setScale(2, RoundingMode.HALF_UP));
			}
	
			// Rafael: Segundo a Letícia, não pode atualizar o DOLAR caso haja uma
			// atualização de preço, os dolores somente são gerados na inclusão de preço.
	
			// Tarifa tarifa = this.obtenerID(entidad.getTarifaId());
			// entidad.setLsTarifaCategoria(tarifa.getLsTarifaCategoria());
			// entidad.setLsTarifaTipoptovta(tarifa.getLsTarifaTipoptovta());
	
			cadastrarTarifaHistorico(entidad);
			// cadastrarTarifaMonedaEstrangeira(entidad);
			
			
			Tarifa originalClone = entidad.getCloneObject();
			
			tarifaDAO.updateTarifa(entidad);
			
			logAuditoriaService.auditar(originalClone, entidad, entidad.getMarca() != null && entidad.getMarca().getEmpresa() != null ? entidad.getMarca().getEmpresa().getEmpresaId() : null);
			
			return entidad;
		
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	@Transactional
	public void borrar(Tarifa entidad) {
		for (TarifaCategoria pricing : entidad.getLsTarifaCategoria()) {
			pricing.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			pricing.setFecmodif(Calendar.getInstance().getTime());
			pricing.setActivo(Boolean.FALSE);
		}

		for (TarifaTipoptovta pricing : entidad.getLsTarifaTipoptovta()) {
			pricing.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			pricing.setFecmodif(Calendar.getInstance().getTime());
			pricing.setActivo(Boolean.FALSE);
		}

		entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.FALSE);

		cadastrarTarifaHistorico(entidad);
		
		logAuditoriaService.auditarExclusao(entidad, entidad.getMarca() != null && entidad.getMarca().getEmpresa() != null ? entidad.getMarca().getEmpresa().getEmpresaId() : null);

		tarifaDAO.actualizacion(entidad);
	}

	public boolean existe(Marca marca, Tramo tramo, Moneda moneda, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Ruta ruta, OrgaoConcedente orgaoConcedente) {
		return tarifaDAO.existe(marca, tramo, moneda, claseServicio, vigenciaTarifa, ruta, orgaoConcedente);
	}

	public List<Tarifa> pesquisar(Marca marca, Parada origem, Parada destino, Moneda moneda,
			ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa,
			Categoria categoria, TipoPuntoVenta tipoPuntoVenta) {
		return tarifaDAO.pesquisar(marca, origem, destino, moneda, claseServicio, vigenciaTarifa,
				categoria, tipoPuntoVenta);
	}

	public Tarifa buscar(Tramo tramo, Marca marca, ClaseServicio claseServicio,
			VigenciaTarifa vigenciaTarifa, Moneda moneda, Ruta ruta) {
		return tarifaDAO.buscar(tramo, marca, claseServicio, vigenciaTarifa, moneda, ruta);
	}

	public List<Tarifa> buscarPorVigencia(VigenciaTarifa vigencia, Empresa empresa) {
		return tarifaDAO.buscarTarifasAtivasInativasPorVigencia(vigencia, empresa);
	}

	public Boolean podeAlterarTarifaMinima(Tarifa tarifa, Marca marca, Parada origem,
			Parada destino, ClaseServicio claseServicio, Plaza plaza, Moneda moneda, VigenciaTarifa vigenciaTarifa) {

		Boolean podeAlterarTarifaMinima = Boolean.TRUE;

		List<TarifaMinima> lsTarifaMinima = tarifaMinimaService.pesquisarEspecifico(marca, origem, destino, claseServicio, moneda,vigenciaTarifa);

		if (lsTarifaMinima.isEmpty()) {
			lsTarifaMinima = tarifaMinimaService.pesquisarOrigemDestinoTodos(marca, origem, destino, claseServicio, moneda,vigenciaTarifa);
		}

		log.debug("Moneda : " + moneda.getDescmoneda());
		log.debug("preço  : " + tarifa.getPrecio());

		for (TarifaMinima tm : lsTarifaMinima) {
			if (tarifa.getPrecio().compareTo(tm.getImportetarifa()) == -1) {
				podeAlterarTarifaMinima = Boolean.FALSE;
				log.debug("Tarifa Minima ID: " + tm.getTarifaminimaId());
				log.debug("Tarifa Minima Origen : " + tm.getOrigem().getDescparada());
				log.debug("Tarifa Minima Destino: " + tm.getDestino().getDescparada());
				log.debug("Tarifa Minima Marca  : " + tm.getMarca().getDescmarca());
				log.debug("Tarifa Minima Clase  : " + tm.getClaseServicio().getDescclase());
				log.debug("Tarifa Minima Moneda : " + tm.getMoneda().getDescmoneda());
				log.debug("Tarifa Minima        : " + tm.getImportetarifa() + " Valor Alterado: " + tarifa.getPrecio());
			}
		}

		return podeAlterarTarifaMinima;
	}
	
	public List<Tarifa> buscarExisteVigencia(VigenciaTarifa vigenciaTarifa) {
		return tarifaDAO.buscarTarifasAtivasPorVigencia(vigenciaTarifa);
	}
	
	
	// Metodo para gerar todas as tarifas possiveis
	@Transactional
	public Boolean generarTarifas(VigenciaTarifa vigencia, Marca marca) {

		// Lista de Rutas
		List<Ruta> lsRuta = rutaService.obtenerTodos();
		try {
			for (Ruta r : lsRuta) {
				Ruta ruta = rutaService.obtenerID(r.getRutaId());

				// Lista de Combinações
				List<RutaCombinacion> lsRutaCombinacion = ruta.getRutaCombinacionList();
				for (RutaCombinacion rc : lsRutaCombinacion) {

					Tarifa tarifa = new Tarifa();
					// Valor de 6 Pesos por Default
					tarifa.setPrecio(BigDecimal.valueOf(6));
					tarifa.setPreciooriginal(BigDecimal.ZERO);
					// Pesos Mexicano
					tarifa.setMoneda(monedaService.obtenerID(1));
					// Marca... informado antes
					// Vigencia... informado antes
					tarifa.setVigenciaTarifa(vigencia);
					tarifa.setMarca(marca);

					tarifa.setClaseServicio(r.getClaseServicio());
					tarifa.setTramo(rc.getTramo());

					// Tramo-Marca-Classe-Vigencia-Moneda
					boolean existe = tarifaDAO.existe(tarifa.getMarca(), tarifa.getTramo(), tarifa.getMoneda(), tarifa.getClaseServicio(), tarifa.getVigenciaTarifa(), tarifa.getRuta(), tarifa.getOrgaoConcedente());

					if (!existe) {
						tarifa.setFecmodif(Calendar.getInstance().getTime());
						tarifa.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
						tarifa.setActivo(Boolean.TRUE);
						tarifa.setStatustarifa("L");

						log.debug("Tarifa: Ruta " + ruta.getDescruta() + " - " + ruta.getRutaId() + " Tramo: " + tarifa.getTramo().getTramoId()
								+ " Marca " + marca + " Vigencia: " + vigencia);
						
						tarifa = tarifaDAO.suscribir(tarifa);
						
						logAuditoriaService.auditar(null, tarifa, tarifa.getMarca() != null && tarifa.getMarca().getEmpresa() != null ? tarifa.getMarca().getEmpresa().getEmpresaId() : null);
					}
				}
			}
		} catch (Exception e) {
			log.debug("ERRO al generar tarifas", e);
			return false;
		}
		return true;
	}

	@Override
	public boolean buscarTarifaExisteTramo(Tramo tramo) {
		return tarifaDAO.buscarTarifaExisteTramo(tramo);
	}

	@Override
	public void copiarTarifas(VigenciaTarifa vigenciaTarifaOrigem, VigenciaTarifa vigenciaTarifaDestino, Empresa empresa, boolean excluirTarifasDestino) throws BusinessException {
		tarifaDAO.copiarTarifas(vigenciaTarifaOrigem, vigenciaTarifaDestino, empresa, excluirTarifasDestino);
	}

	@Override
	public boolean existeTarifas(VigenciaTarifa vigenciaTarifa) {
		return tarifaDAO.existeTarifas(vigenciaTarifa);
	}
	
	@Override
	public void excluirTodasTarifas(Moneda moneda, Marca marca, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Parada origem, 
	Parada destino, Categoria categoria, TipoPuntoVenta tipoPuntoVenta, Ruta ruta, Via via, Boolean vende){
		tarifaDAO.excluirTodasTarifas(moneda, marca, claseServicio, vigenciaTarifa, origem, destino, categoria, tipoPuntoVenta, ruta, via, vende, UsuarioLogado.getUsuarioLogado().getUsuarioId());
	}

	@Override
	public List<Tarifa> obterTarifaOficialPorFiltro(Moneda moneda, Marca marca, List<Marca> lsMarcas, Parada origem, Parada destino, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Categoria categoria, TipoPuntoVenta tipoPuntoVenta, Ruta ruta, Via via, Boolean vende) {
		return converterVo(tarifaDAO.obterTarifaOficialPorFiltroVO(moneda, marca, lsMarcas, origem, destino, claseServicio, vigenciaTarifa, categoria, tipoPuntoVenta, ruta, via, vende));

	}
	
	public List<Tarifa> converterVo(List<TarifaVO> lsTarifaVo){
		List<Tarifa> lsTarifa= new ArrayList<Tarifa>();
		Tarifa ta;
		Parada origem;
		Parada destino;
		Tramo tramo;
		Marca marca;
		Via via;
		VigenciaTarifa vi;
		
		for(TarifaVO t:lsTarifaVo){
			 ta= new Tarifa();
			 ta.setTarifaId(t.getTarifaid());
			 ta.setPrecio(t.getPrecio());
			 ta.setPreciooriginal(t.getPreciooriginal());
			 ta.setImportepedagio(t.getImportepedagio());
			 ta.setImporteseguro(t.getImporteseguro());
			 ta.setImportetaxaembarque(t.getImportetaxaembarque());
			 ta.setImporteoutros(t.getImporteoutros());
			 ta.setStatustarifa(t.getStatustarifa());
			 ta.setImporteTPP(t.getImportetpp());
			 origem = new Parada();
			 origem.setDescparada(t.getDescparadaOrigem());
			 destino = new Parada();
			 destino.setDescparada(t.getDescparadaDestino());
			 via =new Via();
			 via.setNombvia(t.getNomeVia());
			 tramo = new Tramo();
			 tramo.setOrigem(origem);
			 tramo.setDestino(destino);
			 tramo.setVia(via);
			 ta.setTramo(tramo);
			 marca= new Marca();
			 marca.setDescmarca(t.getDescMarca());
			 ta.setMarca(marca);
			 vi= new VigenciaTarifa();
			 vi.setFeciniciovigencia(t.getFeciniciovigencia());
			 vi.setFecfinvigencia(t.getFecfimvigencia());
			 ta.setVigenciaTarifa(vi);
			 OrgaoConcedente or = new OrgaoConcedente();
			 or.setDescOrgao(t.getDescorgao());
			 ta.setOrgaoConcedente(or);
			 ClaseServicio cl = new ClaseServicio();
			 cl.setDescclase(t.getDescclasse());
			 ta.setClaseServicio(cl);
			 Ruta r = new Ruta();
			 r.setPrefixo(t.getRutaprefixo());
			 r.setNumRuta(t.getNumruta());
			 ta.setRuta(r);
			 lsTarifa.add(ta);
			
			
		}
		return lsTarifa ;
	}

}
