package com.ejie.u74a.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.u74a.dao.ArticuloDao;
import com.ejie.u74a.dao.OficinaDao;
import com.ejie.u74a.dao.PeticionDao;
import com.ejie.u74a.dao.UbicacionDao;
import com.ejie.u74a.model.Articulo;
import com.ejie.u74a.model.ArticuloSolicitado;
import com.ejie.u74a.model.FichaSolicitud;
import com.ejie.u74a.model.Oficina;
import com.ejie.u74a.model.Peticion;
import com.ejie.u74a.model.Ubicacion;
import com.ejie.u74a.model.UsuarioDetalles;
import com.ejie.u74a.util.Constants;
import com.ejie.u74a.util.Utilidades;
import com.ejie.u74a.util.exception.ParameterValidationException;

/**
 * Clase que implementa los servicios para la solicitud de materiales.
 * 
 *  
 */
@Service(value = "solicitudService")
@Transactional()
public class SolicitudServiceImpl implements SolicitudService {

	@Autowired()
	private ArticuloDao articuloDao;

	@Autowired()
	private OficinaDao oficinaDao;

	@Autowired()
	private UbicacionDao ubicacionDao;

	@Autowired()
	private PeticionDao peticionDao;

	// @Resource(name = "usuario")
	// private User usuario;

	@Resource(name = "appMessageSource")
	private ReloadableResourceBundleMessageSource messageSource;

	@Autowired()
	private MailService mailService;

	@Resource(name = "appConfiguration")
	private Properties config;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.u74a.service.TemaMaterialService#findByTipoMaterial(int)
	 */
	@Transactional(readOnly = true)
	@Override()
	public FichaSolicitud detalleSolicitud(List<Integer> codigosArticulosLst) { // codigosMaterialesLst

		Date fechaSolicitud = new Date();

		String estado = this.messageSource.getMessage("solicitud.estadoPendiente", null,
				LocaleContextHolder.getLocale());

		/* Lista de los artículos solicitados. */
		List<ArticuloSolicitado> articulosSolicitadosLst = new ArrayList<ArticuloSolicitado>();

		// Se recupera la lista de articulos para los materiales seleccionados.
		List<Articulo> articulosLst = this.articuloDao.findByListaCodigos(codigosArticulosLst); // findByMaterial(codigosMaterialesLst);

		if (articulosLst != null && articulosLst.size() > 0) {
			ArticuloSolicitado articuloSolicitado;
			for (Articulo articulo : articulosLst) {
				articuloSolicitado = new ArticuloSolicitado();
				articuloSolicitado.setArticulo(articulo);
				articuloSolicitado.setCodArticulo(articulo.getCodArticulo());
				articulosSolicitadosLst.add(articuloSolicitado);
			}
		}

		String codigoOficina = Utilidades.getDetallesUsuario().getCodigoOficina();
		Oficina oficinaSolicitud = this.oficinaDao.findByCodigo(codigoOficina);

		// Obtener la lista de las ubicaciones
		List<Ubicacion> ubicacionesLst = this.ubicacionDao.findByCodigoOficina(codigoOficina);

		FichaSolicitud fichaSolicitud = new FichaSolicitud();
		fichaSolicitud.setFechaSolicitud(fechaSolicitud);
		fichaSolicitud.setEstado(estado);
		fichaSolicitud.setArticulosLst(articulosSolicitadosLst);
		fichaSolicitud.setOficinaSolicitud(oficinaSolicitud);
		fichaSolicitud.setUbicacionesLst(ubicacionesLst);
		return fichaSolicitud;
	}

	/**
	 * Guarda la lista de articulos solicitados.
	 * 
	 * @param fichaSolicitud {@link FichaSolicitud} Objeto con los datos de la solicitud
	 * 
	 * @return String mensaje con el error si ha fallado al guardar la solicitud, blanco en caso contrario.
	 */
	@Transactional()
	@Override()
	public String guardarSolicitud(FichaSolicitud fichaSolicitud) { // TODO revisar control excepciones
		String resultado = "";
		StringBuilder errores = new StringBuilder();
		String asunto = "";
		StringBuilder body = new StringBuilder();
		StringBuilder erroresStock = new StringBuilder();

		if (fichaSolicitud != null) {

			List<ArticuloSolicitado> articulosLst = fichaSolicitud.getArticulosLst();
			// Primero hay que validar que hay stock de los articulos solicitados
			for (ArticuloSolicitado articuloSolicitado : articulosLst) {
				Articulo datosStock = this.articuloDao.getDatosStockArticulo(articuloSolicitado.getArticulo()
						.getCodArticulo());

				// los guardo en variables para realizar cálculos
				int stock = datosStock.getStock();
				int stockMinimo = datosStock.getStockMin();

				int numEjemplaresSolicitados = articuloSolicitado.getNumEjemplaresSolicitados();
				if (articuloSolicitado.getArticulo().getModoPeticion().equals(Constants.MODO_ENVIO_CAJAS)) {
					numEjemplaresSolicitados = articuloSolicitado.getNumEjemplaresSolicitados()
							* articuloSolicitado.getArticulo().getNumEjemplares();
				}

				int stockActualizado = stock - numEjemplaresSolicitados;

				// if (stock < numEjemplaresSolicitados) {
				// en caso de que el stock se vaya a quedar por debajo del stock mínimo
				if (stockActualizado < stockMinimo) {// devuelvo un error
					Object[] msgArgs = { articuloSolicitado.getArticulo().getMaterial()
							.getTitulo(LocaleContextHolder.getLocale())
							+ " - " + articuloSolicitado.getArticulo().getDescripcionIdioma() };

					erroresStock.append(
							this.messageSource.getMessage("solicitud.errorStock", msgArgs,
									LocaleContextHolder.getLocale())).append("<br/>");
				}
			}

			// si hay errores en la validación del stock de artículos solicitados
			if (!erroresStock.toString().equals("")) {
				throw new ParameterValidationException(erroresStock.toString());
			}

			Articulo articulo;
			Oficina oficinaSolicitante = fichaSolicitud.getOficinaSolicitud();
			UsuarioDetalles usuario = Utilidades.getDetallesUsuario();

			asunto = this.messageSource.getMessage("solicitud.email.coordinador.asunto",
					new Object[] { oficinaSolicitante.getNombreOficina() }, LocaleContextHolder.getLocale());

			body.append(this.messageSource.getMessage("solicitud.email.coordinador.body.intro",
					new Object[] { oficinaSolicitante.getNombreOficina() }, LocaleContextHolder.getLocale()));

			// Validacion campos
			if (fichaSolicitud.getPuntoRecepcion() == null) {
				errores.append(this.messageSource.getMessage("solicitud.errorPtoRecepcionOblig", null,
						LocaleContextHolder.getLocale()));
			}
			if (fichaSolicitud.getOficinaSolicitud() == null) {
				errores.append(this.messageSource.getMessage("solicitud.errorOficinaSolOblig", null,
						LocaleContextHolder.getLocale()));
			}

			if (fichaSolicitud.getArticulosLst() == null || fichaSolicitud.getArticulosLst().size() == 0) {
				errores.append(this.messageSource.getMessage("solicitud.errorArticulosOblig", null,
						LocaleContextHolder.getLocale()));
			} else {
				Date hoy = new Date();
				for (ArticuloSolicitado articuloSolicitado : articulosLst) {

					if (articuloSolicitado.getArticulo() != null) {

						Peticion peticion = new Peticion();
						articulo = articuloSolicitado.getArticulo();

						peticion.setCodigoArticulo(articulo.getCodArticulo());
						peticion.setFechaPeticion(fichaSolicitud.getFechaSolicitud());
						peticion.setNumPedido(articuloSolicitado.getNumEjemplaresSolicitados());
						peticion.setNumEjemplaresCaja(articulo.getNumEjemplares());
						peticion.setCodigoFormaEnvio(articulo.getCodigoFormaEnvio());
						peticion.setTextoPeticion(fichaSolicitud.getObservacionesSolicitud());
						peticion.setCodigoSolicitante(oficinaSolicitante.getCodigoOficina());
						peticion.setCodigoUbicacion(fichaSolicitud.getPuntoRecepcion().getCodigoUbicacion());
						peticion.setTextoPuntoRecepcion(fichaSolicitud.getObservacionesRecepcion());
						peticion.setFechaEstado(hoy);
						peticion.setEstado(Constants.ESTADO_PENDIENTE);
						peticion.setFechaModificacion(hoy);
						peticion.setCodigoUsuarioModificador(Integer.parseInt(usuario.getUsername()));

						this.peticionDao.insertPeticion(peticion);

						// enviamos mail al coordinador avisando de la nueva solicitud

						List<String> args = new ArrayList<String>();
						args.add(articuloSolicitado.getArticulo().getMaterial().getTituloCastellano());
						args.add(this.articuloDao.getDescripcionIdiomasArticulo(peticion.getCodigoArticulo()));

						args.add(Integer.toString(peticion.getNumPedido()));

						if (peticion.getNumEjemplaresCaja() > 0) {
							args.add(this.messageSource.getMessage("solicitud.email.body.cajas", null,
									LocaleContextHolder.getLocale()));
						} else {
							args.add(this.messageSource.getMessage("solicitud.email.body.ejemplares", null,
									LocaleContextHolder.getLocale()));
						}

						body.append("\n\n");
						body.append(this.messageSource.getMessage("solicitud.email.coordinador.body", args.toArray(),
								LocaleContextHolder.getLocale()));

					} else {
						errores.append(this.messageSource.getMessage("solicitud.errorArticulosOblig", null,
								LocaleContextHolder.getLocale()));
					}
				}
				resultado = "{\"resultado\": \"OK\"}";
			}

		} else {
			errores.append(this.messageSource.getMessage("solicitud.errorDatosOblig", null,
					LocaleContextHolder.getLocale()));
		}
		if (!"".equals(errores.toString())) {
			throw new ParameterValidationException(errores.toString());
		}

		// obtenemos el mail del coordinaro del fichero config
		String mailTo = this.config.getProperty("email.coordinador");
		// enviamos mail al coordinador avisando de las solicitudes realizadas
		this.mailService.sendMail(mailTo, asunto, body.toString());

		return resultado;
	}
}
