package com.rjconsultores.ventaboletos.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.rjconsultores.ventaboletos.entidad.AbastoBoleto;
import com.rjconsultores.ventaboletos.entidad.Aidf;
import com.rjconsultores.ventaboletos.entidad.Articulo;
import com.rjconsultores.ventaboletos.entidad.Clasificacion;
import com.rjconsultores.ventaboletos.entidad.DetAbastoBoleto;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Estacion;
import com.rjconsultores.ventaboletos.entidad.EstacionImpresora;
import com.rjconsultores.ventaboletos.entidad.FolioPreimpreso;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.RequisicionBoleto;
import com.rjconsultores.ventaboletos.entidad.TipoMovimentacion;
import com.rjconsultores.ventaboletos.service.AbastoBoletoService;
import com.rjconsultores.ventaboletos.service.ArticuloService;
import com.rjconsultores.ventaboletos.service.AutorizaFolioService;
import com.rjconsultores.ventaboletos.service.DetAbastoBoletoService;
import com.rjconsultores.ventaboletos.service.FolioPreimpresoService;
import com.rjconsultores.ventaboletos.service.RequisicionBoletoService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;

@Service("autorizaFolioService")
public class AutorizaFolioServiceImpl implements AutorizaFolioService {
	// Numero max de folios por estacion
	public static final Integer MAX_CANT_FOLIOS = Integer.MAX_VALUE;
	public static final Integer INICIO_FOLIO = 1;

	@Autowired
	private ArticuloService articuloService;
	@Autowired
	private RequisicionBoletoService requisicionBoletoService;
	@Autowired
	private AbastoBoletoService abastoBoletoService;
	@Autowired
	private DetAbastoBoletoService detAbastoBoletoService;
	@Autowired
	private FolioPreimpresoService folioPreimpresoService;

	@Override
	public void devolverFoliosAutomaticosImpressoraFiscal(final EstacionImpresora ei) {

		Empresa empresa = ei.getEmpresa();
		FolioPreimpreso folio = folioPreimpresoService.buscaFolioPreImpressoEstacionImpresora(ei.getEstacion(), empresa);

		if (folio != null) {
			List<DetAbastoBoleto> lsDetAbasto = detAbastoBoletoService.buscabDetAbastoBoletoAutomatico(ei.getEstacion(), folio.getNumeserie());
			if (!lsDetAbasto.isEmpty()) {

				DetAbastoBoleto dab = lsDetAbasto.get(0);

				abastoBoletoService.borrar(dab.getAbastoBoleto());
				detAbastoBoletoService.borrar(dab);
				folioPreimpresoService.borrar(folio);
			}
		}
	}

	@Override
	public Boolean noChequeFolioPreimpresos(Aidf aidf, Estacion origem, Estacion destino, String numfolioinicial, String numfoliofinal, String numseriepreimpresa,
			Empresa empresaUsuario, TipoMovimentacion tipoMovimentacion) {

		if (TipoMovimentacion.TIPO_ENVIO == tipoMovimentacion.getTipomovimentacionId() ||
				TipoMovimentacion.TIPO_TRANSFERENCIA == tipoMovimentacion.getTipomovimentacionId()) {

			FolioPreimpreso folio = folioPreimpresoService.buscaFolioPreImpressoEstacionImpresora(destino, empresaUsuario);

			RequisicionBoleto requisicionBoleto = geraRequisicionBoleto(aidf, destino, empresaUsuario);
			AbastoBoleto abastoBoleto = geraAbastoBoleto(requisicionBoleto);
			DetAbastoBoleto detAbastoBoleto = geraDetAbastoBoleto(abastoBoleto, numfolioinicial, numfoliofinal, numseriepreimpresa);
			actualizaStatusRequisicion(requisicionBoleto);

			if (folio == null) {
				FolioPreimpreso folioPreimpreso = geraFolioPreimpreso(detAbastoBoleto, numfolioinicial);

				if (folioPreimpreso.getFoliopreimpresoId() == null)
					return Boolean.FALSE;

			} else {
				actualizaFolioPreimpreso(folio, numseriepreimpresa, numfolioinicial);
			}
		}

		if (TipoMovimentacion.TIPO_TRANSFERENCIA == tipoMovimentacion.getTipomovimentacionId() ||
				TipoMovimentacion.TIPO_VOLVER == tipoMovimentacion.getTipomovimentacionId() ||
				TipoMovimentacion.TIPO_PERDIDO == tipoMovimentacion.getTipomovimentacionId())

			detAbastoBoletoService.desabilitaDetAbastos(origem, numfolioinicial, numfoliofinal, numseriepreimpresa);

		return Boolean.TRUE;

	}

	private RequisicionBoleto geraRequisicionBoleto(Aidf aidf, Estacion estacion, Empresa empresa) {

		Articulo articulo = articuloService.obtenerID(aidf.getAidfTipo().getAidftipoId());
		Clasificacion clasificacion = articulo.getClasificacion();

		PuntoVenta puntoVenta = estacion.getPuntoVenta();

		RequisicionBoleto requisicionBoleto = new RequisicionBoleto();
		requisicionBoleto.setArticulo(articulo);
		requisicionBoleto.setCantfajilla(1L);
		requisicionBoleto.setClasificacion(clasificacion);
		requisicionBoleto.setEstacion(estacion);
		requisicionBoleto.setPuntoVenta(puntoVenta);
		requisicionBoleto.setStatusenvio(Boolean.TRUE);
		requisicionBoleto.setEmpresa(empresa);

		return requisicionBoletoService.suscribir(requisicionBoleto);
	}

	private DetAbastoBoleto geraDetAbastoBoleto(AbastoBoleto abastoBoleto, String numfolioinicial, String numfoliofinal, String numseriepreimpresa) {

		Integer statusoperacion = 1;
		Long nummovimiento = detAbastoBoletoService.getSecuencia();

		DetAbastoBoleto detAbastoBoleto = new DetAbastoBoleto();
		detAbastoBoleto.setAbastoBoleto(abastoBoleto);
		detAbastoBoleto.setNummovimiento(nummovimiento);
		detAbastoBoleto.setNumseriepreimpresa(numseriepreimpresa.trim());
		detAbastoBoleto.setNumfolioinicial(numfolioinicial.trim());
		detAbastoBoleto.setNumfoliofinal(numfoliofinal.trim());
		detAbastoBoleto.setStatusfirma(Boolean.TRUE);
		detAbastoBoleto.setStatusoperacion(statusoperacion);
		detAbastoBoleto.setStatusenvio(Boolean.TRUE);

		return detAbastoBoletoService.suscribir(detAbastoBoleto);
	}

	private void actualizaStatusRequisicion(RequisicionBoleto requisicionBoleto) {
		requisicionBoleto.setStatusenvio(Boolean.FALSE);
		requisicionBoletoService.actualizacion(requisicionBoleto);
	}

	private FolioPreimpreso geraFolioPreimpreso(DetAbastoBoleto detAbastoBoleto, String numfoliopreimpreso) {

		AbastoBoleto abastoBoleto = detAbastoBoleto.getAbastoBoleto();

		FolioPreimpreso folioPreimpreso = new FolioPreimpreso();
		folioPreimpreso.setEmpresa(abastoBoleto.getEmpresa());
		folioPreimpreso.setEstacion(abastoBoleto.getEstacion());
		folioPreimpreso.setFoliopreimpreso(numfoliopreimpreso);
		folioPreimpreso.setNodoId(1);
		folioPreimpreso.setNumeserie(detAbastoBoleto.getNumseriepreimpresa());
		folioPreimpreso.setPuntoVenta(abastoBoleto.getPuntoventa());
		folioPreimpreso.setIndreplica(NumberUtils.LONG_ZERO);

		return folioPreimpresoService.suscribir(folioPreimpreso);
	}

	private FolioPreimpreso actualizaFolioPreimpreso(FolioPreimpreso folioPreimpreso, String serieFoliopreimpreso, String numfoliopreimpreso) {

		folioPreimpreso.setFoliopreimpreso(numfoliopreimpreso);
		folioPreimpreso.setNumeserie(serieFoliopreimpreso);

		return folioPreimpresoService.actualizacion(folioPreimpreso);
	}

	@Override
	public String noChequeFolioPreimpresos(EstacionImpresora estacionImpresora, boolean isImpressoraFiscal) {

		Empresa empresa = estacionImpresora.getEmpresa();
		FolioPreimpreso folio = folioPreimpresoService.buscaFolioPreImpressoEstacionImpresora(estacionImpresora.getEstacion(), empresa);

		// condição para qd o folio foi gerado indevidamente pelo cliente de venda.
		// antes de a rotina abaixo ter sido executada se o numserie é 0, é um folio inválido
		if ((folio != null) && (folio.getNumeserie().equals("0"))) {
			folioPreimpresoService.borrar(folio);
			folio = null;
		}

		if ((folio != null) && isImpressoraFiscal) {
			return "estacionServiceImpl.msg.noChequeFolioPreimpresos";
		}

		if (folio == null && estacionImpresora.getEstacionCentral() == null) {
			RequisicionBoleto requisicionBoleto = geraRequisicionBoleto(estacionImpresora.getEstacion(), empresa);
			AbastoBoleto abastoBoleto = geraAbastoBoleto(requisicionBoleto);
			DetAbastoBoleto detAbastoBoleto = geraDetAbastoBoleto(abastoBoleto);
			actualizaStatusRequisicion(requisicionBoleto);

			FolioPreimpreso folioPreimpreso = geraFolioPreimpreso(detAbastoBoleto);
			if (folioPreimpreso.getFoliopreimpresoId() == null) {
				return "MSG.Error";
			}
		}

		return StringUtils.EMPTY;
	}

	private RequisicionBoleto geraRequisicionBoleto(Estacion estacion, Empresa empresa) {

		Articulo articulo = articuloService.obtenerID(Articulo.TIPO_VENDA);
		Clasificacion clasificacion = articulo.getClasificacion();

		PuntoVenta puntoVenta = estacion.getPuntoVenta();

		RequisicionBoleto requisicionBoleto = new RequisicionBoleto();
		requisicionBoleto.setArticulo(articulo);
		requisicionBoleto.setCantfajilla(1L);
		requisicionBoleto.setClasificacion(clasificacion);
		requisicionBoleto.setEstacion(estacion);
		requisicionBoleto.setPuntoVenta(puntoVenta);
		requisicionBoleto.setStatusenvio(Boolean.TRUE);
		requisicionBoleto.setEmpresa(empresa);

		return requisicionBoletoService.suscribir(requisicionBoleto);
	}

	private AbastoBoleto geraAbastoBoleto(RequisicionBoleto requisicionBoleto) {

		Date fechaHrReq = requisicionBoleto.getFecmodif();

		Date now = Calendar.getInstance().getTime();

		Long numRequisicion = Long.parseLong(requisicionBoleto.getRequisicionboletoId().toString());

		AbastoBoleto abastoboleto = new AbastoBoleto();
		abastoboleto.setNumservidor(1);
		abastoboleto.setNumrequisicion(numRequisicion);
		abastoboleto.setCantfajilla(requisicionBoleto.getCantfajilla());
		abastoboleto.setEstacion(requisicionBoleto.getEstacion());
		abastoboleto.setArticulo(requisicionBoleto.getArticulo());
		abastoboleto.setClasificacion(requisicionBoleto.getClasificacion());
		abastoboleto.setPuntoventa(requisicionBoleto.getPuntoVenta());
		abastoboleto.setPuntoventacentral(requisicionBoleto.getPuntoVenta());
		abastoboleto.setEmpresa(requisicionBoleto.getEmpresa());
		abastoboleto.setFechorreq(fechaHrReq);
		abastoboleto.setStatusfirma(2);
		abastoboleto.setStatusEnvio(1);
		abastoboleto.setUsuarioreqId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		abastoboleto.setFechorfirma(now);
		abastoboleto.setFechorgeneracion(now);
		abastoboleto.setUsuariogeneracionId(UsuarioLogado.getUsuarioLogado().getUsuarioId());

		return abastoBoletoService.suscribir(abastoboleto);
	}

	private DetAbastoBoleto geraDetAbastoBoleto(AbastoBoleto abastoBoleto) {

		Long nummovimiento = detAbastoBoletoService.getSecuencia();
		
		Integer statusoperacion = 1;
		String numseriepreimpresa = nummovimiento.toString() + abastoBoleto.getEmpresa().getEmpresaId().toString();
		String numfolioinicial = INICIO_FOLIO.toString();
		String numfoliofinal = MAX_CANT_FOLIOS.toString();

		DetAbastoBoleto detAbastoBoleto = new DetAbastoBoleto();
		detAbastoBoleto.setAbastoBoleto(abastoBoleto);
		detAbastoBoleto.setNummovimiento(nummovimiento);
		detAbastoBoleto.setNumseriepreimpresa(numseriepreimpresa.trim());
		detAbastoBoleto.setNumfolioinicial(numfolioinicial.trim());
		detAbastoBoleto.setNumfoliofinal(numfoliofinal.trim());
		detAbastoBoleto.setStatusfirma(Boolean.TRUE);
		detAbastoBoleto.setStatusoperacion(statusoperacion);
		detAbastoBoleto.setStatusenvio(Boolean.TRUE);

		return detAbastoBoletoService.suscribir(detAbastoBoleto);
	}

	private FolioPreimpreso geraFolioPreimpreso(DetAbastoBoleto detAbastoBoleto) {

		AbastoBoleto abastoBoleto = detAbastoBoleto.getAbastoBoleto();

		FolioPreimpreso folioPreimpreso = new FolioPreimpreso();
		folioPreimpreso.setEmpresa(abastoBoleto.getEmpresa());
		folioPreimpreso.setEstacion(abastoBoleto.getEstacion());
		folioPreimpreso.setFoliopreimpreso(INICIO_FOLIO.toString());
		folioPreimpreso.setNodoId(1);
		folioPreimpreso.setNumeserie(detAbastoBoleto.getNumseriepreimpresa());
		folioPreimpreso.setPuntoVenta(abastoBoleto.getPuntoventa());
		folioPreimpreso.setIndreplica(NumberUtils.LONG_ZERO);

		return folioPreimpresoService.suscribir(folioPreimpreso);
	}
}
