package com.ejie.ad74a.service.tramitacion;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ejie.ad74a.dao.BandejaTelematicaDao;
import com.ejie.ad74a.dao.DocumentosBanTelDao;
import com.ejie.ad74a.dao.DocumentosTareaDao;
import com.ejie.ad74a.dao.ExpedientesDao;
import com.ejie.ad74a.dao.TareasTramiteDao;
import com.ejie.ad74a.dao.TramitesExpedienteDao;
import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.jms.service.ParserJMSRequest;
import com.ejie.ad74a.model.BandejaTelematica;
import com.ejie.ad74a.model.DatosTareaEstudio;
import com.ejie.ad74a.model.DocumentosBanTel;
import com.ejie.ad74a.model.DocumentosTarea;
import com.ejie.ad74a.model.Estados;
import com.ejie.ad74a.model.Expedientes;
import com.ejie.ad74a.model.TareasTramite;
import com.ejie.ad74a.model.TramitesExpediente;
import com.ejie.ad74a.util.comun.UtilSeguridad;
import com.ejie.ad74a.util.constantes.Constantes;
import com.ejie.ad74a.util.constantes.EstadosExpedienteEnum;
import com.ejie.ad74a.util.constantes.FinalizacionEstudioEnum;
import com.ejie.ad74a.util.constantes.ProcedimientosEnum;
import com.ejie.ad74a.util.constantes.TareasEnum;
import com.ejie.ad74a.util.constantes.TipoAportacionEnum;
import com.ejie.ad74a.util.constantes.TipoProcesoEnum;
import com.ejie.ad74a.util.constantes.TipoTramiteExpediente;
import com.ejie.ad74a.util.constantes.TramitesEnum;
import com.ejie.ad74a.ws.client.platea.model.context.ContextSubmissionEvent;
import com.ejie.ad74a.ws.client.platea.tareasTramitacion.TStringList;

/**
 * Gestión de la Tarea de Entrada de Documentación - NO TAREA PLATEA
 * 
 * @author IBERMATICA
 */

@Service(value = "tareaEntradaDocumentacionService")
public class TareaEntradaDocumentacionServiceImpl implements TareaEntradaDocumentacionService {

	private static final Logger logger = LoggerFactory.getLogger(TareaEntradaDocumentacionServiceImpl.class);

	@Autowired
	private ExpedientesDao expedientesDao;

	@Autowired
	private TramitacionService tramitacionService;

	@Autowired
	private DocumentosBanTelDao documentosBanTelDao;

	@Autowired
	private DocumentosTareaDao documentosTareaDao;

	@Autowired
	private TareasTramiteDao tareasTramiteDao;

	@Autowired
	private ParserJMSRequest parserRequest;

	@Autowired
	private TramitesExpedienteDao tramitesExpedienteDao;

	@Autowired
	private BandejaTelematicaDao bandejaTelematicaDao;

	public BandejaTelematica procesarEntradaDocumentacion(BandejaTelematica entrada) {
		TareaEntradaDocumentacionServiceImpl.logger
				.info("TareaEntradaDocumentacionServiceImpl.procesarEntradaDocumentacion - Inicio");

		try {

			// recuperamos los datos del expediente
			Expedientes expediente = this.expedientesDao
					.find(new Expedientes(entrada.getExpediente().getIdExpediente00()));
			entrada.setExpediente(expediente);

			if (entrada.getSubmisiontypeProcesado14().equalsIgnoreCase(TipoProcesoEnum.APORTACION.getTipo())) {
				this.procesarEntradaAportacion(entrada);
				entrada.setSubmisiontype14(TipoProcesoEnum.getNuevoTipoByTipo(entrada.getSubmisiontypeProcesado14()));
			} else if (entrada.getSubmisiontypeProcesado14()
					.equalsIgnoreCase(TipoProcesoEnum.SUBSANACION_DOCUMENTOS.getTipo())) {
				this.procesarEntradaSubsanacion(entrada);
			} else if (entrada.getSubmisiontypeProcesado14()
					.equalsIgnoreCase(TipoProcesoEnum.DESISTIMIENTO.getTipo())) {
				this.procesarEntradaDesistimiento(entrada);
			}

			this.bandejaTelematicaDao.updateTipoProceso(entrada);
		} catch (Throwable e) {
			ManagerErrors.manageException(e, "Error al procesar una entrada");
		}

		TareaEntradaDocumentacionServiceImpl.logger.info("BandejaEntradaServiceImpl.procesarEntrada - Fin");

		return entrada;
	}

	@Override
	public ContextSubmissionEvent procesarEntradaDocumentacionPapel0(ContextSubmissionEvent contextSubmissionEvent) {
		TareaEntradaDocumentacionServiceImpl.logger
				.info("TareaEntradaDocumentacionServiceImpl.procesarEntradaDocumentacionPapel0 - Inicio");

		try {

			// recuperamos los datos del expediente
			Expedientes expedienteFilter = new Expedientes();
			expedienteFilter.setFolderId00(contextSubmissionEvent.getFolderID());
			Expedientes expediente = this.expedientesDao.findExpedienteByFolderId(expedienteFilter).get(0);

			BandejaTelematica bandeja = parserRequest.getBandejaTelematicaEjgv(contextSubmissionEvent);
			bandeja.setExpediente(expediente);

			String submissionType = contextSubmissionEvent.getSubmissionType();

			if (submissionType.equalsIgnoreCase(TipoAportacionEnum.APORTACION_DOCUMENTOS.getTipo())) {
				this.procesarEntradaAportacion(bandeja);
				bandeja.setSubmisiontype14(TipoProcesoEnum.getNuevoTipoByTipo(bandeja.getSubmisiontypeProcesado14()));
			} else if (submissionType.equalsIgnoreCase(TipoAportacionEnum.SUBSANACION.getTipo())) {
				this.procesarEntradaSubsanacion(bandeja);
			} else if (submissionType.equalsIgnoreCase(TipoAportacionEnum.DESISTIMIENTO.getTipo())) {
				this.procesarEntradaDesistimiento(bandeja);
			}

		} catch (Throwable e) {
			ManagerErrors.manageException(e, "Error al procesar una entrada de");
		}

		TareaEntradaDocumentacionServiceImpl.logger
				.info("BandejaEntradaServiceImpl.procesarEntradaDocumentacionPapel0 - Fin");

		return contextSubmissionEvent;
	}

	/**
	 * 1- Se crea el tramite de recepcion de documentacion
	 * 
	 * 2- Se guardan los documentos en ese tramite
	 * 
	 * 3- Si el estado del expediente es Pendiente de subsanación se modifica a
	 * Pendiente de estudio por aportación/subsanación
	 * 
	 * @param bandeja
	 * @throws Throwable
	 */
	private void procesarEntradaAportacion(BandejaTelematica bandeja) throws Throwable {

		// crear el tramite de Recepcion de documentacion
		TramitesExpediente tramiteExp = this.tramitacionService.tratamientoTramiteBandeja(bandeja,
				Constantes.PLATEA_TASK_ID_RECEPCION_DOC_FICTICIO, TareasEnum.RECEP_DOCUMENTACION,
				Constantes.EstadoTramitacion.ESTADO_TRAMITE_FINALIZADO);

		// grabar documentos tramite
		this.saveDocumentsBandejaToTramite(bandeja, tramiteExp);
	}

	/**
	 * 1.- Si la situación del expediente es ‘Estudio documentación’ actualiza el
	 * estado del expediente a ‘Pendiente de estudio por aportación/subsanación’. En
	 * otra situación no se actualiza el estado
	 * 
	 * @param bandeja BandejaEntrada
	 * @throws Throwable
	 */
	private void procesarEntradaSubsanacion(BandejaTelematica bandeja) throws Throwable {

		// crear el tramite de Recepcion de documentacion
		TramitesExpediente tramiteExp = this.tramitacionService.tratamientoTramiteBandeja(bandeja,
				Constantes.PLATEA_TASK_ID_RECEPCION_DOC_FICTICIO, TareasEnum.RECEP_DOCUMENTACION,
				Constantes.EstadoTramitacion.ESTADO_TRAMITE_FINALIZADO);

		// grabar documentos tramite
		this.saveDocumentsBandejaToTramite(bandeja, tramiteExp);

	}

	/**
	 * 1.- Finaliza la tarea de estudio que estuviese abierta. La situación de fin
	 * del estudio será Desistimiento expreso.
	 * 
	 * 2.- Sugiere la tarea de Inicio de desistimiento expreso.
	 * 
	 * 3.- Al recibir el evento de la tarea sugerida, crea el trámite en el
	 * repositorio de trámites y actualiza el estado del expediente a Pendiente de
	 * resolución de desistimiento. La situación del expediente pasa a
	 * Desistimiento.
	 * 
	 * @param bandeja BandejaEntrada
	 * @throws Throwable
	 */
	private void procesarEntradaDesistimiento(BandejaTelematica bandeja) throws Throwable {
		TareaEntradaDocumentacionServiceImpl.logger
				.info("BandejaEntradaServiceImpl.procesarEntradaDesistimiento - Inicio");
		// ** crear el tramite de Recepcion Desistimiento expreso ** //
		TramitesExpediente tramiteExp = this.tramitacionService.tratamientoTramiteBandeja(bandeja,
				Constantes.PLATEA_TASK_ID_RECEP_DESIS_EXPRESO_FICTICIO, TareasEnum.RECEPCION_DESIS_EXPRESO,
				Constantes.EstadoTramitacion.ESTADO_TRAMITE_FINALIZADO);

		// grabar documentos tramite
		this.saveDocumentsBandejaToTramite(bandeja, tramiteExp);

		// actualizamos el estado del expediente y el tipo de desistimiento
		Expedientes expediente = bandeja.getExpediente();
		// actualizamos el estado a lo que corresponda
		expediente.setEstados(new Estados(EstadosExpedienteEnum.PEND_RESOL_DES.getId()));
		// grabar fecha de desistimiento con la fecha
		expediente.setfDesistimiento00(bandeja.getfRegistro14());
		expediente.setTipoDesis00(Constantes.TiposDesistimiento.TIPO_DESISTIMIENTO_EXPRESO);
		expediente = this.expedientesDao.updateDesistimiento(expediente);

		// ** Sugerimos la tarea de resolucion desistimiento ** //
		TStringList mailboxes = new TStringList();
		mailboxes.getItem().add(0, expediente.getTecnicoExpediente00());

		// Actualizamos los datos de estudio con el fin de desistimiento para que se
		// puedan consultar.

		List<TareasTramite> listaTareas = this.tareasTramiteDao.getLastNotExecutedTask(expediente.getIdExpediente00(),
				TramitesEnum.ESTUDIO_DOCUMENTACION);

		if (!listaTareas.isEmpty()) {
			TramitesExpediente tramiteEstudio = this.tramitesExpedienteDao
					.find(new TramitesExpediente(listaTareas.get(0).getTramitesExpediente().getIdTramiteExp10()));

			tramiteEstudio.setTipoEstudioDoc10(
					TipoTramiteExpediente.tipoEstudioDoc10.ESTUDIO_DOCUMENTACION_DESISTIMIENTO.getId());
			this.tramitesExpedienteDao.update(tramiteEstudio);

			TareasTramite tareaEstudio = listaTareas.get(0);
			DatosTareaEstudio datosTareaEstudio = tareaEstudio.getDatosTareaEstudio() != null
					? tareaEstudio.getDatosTareaEstudio()
					: DatosTareaEstudio.getNewDatosTareaEstudioByIdProcedimiento(
							ProcedimientosEnum.getById(expediente.getIdProcedimiento00()));

			datosTareaEstudio.setSituacioneFinalTarea(Long.parseLong(FinalizacionEstudioEnum.DESISTIMIENTO.getId()));
			datosTareaEstudio.setResultadoEstudio(Constantes.ResultadoDocumentacion.COMPLETO.getId());

			datosTareaEstudio.setTramitesExpediente(tramiteEstudio);
			datosTareaEstudio.setExpediente(expediente);

			tareaEstudio.setDatosTareaClob(datosTareaEstudio);
			this.tareasTramiteDao.update(tareaEstudio);

			// EJECUTAR TAREA DE ESTUDIO ** //
			this.tramitacionService.finalizarTareaEstudio(expediente.getFolderId00(),
					FinalizacionEstudioEnum.DESISTIMIENTO.getId());
		}

		TareaEntradaDocumentacionServiceImpl.logger
				.info("BandejaEntradaServiceImpl.procesarEntradaDesistimiento - Fin");
	}

	private void saveDocumentsBandejaToTramite(BandejaTelematica bandeja, TramitesExpediente tramiteExp) {
		// recuperamos los documentos de la entrada
		List<DocumentosBanTel> listaDocuments = this.getDocsBandeja(bandeja);

		// trasnformamos los documentos
		List<DocumentosTarea> listaDocTarea = this.parserRequest.parseDocEntradaToDocTarea(listaDocuments,
				tramiteExp.getTareasTramites().get(0).getIdTareaTram11());

		for (DocumentosTarea docTarea : listaDocTarea) {
			this.documentosTareaDao.add(docTarea);
		}
	}

	private List<DocumentosBanTel> getDocsBandeja(BandejaTelematica bandeja) {
		DocumentosBanTel documentosEntrada = new DocumentosBanTel();
		documentosEntrada.setIdEntrada15(bandeja.getIdEntrada14());
		return this.documentosBanTelDao.findAll(documentosEntrada, null);
	}
}
