package com.ejie.ad74a.service;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.ejie.ad74a.dao.CuentasDao;
import com.ejie.ad74a.dao.DireccionesDao;
import com.ejie.ad74a.dao.ExpedientesDao;
import com.ejie.ad74a.dao.PerfilesDao;
import com.ejie.ad74a.dao.SolicitantesDao;
import com.ejie.ad74a.exceptions.ErrorField;
import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.exceptions.ValidatorException;
import com.ejie.ad74a.model.Cuentas;
import com.ejie.ad74a.model.DatosInterop;
import com.ejie.ad74a.model.Direcciones;
import com.ejie.ad74a.model.Documento;
import com.ejie.ad74a.model.Expedientes;
import com.ejie.ad74a.model.Perfiles;
import com.ejie.ad74a.util.comun.UtilLiterales;
import com.ejie.ad74a.util.comun.UtilSeguridad;
import com.ejie.ad74a.util.comun.UtilTokenXlnets;
import com.ejie.ad74a.util.comun.Utilidades;
import com.ejie.ad74a.util.comun.UtilidadesFecha;
import com.ejie.ad74a.util.constantes.Constantes;
import com.ejie.ad74a.util.constantes.EstadosExpedienteEnum;
import com.ejie.ad74a.util.constantes.ProcedimientosEnum;
import com.ejie.ad74a.util.constantes.modelos.TipoExpedientes;
import com.ejie.ad74a.util.pif.Ad74aPIFws;
import com.ejie.ad74a.ws.client.platea.service.PlateaService;
import com.ejie.ad74a.ws.client.platea.service.PlateaUtils;
import com.ejie.ad74a.ws.client.platea.solAportacion.TAdminInitRequest;

@Service(value = "inicioOficioService")
public class InicioOficioServiceImpl implements InicioOficioService {

	@Autowired
	private PlateaService plateaService;

	@Autowired
	private ExpedientesDao expedientesDao;

	@Autowired
	private CuentasDao cuentasDao;

	@Autowired
	private DireccionesDao direccionesDao;

	@Autowired
	private SolicitantesDao solicitantesDao;

	@Autowired
	private PerfilesDao perfilesDao;

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Autowired
	private DatosInteropService datosInteropService;

	@Transactional(rollbackFor = Throwable.class)
	public String aportar(MultipartFile documento) {
		// Subir a PIF
		String rutaPif = "";
		try {
			InputStream inputStream = new BufferedInputStream(documento.getInputStream());
			String pathDocumento = "/".concat(com.ejie.ad74a.constantes.Constantes.COD_APLICACION.toLowerCase())
					.concat("/").concat(documento.getOriginalFilename());
			rutaPif = Ad74aPIFws.getInstance().uploadDocument(inputStream, pathDocumento, true);
			inputStream.close();
		} catch (Exception e) {
			ManagerErrors.manageException(e, "ERROR subiendo documento aportar al informe a PIF");
		}
		return rutaPif;
	}

	@Transactional(rollbackFor = Throwable.class)
	public void inicioOficio(Expedientes expediente, String folderTitle, List<Documento> documentos)
			throws ParseException {

		validarInicioDeOficio(expediente);

		// insertamos datos del expediente
		Expedientes nuevoExp = this.insertSolicitudInicioOficio(expediente);

		// Crear registro en datos Interop solo en caso de que sea modificacion de la
		// direccion o
		// Revisión de Precio Público
		if (expediente.getIdProcedimiento00().equalsIgnoreCase(ProcedimientosEnum.REVISION_PRECIO.getId())
				|| expediente.getIdProcedimiento00().equalsIgnoreCase(ProcedimientosEnum.MODIFICACION.getId())) {
			DatosInterop dInteropNuevo = new DatosInterop();
			dInteropNuevo.setIdExpediente19(nuevoExp.getIdExpediente00());
			this.datosInteropService.add(dInteropNuevo);
		}

		// recuperamos procedimiento baja
		com.ejie.ad74a.ws.client.platea.procedimientos.TProcedureList listProcedures = this.plateaService
				.getProcedure(nuevoExp.getIdProcedimiento00());

		// Iniciar expediente de oficio de baja del beneficiario
		TAdminInitRequest request = null;
		try {
			request = PlateaUtils.createRequestInicioOficio(nuevoExp, listProcedures.getProcedure().get(0), folderTitle,
					documentos);
		} catch (Exception e) {
			ManagerErrors.manageError("Error al preparar la request de inicio de oficio");
		}

		com.ejie.ad74a.ws.client.platea.solAportacion.TSubmissionResponse result = null;
		try {
			result = this.plateaService.iniciarExpOficio(request);

		} catch (Exception e) {
			ManagerErrors.manageError("Error al iniciar el expediente de oficio en platea" + " " + e.toString());
		}

//		Solicitantes benef = new Solicitantes();
//		benef.setIdSolicitante01(expediente.getSolicitantes().getIdSolicitante01());
//		benef = this.solicitantesDao.find(benef);
//		nuevoExp.setSolicitantes(benef);
//		nuevoExp.setDirecciones(benef.getDirecciones());
//		// Modificación de direccion(0087004): Padrón
//		// Revisión de precio publico(0087005): Padrón ; Nivel de renta
//		if (expediente.getIdProcedimiento00().equalsIgnoreCase(ProcedimientosEnum.MODIFICACION.getId())) {
//			this.nisaeService.consultaPadron(nuevoExp);
//		} else if (expediente.getIdProcedimiento00().equalsIgnoreCase(ProcedimientosEnum.REVISION_PRECIO.getId())) {
//			this.nisaeService.consultaConyugeIrpf(nuevoExp);
//			this.nisaeService.consultaIrpfInterop(expediente);
//			this.nisaeService.consultaPadron(nuevoExp);
//		}
		// grabamos el folderID
		String folderID = result.getPropertyList().getProperty().get(0).getAdminInitInfo().getFolderID();
		nuevoExp.setFolderId00(folderID);
		this.expedientesDao.updateFolderID(nuevoExp);

	}

	private void validarInicioDeOficio(Expedientes expediente) {
		Boolean expedientesIniciados = this.solicitantesDao.tieneExpedienteInciado(expediente.getIdProcedimiento00(),
				expediente.getSolicitantes().getIdentificador01());
		if (Boolean.TRUE.equals(expedientesIniciados)) {
			ManagerErrors
					.manageError(UtilLiterales.getLiteralMessage(appMessageSource, "error.expedienteYaPresentado"));
		}

		if (ProcedimientosEnum.BAJA.getId().equals(expediente.getIdProcedimiento00())) {
			Boolean isSolAlta = this.solicitantesDao.isSolAlta(expediente.getSolicitantes());

			if (Boolean.FALSE.equals(isSolAlta)
					&& ProcedimientosEnum.BAJA.getId().equals(expediente.getIdProcedimiento00())) {
				ManagerErrors.manageError("error.tramitar.estudio.doc.solicitante.noAlta");
			}
		}

	}

	/**
	 * Crea un expediente de oficio
	 * 
	 * @param BandejaPapel0
	 */
	public Expedientes insertSolicitudInicioOficio(Expedientes expediente) {

		// TODO: validaciones de datos y de permisos
		List<ErrorField> errores = new ArrayList<ErrorField>();

		// solicitudesPapel0Validator.validateEntradaPapel0(errores, bandejaPapel0);

		if (errores.size() != com.ejie.ad74a.constantes.Constantes.CERO) {
			throw new ValidatorException(errores);
		}

		// TODO: crear o actualizar las direcciones, las cuentas, el
		// contacto(representante),
		// el perfil y el informe social

		// Dirección
		if (expediente.getDirecciones() != null && expediente.getDirecciones().getIdDireccion06() == null) {
			expediente.getDirecciones().setUsuAlta06(UtilSeguridad.getUsuarioConectado().getUserName());
			expediente.getDirecciones().setIdSolicitante06(expediente.getSolicitantes().getIdSolicitante01());
			Direcciones newDireccion = this.direccionesDao.add(expediente.getDirecciones());
			expediente.setDirecciones(newDireccion);
		} else if (expediente.getDirecciones() != null) {
			expediente.getDirecciones().setIdSolicitante06(expediente.getSolicitantes().getIdSolicitante01());
			this.direccionesDao.updateDireccion(expediente.getDirecciones());
		}
		if (expediente.getPerfiles() != null) {
			// mirar si es piso tutelado
			if (expediente.getPerfiles().getPisoTutelado07() != null
					&& expediente.getPerfiles().getIdPerfil07() != null) {
				this.perfilesDao.updatePisoTutelado(expediente.getPerfiles());
			} else if (expediente.getPerfiles().getPisoTutelado07() != null
					&& expediente.getPerfiles().getIdPerfil07() == null) {
				if (ProcedimientosEnum.MODIFICACION.getId().equalsIgnoreCase(expediente.getIdProcedimiento00())) {
					// Si es un procedimiento de modificación recuperamos los datos del perfil del
					// beneficiario
					Perfiles perfiBeneficiario = this.solicitantesDao.findPorDni(expediente.getSolicitantes())
							.getPerfiles();
					perfiBeneficiario.setPisoTutelado07(expediente.getPerfiles().getPisoTutelado07());
					perfiBeneficiario.setPisosTutelados(expediente.getPerfiles().getPisosTutelados());
					expediente.setPerfiles(perfiBeneficiario);

				}
				Perfiles perfil = this.perfilesDao.add(expediente.getPerfiles());
				expediente.setPerfiles(perfil);
			}

		}
		if (expediente.getDireccionNotif() != null) {
			if (expediente.getDireccionNotif().getIdDireccion06() == null) {

				expediente.getDireccionNotif().setUsuAlta06(UtilSeguridad.getUsuarioConectado().getNif());
				expediente.setDireccionNotif(this.direccionesDao.add(expediente.getDireccionNotif()));
			} else {

				this.direccionesDao.update(expediente.getDireccionNotif());
			}
		}

		// Cuenta
		if (expediente.getCuentas() != null && expediente.getCuentas().getIdCuenta05() == null) {
			expediente.getCuentas().setUsuAlta05(UtilSeguridad.getUsuarioConectado().getUserName());
			expediente.getCuentas().setIdSolicitante05(expediente.getSolicitantes().getIdSolicitante01());
			Cuentas newCuenta = this.cuentasDao.add(expediente.getCuentas());
			expediente.setCuentas(newCuenta);
		} else if (expediente.getCuentas() != null) {
			expediente.getCuentas().setIdSolicitante05(expediente.getSolicitantes().getIdSolicitante01());
			this.cuentasDao.updateCuenta(expediente.getCuentas());
		}

		expediente.getSolicitantes().setCuentas(expediente.getCuentas());
		expediente.getSolicitantes().setDirecciones(expediente.getDirecciones());
		expediente.setDireccionNotif(expediente.getDireccionNotif());
		expediente.getSolicitantes().setUsuModif01(UtilSeguridad.getUsuarioConectado().getUserName());
		expediente.getSolicitantes().setfModif01(UtilidadesFecha.getFechaSistema());
		expediente.setFolderId00(Constantes.ValoresDefectoBandejaPapel0.FOLDERID);
		expediente.setUrgencia00(TipoExpedientes.urgencia00.NO.getId());
		// expediente.setIdTipoNot00(Constantes.TipoNotificacion.TELEMATICA);
		if (!Utilidades.esBlancoNulo(expediente.getIdTipoNot00())) {
			expediente.setIdTipoNot00(expediente.getIdTipoNot00());
		} else {
			ManagerErrors.manageError("No hay tipo de notificacion");
		}

		// expediente.setCanalNot00(Constantes.CanalNotificacion.CANAL_NOTIF_ALL);
		if (!Utilidades.esBlancoNulo(expediente.getCanalNot00())) {
			expediente.setCanalNot00(expediente.getCanalNot00());
		} else {
			ManagerErrors.manageError("No hay canal de notificacion");
		}

		expediente.setUsuAlta00(UtilSeguridad.getUsuarioConectado().getUserName());
		// expediente.setUsuModif00(UtilSeguridad.getUsuarioConectado().getUserName());
		expediente.setfAlta00(UtilidadesFecha.getFechaSistema());
		// expediente.setfModif00(UtilidadesFecha.getFechaSistema());
		expediente.setIdTipoEntrada00(TipoExpedientes.idTipoEntrada00.OFICIO.getIdStr());
		expediente.setDeOficio00(Constantes.TipoSolicitud.SOLICITUD_DE_OFICIO);
		expediente.setEstados(EstadosExpedienteEnum.PEND_COMPLETAR.getEstado());
		// expediente.setNumRegistro00(Constantes.ValoresDefectoRegistro.NUM_REGISTRO);
		// expediente.setfRegistro00(Constantes.ValoresDefectoRegistro.FREGISTRO);
		if (null != expediente.getIdProcedimiento00()
				&& expediente.getIdProcedimiento00().equalsIgnoreCase(ProcedimientosEnum.BAJA.getId())
				&& null == expediente.getfBaja00()) {
			expediente.setfBaja00(UtilidadesFecha.getFechaSistema());
		}

		// Obtenemos un técnico del grupo de usuarios técnicos.
		expediente.setTecnicoExpediente00(UtilSeguridad.getUsuarioConectado().getUserName());
		return this.expedientesDao.insertSolicitudInicioOficio(expediente);
	}
}
