/*
 * 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.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.dao.BoletoDAO;
import com.rjconsultores.ventaboletos.entidad.Boleto;
import com.rjconsultores.ventaboletos.entidad.PtoVtaSeguro;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.RutaCombinacion;
import com.rjconsultores.ventaboletos.entidad.Usuario;
import com.rjconsultores.ventaboletos.service.BoletoService;
import com.rjconsultores.ventaboletos.service.PuntoVentaService;
import com.rjconsultores.ventaboletos.service.RutaCombinacionService;
import com.rjconsultores.ventaboletos.service.UsuarioService;
import com.rjconsultores.ventaboletos.utilerias.MoneyHelper;

/**
 * 
 * @author Fabricio
 */
@Service("boletoService")
public class BoletoServiceImpl implements BoletoService {

	@Autowired
	private BoletoDAO boletoDAO;
	

	@Autowired
	private PuntoVentaService puntoVentaService;

	@Autowired
	private UsuarioService usuarioService;

	@Autowired
	private RutaCombinacionService rutaCombinacionService;

	
	public Boleto buscarPeloImeiDoDispositivo(String imei) {
		return boletoDAO.buscarPeloImeiDoDispositivo(imei);
	}
	
	@Override
	@Transactional
	public Boleto suscribir(Boleto boleto) {
		return boletoDAO.suscribir(boleto);
	}
	
	@Override
	@Transactional
	public void criaBoletoReserva(String unoAsientoSelec, Integer unaCorridaId, Date unaFecCorrida,
			Integer unoTerminalOrigenId, Integer unoTerminalDestinoId, Integer unoTipoVenta, Integer unaCategoriaSelec,
			String unoNumeOperacion, Integer unUsuarioId, Integer unPuntoVenta, Integer unClienteId, Integer rutaId, 
			BigDecimal tarifa, Long tempoReserva, Integer estacionId, String docCPF, String numFidelidade, Integer claseservicioId, 
			Short marcaId, Date fecViaje,  Integer empresaCorridaId, String nombPassageiro, BigDecimal valorSeguro, 
			BigDecimal valorTaxaEmbarque, BigDecimal valorPedagio) throws Exception {

		PuntoVenta miPuntoVenta = puntoVentaService.obtenerID(unPuntoVenta.intValue());
		Boleto miBoletoTemporal = new Boleto();
		atualizaValoresTarifaPedagioSeguroTaxaEmbarque(tarifa, empresaCorridaId, valorSeguro, valorTaxaEmbarque, valorPedagio, miPuntoVenta, miBoletoTemporal);
		miBoletoTemporal.setBoletoId(formataBoletoId(getSequenciaBoletoId()));
		miBoletoTemporal.setBoletooriginalId(miBoletoTemporal.getBoletoId());
		// Sempre Categoria Normal (1)
		miBoletoTemporal.setCategoriaId(Constantes.TPV_DIRECTO_NORMAL.intValue() );
		miBoletoTemporal.setClienteId(unClienteId);
		miBoletoTemporal.setClaseservicioId(claseservicioId.byteValue());
		miBoletoTemporal.setDestinoId(unoTerminalDestinoId);		
		miBoletoTemporal.setDesctipodoc("CPF");
		miBoletoTemporal.setDescnumdoc(docCPF);
		miBoletoTemporal.setEmpresacorridaId(empresaCorridaId);
		miBoletoTemporal.setEmpresapuntoventaId(miPuntoVenta.getEmpresa().getEmpresaId());
		miBoletoTemporal.setEstacionId(estacionId);
		miBoletoTemporal.setFeccreacion(new Date());
		miBoletoTemporal.setFecmodif(new Date());
		miBoletoTemporal.setFechorventa(new Date());
		miBoletoTemporal.setFechorventaH(new Date());
		miBoletoTemporal.setFechorviaje(fecViaje);
		miBoletoTemporal.setFeccorrida(unaFecCorrida);
		miBoletoTemporal.setCorridaId(unaCorridaId);
		miBoletoTemporal.setIndcancelacion(Boolean.FALSE);
		miBoletoTemporal.setIndreimpresion(Boolean.FALSE);
		miBoletoTemporal.setIndextraviado(Boolean.FALSE);
		miBoletoTemporal.setIndstatusoperacion("F");
		miBoletoTemporal.setIndcancelacion(Boolean.FALSE);
		miBoletoTemporal.setIndreplica(Boolean.FALSE);
		miBoletoTemporal.setIndstatusboleto("S");
		miBoletoTemporal.setIndreimpresion(Boolean.FALSE);
		miBoletoTemporal.setImporteoutros(BigDecimal.ZERO);
		miBoletoTemporal.setMarcaId(marcaId);
		miBoletoTemporal.setMonedaId(1);
		miBoletoTemporal.setNodoId((byte) 1);
		miBoletoTemporal.setNumkmviaje(
				calcularKmViaje(rutaId, unoTerminalOrigenId, unoTerminalDestinoId));
		miBoletoTemporal.setNombpasajero(nombPassageiro);
		miBoletoTemporal.setNumasiento(unoAsientoSelec);
		miBoletoTemporal.setNumfidelidad(numFidelidade);
		miBoletoTemporal.setNumoperacion(formataNumOperacion(getSequenciaNumOperacion()));
		miBoletoTemporal.setNumreservacion(formataNumReservacion(getSequenciaNumReservacion()));
		miBoletoTemporal.setOrigenId(unoTerminalOrigenId);
		miBoletoTemporal.setPreciopricing(BigDecimal.ZERO);
		miBoletoTemporal.setPorccategoria(null);
		miBoletoTemporal.setPuntoVentaId(unPuntoVenta.intValue());
		miBoletoTemporal.setPtovtaventaId(miPuntoVenta.getPuntoventaId());
		miBoletoTemporal.setRutaId(rutaId);
		miBoletoTemporal.setTemporeservafidelidade(tempoReserva!=null ? tempoReserva.intValue() : 0);
		miBoletoTemporal.setTipoventaId(unoTipoVenta.byteValue());
		Usuario usuario = usuarioService.obtenerID(unUsuarioId);
		miBoletoTemporal.setUsuarioautorizacionId(usuario.getUsuarioUbicacionActivoList().get(0).getUsuarioubicacionId());
		miBoletoTemporal.setUsuario(usuario);
		miBoletoTemporal.setActivo(true);
		// Cria boleto de reserva
		boletoDAO.insertBoletoReserva(miBoletoTemporal);

	}

	/**
	 * Verifica e atualiza valores tarifa, pedágio, seguro e taxa de embarque.
	 * Sendo que o seguro e taxa de embarque somente serão setados caso no ponto de venda marcado como vende default. 
	 * @param tarifa
	 * @param empresaCorridaId
	 * @param valorSeguro
	 * @param valorTaxaEmbarque
	 * @param valorPedagio
	 * @param miPuntoVenta
	 * @param miBoletoTemporal
	 */
	private void atualizaValoresTarifaPedagioSeguroTaxaEmbarque(BigDecimal tarifa, Integer empresaCorridaId, BigDecimal valorSeguro, 
			BigDecimal valorTaxaEmbarque, BigDecimal valorPedagio, PuntoVenta miPuntoVenta, Boleto miBoletoTemporal) {
		BigDecimal miPrecio = MoneyHelper.arredondar(tarifa) ;
		miBoletoTemporal.setImportepedagio(valorPedagio);
		miBoletoTemporal.setPreciopagado(miPrecio);
		miBoletoTemporal.setPreciobase(miPrecio);
		if(miPuntoVenta !=null && miPuntoVenta.getPtovtaSeguroList() !=null) {
			for (PtoVtaSeguro ptoVtaSeguro : miPuntoVenta.getPtovtaSeguroList()) {
				if(empresaCorridaId.equals(ptoVtaSeguro.getEmpresa().getEmpresaId()) && Boolean.TRUE.equals(miPuntoVenta.getActivo())) {
					if(Boolean.TRUE.equals(ptoVtaSeguro.getIndEstanTasaEmbarque())) {
						miBoletoTemporal.setImportetaxaembarque(valorTaxaEmbarque);
					}
					if(Boolean.TRUE.equals(ptoVtaSeguro.getIndEstanSegTabela())) {
						miBoletoTemporal.setImporteseguro(valorSeguro);
					}
					break;
				}
				
			}
		}
	}

	public BigDecimal calcularKmViaje(int rutaId, Integer unoOrigenId, Integer unoDestinoId) {
		RutaCombinacion rutaCombinacion = rutaCombinacionService.busquedaTramoRutaOrigemDestino(rutaId, unoOrigenId, unoDestinoId);
		return rutaCombinacion.getTramo().getKmReal();

	}
	
	String getSequenciaBoletoId(){
		return boletoDAO.getSequenciaBoletoId();
	}
	
	String getSequenciaNumOperacion(){
		return boletoDAO.getSequenciaNumOperacion();
	}
	
	String getSequenciaNumReservacion(){
		return boletoDAO.getSequenciaNumReservacion();
	}
	
	/**
	 * Foemata boleto Id com 15 dígitos conforme Totalbus
	 * @param boletoSeq
	 * @return
	 */
	public Long formataBoletoId(String boletoSeq){
		String valor = "1" + String.format("%013d", Integer.valueOf(boletoSeq).intValue());
		return Long.valueOf(valor);
	}
	
	public String formataNumOperacion(String numOperacionSeq){
		return  "01" + (String.format("%010d", Integer.valueOf(numOperacionSeq).intValue()));
	}
	
	public String formataNumReservacion(String numReservacopnSeq){
		return  "01" + (String.format("%010d",  Integer.valueOf(numReservacopnSeq).intValue()));
	}

	public boolean isExisteBoletoPorCorrida(Integer corridaId, Date fecCorrida) {
		return boletoDAO.isExisteBoletoPorCorrida(corridaId, fecCorrida);

	}
	
	public boolean isExisteBoletoPorCorridaOrigemIdOuDestinoId(Integer corridaId, Date fecCorrida, Integer origemId, Integer destinoId) {
		return boletoDAO.isExisteBoletoPorCorridaOrigemIdOuDestinoId(corridaId, fecCorrida, origemId, destinoId);

	}

}
