package com.ejie.u74a.service;

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

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

import com.ejie.u74a.dao.ArticuloDao;
import com.ejie.u74a.dao.MaterialDao;
import com.ejie.u74a.dao.RegistroEntradasSalidasDao;
import com.ejie.u74a.model.Articulo;
import com.ejie.u74a.model.CriteriosBusqueda;
import com.ejie.u74a.model.Idioma;
import com.ejie.u74a.model.RegistroES;
import com.ejie.u74a.model.UsuarioDetalles;
import com.ejie.u74a.util.Constants;
import com.ejie.u74a.util.Utilidades;
import com.ejie.u74a.util.exception.NegocioException;

/**
 * Clase que implementa los servicios de acceso a los datos de materiales.
 * 
 *  
 */
@Service(value = "articuloService")
@Transactional()
public class ArticuloServiceImpl implements ArticuloService {

	@Autowired()
	private ArticuloDao dao;

	@Autowired()
	private MaterialDao materialDao;

	@Autowired()
	private RegistroEntradasSalidasDao registroESDao;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#findByCriteria(CriteriosBusqueda)
	 */
	@Transactional(readOnly = true)
	@Override()
	public List<Articulo> findByCriteria(CriteriosBusqueda filtro) {
		List<Articulo> articulosLst = this.dao.findByCriteria(filtro);

		return articulosLst;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#findByCountCriteria(CriteriosBusqueda)
	 */
	@Transactional(readOnly = true)
	@Override()
	public int findByCountCriteria(CriteriosBusqueda filtro) {
		return this.dao.findByCountCriteria(filtro);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#findByCodigo(int)
	 */
	@Transactional(readOnly = true)
	@Override()
	public Articulo findByCodigo(int codigoArticulo) {
		return this.dao.findByCodigo(codigoArticulo);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#findByCodigoExtra(int)
	 */
	@Transactional(readOnly = true)
	@Override()
	public Articulo findByCodigoExtra(int codigoArticulo) {
		return this.dao.findByCodigoExtra(codigoArticulo);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#actualizarArticulo(Articulo)
	 */
	@Transactional()
	@Override()
	public Articulo actualizarArticulo(Articulo articulo) {
		if (articulo != null) {

			if (articulo.getIdiomasLst() != null || articulo.getIdiomasLst().size() > 0) {
				String idioma = articulo.getIdiomasLst().get(0).getCodigo();

				if ("".equals(idioma)) {
					throw new NegocioException("ficha.errorIdiomaObligatorio");
				}

				// Comprobar que no se inserta un idioma duplicado en el caso de materiales monolingües
				if (this.materialDao.existeIdiomaEnMaterial(idioma, articulo.getCodMaterial(),
						articulo.getCodArticulo())) {
					throw new NegocioException("ficha.errorIdiomaMaterialExistente");
				}
			}

			UsuarioDetalles usuario = Utilidades.getDetallesUsuario();
			Date hoy = new Date();
			articulo.setCodigoUsuarioModificador(Integer.parseInt(usuario.getUsername()));
			articulo.setFechaModificacion(hoy);

			articulo = this.dao.actualizarArticulo(articulo);

			// Si ha ido bien, guardar los idiomas para el articulo si es que los hay, borrando primero los que
			// pudiera haber.
			this.dao.borrarIdiomasArticulo(articulo.getCodArticulo());
			if (articulo.getIdiomasLst() != null) {

				for (Idioma idioma : articulo.getIdiomasLst()) {

					this.dao.insertarIdiomaArticulo(articulo.getCodArticulo(), idioma.getCodigo());
				}
			}

		}
		return articulo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#insertarArticulo(Articulo)
	 */
	@Transactional()
	@Override()
	public Articulo insertarArticulo(Articulo articulo) {

		if (articulo != null) {

			if (articulo.getIdiomasLst() != null || articulo.getIdiomasLst().size() > 0) {
				String idioma = articulo.getIdiomasLst().get(0).getCodigo();

				if ("".equals(idioma)) {
					throw new NegocioException("ficha.errorIdiomaObligatorio");
				}

				// Comprobar que no se inserta un idioma duplicado en el caso de materiales monolingües
				if (this.materialDao.existeIdiomaEnMaterial(idioma, articulo.getCodMaterial(),
						articulo.getCodArticulo())) {
					throw new NegocioException("ficha.errorIdiomaMaterialExistente");
				}
			}

			UsuarioDetalles usuario = Utilidades.getDetallesUsuario();
			Date hoy = new Date();
			articulo.setCodigoUsuarioModificador(Integer.parseInt(usuario.getUsername()));
			articulo.setFechaModificacion(hoy);

			articulo = this.dao.insertarArticulo(articulo);

			// Si ha ido bien, guardar los idiomas para el articulo si es que los hay.
			if (articulo.getIdiomasLst() != null) {

				for (Idioma idioma : articulo.getIdiomasLst()) {

					this.dao.insertarIdiomaArticulo(articulo.getCodArticulo(), idioma.getCodigo());
				}
			}

		}
		return articulo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#borrarArticuloIdiomas(int)
	 */
	@Transactional()
	@Override()
	public String borrarArticuloIdiomas(int codigoArticulo, String validarPdtes) {

		if ("S".equals(validarPdtes)) {

			boolean existenPdtes = this.dao.comprobarPeticionesActivasExistentes(codigoArticulo);

			if (existenPdtes) {
				return "{\"existenPdtes\": true}";
			}
		}

		this.dao.borrarIdiomasArticulo(codigoArticulo); // Revisar, creo que sobra esto por estar el delete on
														// cascade
		this.dao.borrarArticulo(codigoArticulo);
		// TODO comprobar filas afectadas y devolver error si es 0 ?
		return "{\"resultado\": \"OK\"}";

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.ArticuloService#actualizarInfoStockArticulo(Articulo)
	 */
	@Transactional()
	@Override()
	public String actualizarInfoStockArticulo(Articulo articulo) {
		UsuarioDetalles usuario = Utilidades.getDetallesUsuario();
		Date fechaModificacion = new Date();
		articulo.setCodigoUsuarioModificador(Integer.parseInt(usuario.getUsername()));
		articulo.setFechaModificacion(fechaModificacion);

		if (articulo.getModoPeticion().equals(Constants.MODO_ENVIO_EJEMPLARES)) {
			articulo.setNumEjemplares(null);
		}

		int numAfectadas = this.dao.actualizarInfoStockArticulo(articulo);
		if (numAfectadas > 0) {

			String tipo = Constants.TIPO_ES_ENTRADA;
			if (articulo.getStockAnterior() > articulo.getStock()) {
				tipo = Constants.TIPO_ES_SALIDA;
			}

			int numEjemplaresDiferencia = Math.abs(articulo.getStock() - articulo.getStockAnterior());
			// Si no hay diferencia de stock no se crea registro entrada o salida.
			if (numEjemplaresDiferencia > 0) {
				RegistroES registroES = new RegistroES();
				registroES.setCodigoArticulo(articulo.getCodArticulo());
				registroES.setCodigoOficina(usuario.getCodigoOficina());
				registroES.setFechaEntradaSalida(fechaModificacion);
				registroES.setTipo(tipo);
				registroES.setSubtipo(Constants.SUBTIPO_ES_CORRECCION_STOCK);
				registroES.setNumEjemplares(numEjemplaresDiferencia);

				this.registroESDao.insertarRegistroES(registroES);
			}
		}

		return "{\"resultado\": \"OK\"}";
	}

}
