package com.ejie.ad74a.ws.client.prestador.service;

import java.util.List;

import org.joda.time.Instant;
import org.joda.time.Interval;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.ejie.ad74a.dao.ContactosDao;
import com.ejie.ad74a.dao.DispositivosSolDao;
import com.ejie.ad74a.dao.ExpedientesDao;
import com.ejie.ad74a.dao.InformesDao;
import com.ejie.ad74a.dao.MotivosBajaDao;
import com.ejie.ad74a.dao.SolicitantesDao;
import com.ejie.ad74a.jms.service.TaskJMSService;
import com.ejie.ad74a.model.Contactos;
import com.ejie.ad74a.model.Direcciones;
import com.ejie.ad74a.model.DispositivosSol;
import com.ejie.ad74a.model.Expedientes;
import com.ejie.ad74a.model.InformeSocial;
import com.ejie.ad74a.model.Informes;
import com.ejie.ad74a.model.MotivosBaja;
import com.ejie.ad74a.model.Solicitantes;
import com.ejie.ad74a.util.comun.UtilidadesFecha;
import com.ejie.ad74a.util.constantes.TipoInformesEnum;
import com.ejie.ad74a.ws.client.prestador.model.BeneficiarioType;
import com.ejie.ad74a.ws.client.prestador.model.CabeceraType;
import com.ejie.ad74a.ws.client.prestador.model.Comunicacion;
import com.ejie.ad74a.ws.client.prestador.model.DatosAltaType;
import com.ejie.ad74a.ws.client.prestador.model.DatosAltaType.ContactosList;
import com.ejie.ad74a.ws.client.prestador.model.DatosAltaType.DatosBeneficiario;
import com.ejie.ad74a.ws.client.prestador.model.DatosAltaType.DatosContacto;
import com.ejie.ad74a.ws.client.prestador.model.DatosBajaType;
import com.ejie.ad74a.ws.client.prestador.model.DatosDomicilioType;
import com.ejie.ad74a.ws.client.prestador.model.DatosDomicilioType.DatosDomicilio;
import com.ejie.ad74a.ws.client.prestador.model.DatosInformeSocialType;
import com.ejie.ad74a.ws.client.prestador.model.DatosModificacionType;
import com.ejie.ad74a.ws.client.prestador.model.DireccionType;
import com.ejie.ad74a.ws.client.prestador.model.InformeMedicoType;
import com.ejie.ad74a.ws.client.prestador.model.Respuesta;
import com.ejie.ad74a.ws.client.prestador.model.TipoComunicacionEnum;

/**
 * TelevidaService. Cliente para el servicio web que expone el prestador del
 * servicio.
 * 
 * 
 * @author jbhg
 */

@Service(value = "prestadorService")
public class PrestadorServiceImpl implements PrestadorService {

	@Autowired
	private SolicitantesDao solicitantesDao;

	@Autowired
	private ExpedientesDao expedientesDao;

	@Autowired
	private DispositivosSolDao dispositivosSolDao;

	@Autowired
	private ContactosDao contactosDao;

	@Autowired
	private MotivosBajaDao motivosBajaDao;

	@Autowired
	private InformesDao informesDao;

	@Autowired
	private ApplicationContext context;
	/**
	 * Final static logger.
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(PrestadorServiceImpl.class);

	@Async("asyncExecutor")
	public Respuesta enviarAlta(Solicitantes solicitantes, Expedientes expedientes) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarAlta - Inicio");

		Respuesta respuesta = new Respuesta();

		Comunicacion comunicacion = this.crearComunicacionAlta(solicitantes, expedientes);
		respuesta = this.callWSPrestador(comunicacion);

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarAlta - Fin");

		return respuesta;

	}

	public Respuesta enviarBaja(Solicitantes solicitantes, Expedientes expedientes) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarBaja - Inicio");

		Respuesta respuesta = new Respuesta();

		Comunicacion comunicacion = this.crearComunicacionBaja(solicitantes, expedientes);
		respuesta = this.callWSPrestador(comunicacion);

		// TODO: hay que actualizar la columna F_BAJA_PS_01 si la respuesta es OK

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarBaja - Fin");

		return respuesta;
	}

	public Respuesta enviarModificacion(Solicitantes solicitantes, Expedientes expedientes) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarModificacion - Inicio");

		Respuesta respuesta = new Respuesta();

		Comunicacion comunicacion = this.crearComunicacionModificacion(solicitantes, expedientes);
		respuesta = this.callWSPrestador(comunicacion);

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarModificacion - Fin");

		return respuesta;
	}

	public Respuesta enviarCambioDomicilio(Solicitantes solicitantes, Expedientes expedientes) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarCambioDomicilio - Inicio");

		Respuesta respuesta = new Respuesta();

		Comunicacion comunicacion = this.crearComunicacionCambioDomicilio(solicitantes, expedientes);
		respuesta = this.callWSPrestador(comunicacion);

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.enviarCambioDomicilio - Fin");

		return respuesta;
	}

	private Respuesta callWSPrestador(Comunicacion comunicacion) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.callWSPrestador - Inicio");

		// TODO: Hacer la llamada SOAP al servicio del prestador. Mientras se pinta
		System.out.println(comunicacion);

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.callWSPrestador - Fin");

		return new Respuesta();
	}

	private Comunicacion crearComunicacionAlta(Solicitantes solicitante, Expedientes expediente) {

		PrestadorServiceImpl.LOGGER.info("PrestadorServiceImpl.crearComunicacionAlta #t0# ");

		Solicitantes sol = new Solicitantes(solicitante.getIdSolicitante01());
		// FindAll con sol
		// TODO: preparar la comunicación con los datos de alta
		DatosAltaType datosAlta = new DatosAltaType();
		Comunicacion comunicacion = new Comunicacion();
		CabeceraType cabecera = new CabeceraType();
		BeneficiarioType beneficiarioType = new BeneficiarioType();
		Expedientes expedientes = new Expedientes();
		List<Solicitantes> listSolicitantes = solicitantesDao.findAll(solicitante, null);

		if (listSolicitantes != null && !listSolicitantes.isEmpty()) {

			cabecera.setTipoComunicacion(TipoComunicacionEnum.ALTA);
			comunicacion.setCabecera(cabecera);

			DatosBeneficiario datosBeneficiario = new DatosBeneficiario();
			datosBeneficiario.setFNacimiento(listSolicitantes.get(0).getfNacimiento01().toString());
			if (listSolicitantes.get(0).getIdiomaSolicitante01() != null) {
				datosBeneficiario.setIdiomaPrestServicio(listSolicitantes.get(0).getIdiomaSolicitante01());
			}
			datosBeneficiario.setSexo(listSolicitantes.get(0).getSexo01());
			datosBeneficiario.setFAltaBeneficiario(listSolicitantes.get(0).getfAlta01Formateada());
			datosBeneficiario.setNss(listSolicitantes.get(0).getNumss01());
			datosBeneficiario.setTis(listSolicitantes.get(0).getNumtis01());
			// TODO datosBeneficiario.setUrgente(listSolicitantes.get(0).get);
			// TODO datosBeneficiario.setGradoDependencia(listSolicitantes.get(0).get);
			datosAlta.setDatosBeneficiario(datosBeneficiario);

			// rellenamos BeneficiarioType
			beneficiarioType = rellenarBeneficiarioType(listSolicitantes.get(0));
			cabecera.setBeneficiario(beneficiarioType);
			// TODO FechaComunicacion
			// cabecera.setFComunicacion(solicitante.getf);
			cabecera.setTipoComunicacion(TipoComunicacionEnum.ALTA);
			comunicacion.setCabecera(cabecera);
			comunicacion.setDatosAlta(datosAlta);

			// obtenemos los contactos
			Contactos contacto = new Contactos();
			contacto.setIdSolicitante03(listSolicitantes.get(0).getIdSolicitante01());
			List<Contactos> listaContactos = contactosDao.findAll(contacto, null);

			if (listaContactos != null && !listaContactos.isEmpty()) {
				contacto = listaContactos.get(0);
			}
			// TODO ASI DEBERIA SER. DEL TIPO CONTACTOTYPE Y NO DEL TIPO CONTACTO. NO TIENEN
			// LOS MISMOS DATOS
//			for (ContactoType conTv : listaContactos.getContacto()) {
//				contactosDao.add(ModelApplicationParser.getContactoUpdate(conTv, solicitante.getIdSolicitante01()));
//			}

			// Datos contacto
			DatosContacto datosContacto = new DatosContacto();
			datosContacto.setDireccion(null);
			// datosContacto.setEmail(contacto.GET);
			datosContacto.setMovil(contacto.getTlfno03());
			datosContacto.setPisoTutelado(0);
			datosContacto.setTelefonoServicio(null);
			datosAlta.setDatosContacto(datosContacto);

			// ContactosList
			ContactosList contactosList = new ContactosList();
			datosAlta.setContactosList(contactosList);
			Informes informes = new Informes();
			expedientes.setIdExpediente00(expediente.getIdExpediente00());
			expedientes = expedientesDao.find(expedientes);
			informes.setExpedientes(expedientes);
			informes.setTipoInforme16(TipoInformesEnum.INFSOC.getId());
			List<Informes> listaInformes = informesDao.findAll(informes, null);
			// DatosInformeSocialType

			if (listaInformes != null && !listaInformes.isEmpty()) {
				for (Informes informe : listaInformes) {
					if (informe.getInformeSocial() != null) {
						datosAlta.setInformeSocial(rellenarInformeSocial(listaInformes.get(0)));
						break;
					}
				}
			}

			// InformeMedicoType
			InformeMedicoType informeMedico = new InformeMedicoType();
			datosAlta.setInformeMedico(informeMedico);

			// Expedientes
			expedientes = expedientesDao.find(expediente);
			if (expedientes != null) {
				System.out.print("expedientes");
			}

			// Recuperamos la lista de dispositivos instalados
			List<DispositivosSol> listaInstalados = getDispositivosBeneficiario(solicitante.getIdSolicitante01());
			if (listaInstalados != null) {
				System.out.print("Dispositivos Instalados");
			}

		}
		return comunicacion;
	}

	private DatosInformeSocialType rellenarInformeSocial(Informes informe) {
		DatosInformeSocialType datosInformeSocial = new DatosInformeSocialType();
		InformeSocial infSocial = informe.getInformeSocial();
		if (infSocial != null) {
			datosInformeSocial.setEstaSolaManana(infSocial.getEstaSolaManana02());
			datosInformeSocial.setEstaSolaNoche(infSocial.getEstaSolaNoche02());
			datosInformeSocial.setEstaSolaTarde(infSocial.getEstaSolaTarde02());
			datosInformeSocial.setFamiliarFallecido(infSocial.getFamiliarFallecido02());
			datosInformeSocial.setFInforme(infSocial.getfInforme02().toString());
			datosInformeSocial.setFrecuenciaSalidas(infSocial.getFrecuenciaSalidas02());
			datosInformeSocial.setObservaciones(infSocial.getObservaciones02());
			datosInformeSocial.setRelacionEntorno(infSocial.getRelacionEntorno02());
			datosInformeSocial.setRutaFichero(informe.getDocumentosInforme().getUrlRuta17());
			datosInformeSocial.setSola(infSocial.getSola02());
			datosInformeSocial.setTiempoSinVisitas(infSocial.getTiempoSinVisitas02());
			datosInformeSocial.setVinculoFallecido(infSocial.getVinculoFallecido02());
			datosInformeSocial.setVisitasAmigos(infSocial.getVisitasAmigos02());
			datosInformeSocial.setVisitasFamilia(infSocial.getVisitasFamilia02());
		}
		return datosInformeSocial;
	}

	private Comunicacion crearComunicacionBaja(Solicitantes solicitante, Expedientes expediente) {

		Solicitantes sol = new Solicitantes(solicitante.getIdSolicitante01());
		// FindAll con sol
		// TODO: preparar la comunicación con los datos de baja
		Comunicacion comunicacion = new Comunicacion();
		CabeceraType cabecera = new CabeceraType();
		cabecera.setTipoComunicacion(TipoComunicacionEnum.BAJA);
		DatosBajaType datosBaja = new DatosBajaType();
		BeneficiarioType beneficiarioType = new BeneficiarioType();
		Expedientes expedientes = new Expedientes();

		List<Solicitantes> listSolicitantes = solicitantesDao.findAll(solicitante, null);
		if (listSolicitantes != null && !listSolicitantes.isEmpty()) {
			Solicitantes solicitantes = new Solicitantes();
			solicitantes = listSolicitantes.get(0);
			cabecera.setTipoComunicacion(TipoComunicacionEnum.ALTA);
			comunicacion.setCabecera(cabecera);
			datosBaja.setFBaja(UtilidadesFecha.formatearDateToString(solicitantes.getfBaja01()));

			DatosBeneficiario datosBeneficiario = new DatosBeneficiario();
			datosBeneficiario.setFNacimiento(listSolicitantes.get(0).getfNacimiento01().toString());
			if (listSolicitantes.get(0).getIdiomaSolicitante01() != null) {
				datosBeneficiario.setIdiomaPrestServicio(listSolicitantes.get(0).getIdiomaSolicitante01());
			}
			datosBeneficiario.setSexo(listSolicitantes.get(0).getSexo01());
			datosBeneficiario.setFAltaBeneficiario(listSolicitantes.get(0).getfAlta01Formateada());
			datosBeneficiario.setNss(listSolicitantes.get(0).getNumss01());
			datosBeneficiario.setTis(listSolicitantes.get(0).getNumtis01());
			// TODO datosBeneficiario.setUrgente(listSolicitantes.get(0).get);
			// TODO datosBeneficiario.setGradoDependencia(listSolicitantes.get(0).get);
			// rellenamos BeneficiarioType
			beneficiarioType = rellenarBeneficiarioType(listSolicitantes.get(0));
			cabecera.setBeneficiario(beneficiarioType);
			// TODO FechaComunicacion
			// cabecera.setFComunicacion(solicitante.getf);
			// Expedientes
			expedientes = expedientesDao.find(expediente);
			if (expedientes != null) {
				// a través del expediente obtenemos el motivo de la baja
				Long idMotBaja = expedientes.getIdMotivoBaja00();
				MotivosBaja motivoBaja = new MotivosBaja();

				motivoBaja = motivosBajaDao.find(motivoBaja);
				datosBaja.setMotivosBaja(Integer.valueOf(motivoBaja.getIdMotivoBaja33().toString()));
				datosBaja.setObservaciones(motivoBaja.getDesc());

			}

			cabecera.setTipoComunicacion(TipoComunicacionEnum.BAJA);
			comunicacion.setCabecera(cabecera);
			comunicacion.setDatosBaja(datosBaja);
		}

		return new Comunicacion();
	}

	private Comunicacion crearComunicacionModificacion(Solicitantes solicitante, Expedientes expediente) {

		Solicitantes sol = new Solicitantes(solicitante.getIdSolicitante01());
		// FindAll con sol
		// TODO: preparar la comunicación con los datos de MODIFICACION
		Comunicacion comunicacion = new Comunicacion();
		CabeceraType cabecera = new CabeceraType();
		cabecera.setTipoComunicacion(TipoComunicacionEnum.UPDATE);
		comunicacion.setCabecera(cabecera);
		DatosModificacionType datosModificacion = new DatosModificacionType();
		BeneficiarioType beneficiarioType = new BeneficiarioType();
		Expedientes expedientes = new Expedientes();

		List<Solicitantes> listSolicitantes = solicitantesDao.findAll(solicitante, null);
		if (listSolicitantes != null && !listSolicitantes.isEmpty()) {
			cabecera.setTipoComunicacion(TipoComunicacionEnum.ALTA);
			comunicacion.setCabecera(cabecera);

			com.ejie.ad74a.ws.client.prestador.model.DatosModificacionType.DatosBeneficiario datosBeneficiario = new com.ejie.ad74a.ws.client.prestador.model.DatosModificacionType.DatosBeneficiario();
			datosBeneficiario.setFNacimiento(listSolicitantes.get(0).getfNacimiento01().toString());
			if (listSolicitantes.get(0).getIdiomaSolicitante01() != null) {
				datosBeneficiario.setIdiomaPrestServicio(listSolicitantes.get(0).getIdiomaSolicitante01());
			}
			datosBeneficiario.setSexo(listSolicitantes.get(0).getSexo01());
			datosBeneficiario.setNss(listSolicitantes.get(0).getNumss01());
			datosBeneficiario.setTis(listSolicitantes.get(0).getNumtis01());
			// TODO datosBeneficiario.setUrgente(listSolicitantes.get(0).get);
			// TODO datosBeneficiario.setGradoDependencia(listSolicitantes.get(0).get);
			datosModificacion.setDatosBeneficiario(datosBeneficiario);

			// rellenamos BeneficiarioType
			beneficiarioType = rellenarBeneficiarioType(listSolicitantes.get(0));
			cabecera.setBeneficiario(beneficiarioType);
			// TODO FechaComunicacion
			// cabecera.setFComunicacion(solicitante.getf);
			cabecera.setTipoComunicacion(TipoComunicacionEnum.UPDATE);
			comunicacion.setCabecera(cabecera);
			comunicacion.setDatosModificacion(datosModificacion);

			// Expedientes
			expedientes = expedientesDao.find(expediente);

			Informes informes = new Informes();
			expedientes.setIdExpediente00(expediente.getIdExpediente00());
			expedientes = expedientesDao.find(expedientes);
			informes.setExpedientes(expedientes);
			informes.setTipoInforme16(TipoInformesEnum.INFSOC.getId());
			List<Informes> listaInformes = informesDao.findAll(informes, null);
			// DatosInformeSocialType

			if (listaInformes != null && !listaInformes.isEmpty()) {
				datosModificacion.setInformeSocial(rellenarInformeSocial(listaInformes.get(0)));
			}
			// InformeMedicoType
			InformeMedicoType informeMedico = new InformeMedicoType();
			Informes informeMedicos = new Informes();
			informes.setExpedientes(expedientes);
			informes.setTipoInforme16(TipoInformesEnum.INFSOC.getId());// Informe Social
			// filtrar por tipo de informe y el de la fecha mas alta
			List<Informes> listaInformesSocial = informesDao.findAllTodosEstados(informes, null);

			// TODO Donde sacar informes

			datosModificacion.setInformeMedico(informeMedico);

			if (expedientes != null) {
				System.out.print("expedientes");
			}
			// Recuperamos la lista de dispositivos instalados
			List<DispositivosSol> listaInstalados = getDispositivosBeneficiario(solicitante.getIdSolicitante01());
			if (listaInstalados != null) {
				System.out.print("Dispositivos Instalados");
			}

		}
		return new Comunicacion();
	}

	// comunicacionInstalacionCambioDomicilio
	private Comunicacion crearComunicacionCambioDomicilio(Solicitantes solicitante, Expedientes expediente) {

		Solicitantes sol = new Solicitantes(solicitante.getIdSolicitante01());
		DatosDomicilioType datosDomicilio = new DatosDomicilioType();

		// FindAll con sol
		List<Solicitantes> listaSolicitantes = solicitantesDao.findAll(solicitante, null);
		if (listaSolicitantes != null && !listaSolicitantes.isEmpty()) {
			Solicitantes solicitantes = listaSolicitantes.get(0);
			Direcciones direcciones = solicitantes.getDirecciones();
			DatosDomicilio datosDom = new DatosDomicilio();
			DireccionType direccion = new DireccionType();
			direccion.setCalle(direcciones.getCalle06());
			// direccion.setCodCalle(direcciones.get);
			direccion.setCodLocalidad(direcciones.getIdLocalidad06());
			direccion.setCodMunicipio(direcciones.getMunicipio06());
			direccion.setCodPortal(direcciones.getIdPortal06());
			direccion.setCodProvincia(direcciones.getIdProvincia06());
			direccion.setCp(direcciones.getCp06());
			direccion.setEscalera(direcciones.getEscalera06());
			direccion.setLetra(direcciones.getLetra06());
			direccion.setPiso(direcciones.getPiso06());
			direccion.setPortal(direcciones.getPortal06());
			datosDom.setDireccion(direccion);
			datosDomicilio.setDatosDomicilio(datosDom);

			// Guardamos los datos de la direccion
		}

		// TODO: preparar la comunicación con los datos de CAMBIO DE DOMICILIO
		Comunicacion comunicacion = new Comunicacion();
		CabeceraType cabecera = new CabeceraType();
		cabecera.setTipoComunicacion(TipoComunicacionEnum.DOMICILIO);
		comunicacion.setCabecera(cabecera);
		comunicacion.setDatosAlta(new DatosAltaType());
		return new Comunicacion();
	}

	private BeneficiarioType rellenarBeneficiarioType(Solicitantes solicitante) {
		BeneficiarioType beneficiario = new BeneficiarioType();
		beneficiario.setNombre(solicitante.getNombre01());
		beneficiario.setApe1(solicitante.getApellido101());
		beneficiario.setApe2(solicitante.getApellido201());
		beneficiario.setNumAbonado(solicitante.getNumAbonado01());
		// TODO
		// beneficiario.setNumDocumento(solicitante.get);
		// beneficiario.setTipoDocumento(solicitante.getTipoIdentificador01());

		return beneficiario;
	}

	private List<DispositivosSol> getDispositivosBeneficiario(Long idSolicitante) {
		DispositivosSol disFind = new DispositivosSol();
		disFind.setIdSolicitante23(idSolicitante);
		return this.dispositivosSolDao.findAll(disFind, null);
	}
}
