package com.ejie.ad74a.util.interoperabilidad;

import java.util.Calendar;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;

import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.model.Expedientes;
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.PropertiesConstantes;
import com.ejie.ad74a.util.constantes.TipoIdentificadorEnum;
import com.ejie.x38.security.UserCredentials;

import es.redsara.intermediacion.scsp.esquemas.datosespecificos.Consulta;
import es.redsara.intermediacion.scsp.esquemas.datosespecificos.DatosConsulta;
import es.redsara.intermediacion.scsp.esquemas.datosespecificos.DatosEntradaPadronDomiciliario;
import es.redsara.intermediacion.scsp.esquemas.datosespecificos.DatosEspecificos;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Atributos;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.DatosGenericos;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Emisor;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Estado;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Funcionario;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Peticion;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Procedimiento;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Solicitante;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.SolicitudTransmision;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Solicitudes;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Titular;
import es.redsara.intermediacion.scsp.esquemas.v3.peticion.Transmision;

public abstract class InteroperabilidadUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(InteroperabilidadUtils.class);

	public static Peticion getDatosDependencia(Expedientes expediente, String auditUser) {

		Peticion peticion = new Peticion();
		peticion.setAtributos(construirAtributos(expediente, Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DEPENDENCIA));

		Solicitudes solicitudes = new Solicitudes();

		SolicitudTransmision solicitudTransmision = new SolicitudTransmision();
		Transmision transmision = new Transmision();
		transmision.setCodigoCertificado(Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DEPENDENCIA);
		transmision.setIdSolicitud(peticion.getAtributos().getIdPeticion());
		DatosGenericos datosGenericos = new DatosGenericos();
		datosGenericos.setTitular(construirTitular(expediente));
		datosGenericos.setSolicitante(construirSolicitante(expediente, auditUser));
		datosGenericos.setTransmision(transmision);
		datosGenericos.setEmisor(construirEmisorImserso());

		solicitudTransmision.setDatosGenericos(datosGenericos);
		solicitudTransmision.setDatosEspecificos(null);

		solicitudes.setSolicitudTransmision(solicitudTransmision);

		peticion.setSolicitudes(solicitudes);
		return peticion;
	}

	public static Peticion getDatosDGP(Expedientes expediente, String auditUser) {

		Peticion peticion = new Peticion();
		peticion.setAtributos(construirAtributos(expediente, Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DGP));

		Solicitudes solicitudes = new Solicitudes();

		SolicitudTransmision solicitudTransmision = new SolicitudTransmision();
		Transmision transmision = new Transmision();
		transmision.setCodigoCertificado(Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DGP);
		transmision.setIdSolicitud(peticion.getAtributos().getIdPeticion());
		DatosGenericos datosGenericos = new DatosGenericos();
		datosGenericos.setTitular(construirTitular(expediente));
		datosGenericos.setSolicitante(construirSolicitante(expediente, auditUser));
		datosGenericos.setTransmision(transmision);
		datosGenericos.setEmisor(construirEmisorDGP());
		solicitudTransmision.setDatosGenericos(datosGenericos);
		DatosEspecificos datosEspecificos = construirDatosEspecificosDGP(expediente);
		solicitudTransmision.setDatosEspecificos(datosEspecificos);

		solicitudes.setSolicitudTransmision(solicitudTransmision);
		peticion.setSolicitudes(solicitudes);

		return peticion;
	}

	public static Peticion getDatosPadron(Expedientes expediente, String auditUser) {

		Peticion peticion = new Peticion();
		peticion.setAtributos(construirAtributos(expediente, Constantes.Nisae.COD_CERTIFICADO_CONSULTA_PADRON));

		Solicitudes solicitudes = new Solicitudes();

		SolicitudTransmision solicitudTransmision = new SolicitudTransmision();
		Transmision transmision = new Transmision();
		transmision.setCodigoCertificado(Constantes.Nisae.COD_CERTIFICADO_CONSULTA_PADRON);
		transmision.setIdSolicitud(peticion.getAtributos().getIdPeticion());
		DatosGenericos datosGenericos = new DatosGenericos();
		datosGenericos.setTitular(construirTitular(expediente));
		datosGenericos.setSolicitante(construirSolicitante(expediente, auditUser));
		datosGenericos.setTransmision(transmision);
		datosGenericos.setEmisor(construirEmisorPadron());
		solicitudTransmision.setDatosGenericos(datosGenericos);
		DatosEspecificos datosEspecificos = construirDatosEspecificosPadron(expediente);
		solicitudTransmision.setDatosEspecificos(datosEspecificos);

		solicitudes.setSolicitudTransmision(solicitudTransmision);

		peticion.setSolicitudes(solicitudes);
		return peticion;
	}

	public static Peticion getDatosIrpf(Expedientes expediente, String auditUser) {

		Peticion peticion = new Peticion();
		peticion.setAtributos(construirAtributos(expediente, Constantes.Nisae.COD_CERTIFICADO_CONSULTA_IRPF));

		Solicitudes solicitudes = new Solicitudes();

		SolicitudTransmision solicitudTransmision = new SolicitudTransmision();
		Transmision transmision = new Transmision();
		transmision.setCodigoCertificado(Constantes.Nisae.COD_CERTIFICADO_CONSULTA_IRPF);
		transmision.setIdSolicitud(peticion.getAtributos().getIdPeticion());
		DatosGenericos datosGenericos = new DatosGenericos();
		datosGenericos.setTitular(construirTitular(expediente));
		datosGenericos.setSolicitante(construirSolicitante(expediente, auditUser));
		datosGenericos.setTransmision(transmision);
		datosGenericos.setEmisor(construirEmisorIrpf());
		solicitudTransmision.setDatosGenericos(datosGenericos);
		solicitudTransmision.setDatosEspecificos(null);

		solicitudes.setSolicitudTransmision(solicitudTransmision);

		peticion.setSolicitudes(solicitudes);
		return peticion;
	}

	public static Peticion getDatosDiscapacidad(Expedientes expediente, String auditUser) {

		Peticion peticion = new Peticion();
		peticion.setAtributos(construirAtributos(expediente, Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DISCAPACIDAD));

		Solicitudes solicitudes = new Solicitudes();

		SolicitudTransmision solicitudTransmision = new SolicitudTransmision();
		Transmision transmision = new Transmision();
		transmision.setCodigoCertificado(Constantes.Nisae.COD_CERTIFICADO_CONSULTA_DISCAPACIDAD);
		transmision.setIdSolicitud(peticion.getAtributos().getIdPeticion());
		DatosGenericos datosGenericos = new DatosGenericos();
		datosGenericos.setTitular(construirTitularSoloDni(expediente));
		datosGenericos.setSolicitante(construirSolicitante(expediente, auditUser));
		datosGenericos.setTransmision(transmision);
		datosGenericos.setEmisor(construirEmisorDiscapacidad());
		solicitudTransmision.setDatosGenericos(datosGenericos);
		solicitudTransmision.setDatosEspecificos(construirDatosEspecificosDiscapacidad(expediente));

		solicitudes.setSolicitudTransmision(solicitudTransmision);

		peticion.setSolicitudes(solicitudes);
		return peticion;
	}

	private static Atributos construirAtributos(Expedientes expediente, String codCertificado) {
		Atributos atributos = new Atributos();

		/*
		 * - IdPeticion: identificador único asociado a la petición que se envía. -
		 * NumElementos: nº de elementos consultados. Su valor siempre será 1. -
		 * TimeStamp: fecha y hora del envío de la petición. - Estado/CodigoEstado: en
		 * la petición su valor será 0001. - Estado/LiteralError: en la petición su
		 * valor será PENDIENTE. - CodigoCertificado: código del servicio que se está
		 * consultando.
		 * 
		 */

		// IDPETICION Nº Expediente - codigo interoperabilidad
		StringBuilder sb = new StringBuilder();
		sb.append(expediente.getIdExpediente00()).append("-").append("codInterop");
		String idPeticion = sb.toString();

		atributos.setIdPeticion(idPeticion);
		atributos.setNumElementos(1);
		atributos.setTimeStamp(
				UtilidadesFecha.fechaHoraGCToString(UtilidadesFecha.getCalendarInstanceHMS(), new Locale("ES")));
		atributos.setCodigoCertificado(codCertificado);

		Estado estado = new Estado();
		estado.setCodigoEstado(Constantes.Nisae.ESTADO_COD_PETICION);
		estado.setLiteralError(Constantes.Nisae.ESTADO_LITERROR_PETICION);
		atributos.setEstado(estado);

		return atributos;
	}

	private static Solicitante construirSolicitante(Expedientes expediente, String auditUser) {
		Solicitante solicitante = new Solicitante();

		String organoSolicitante = new StringBuilder().append("INTPLATEA").append(".managing_unit").append(".")
				.append("nombre").toString();

		// Por definir correctamente
		// De momento se pasa el organo solicitante y el codigo del ejemplo
		solicitante.setNombreSolicitante(Constantes.Nisae.INTER_NOMBRE_SOLICITANTE);
		solicitante.setIdentificadorSolicitante(Constantes.Nisae.INTER_IDSOLICITANTE);
		solicitante.setFinalidad(Constantes.Nisae.FINALIDAD);
		// Unidad Tramitadora: Nombre del Órgano gestor o Unidad tramitadora a
		// la que pertenece la aplicación consumidora
		// El formato es: Valor Castellano - Valor Euskera

		solicitante.setUnidadTramitadora(
				"Departamento de Empleo y Politicas Sociales / Dirección de Política Familiar y Comunitaria - Enplegu eta Gizarte Politikak / Familia eta Komunitate Politikarako Zuzendaritza");

		solicitante.setProcedimiento(construirProcedimiento(expediente));

		// Finalidad: : Nombre del procedimiento de tramitación o administrativo
		// para el que se accede al servicio
		// El formato es: Valor Castellano - Valor Euskera

		solicitante.setFinalidad("Consulta de NISAE");

		solicitante.setConsentimiento(Constantes.Nisae.SOLICITANTE_CONSENTIMIENTO);

		solicitante.setFuncionario(construirFuncionario(auditUser));

		if (!Utilidades.esBlancoNulo(expediente.getFolderId00())) {
			solicitante.setIdExpediente(expediente.getFolderId00());
		} else if (!Utilidades.esNulo(expediente.getIdExpediente00())) {
			solicitante.setIdExpediente(expediente.getIdExpediente00().toString());
		}

		return solicitante;
	}

	private static Titular construirTitular(Expedientes expediente) {
		Titular titular = new Titular();
		if (expediente.getSolicitantes().getTipoIdentificador01().equalsIgnoreCase(TipoIdentificadorEnum.DNI.getId())) {
			titular.setTipoDocumentacion("DNI");
		} else if (expediente.getSolicitantes().getTipoIdentificador01()
				.equalsIgnoreCase(TipoIdentificadorEnum.NIE.getId())) {
			titular.setTipoDocumentacion("NIE");
		} else if (expediente.getSolicitantes().getTipoIdentificador01()
				.equalsIgnoreCase(TipoIdentificadorEnum.PASAPORTE.getId())) {
			titular.setTipoDocumentacion("Pasaporte");
		} else {
			titular.setTipoDocumentacion("DNI");
		}
		if (expediente.getSolicitantes().getIdentificador01() != null)
			titular.setDocumentacion(expediente.getSolicitantes().getIdentificador01());
		if (expediente.getSolicitantes().getNombre01() != null)
			titular.setNombre(expediente.getSolicitantes().getNombre01());
		if (expediente.getSolicitantes().getApellido101() != null)
			titular.setApellido1(expediente.getSolicitantes().getApellido101());
		if (expediente.getSolicitantes().getApellido201() != null)
			titular.setApellido2(expediente.getSolicitantes().getApellido201());

		return titular;
	}

	private static Titular construirTitularSoloDni(Expedientes expediente) {
		Titular titular = new Titular();
		if (expediente.getSolicitantes().getTipoIdentificador01().equalsIgnoreCase(TipoIdentificadorEnum.DNI.getId())) {
			titular.setTipoDocumentacion("DNI");
		} else if (expediente.getSolicitantes().getTipoIdentificador01()
				.equalsIgnoreCase(TipoIdentificadorEnum.NIE.getId())) {
			titular.setTipoDocumentacion("NIE");
		} else if (expediente.getSolicitantes().getTipoIdentificador01()
				.equalsIgnoreCase(TipoIdentificadorEnum.PASAPORTE.getId())) {
			titular.setTipoDocumentacion("Pasaporte");
		} else {
			titular.setTipoDocumentacion("DNI");
		}

		titular.setDocumentacion(expediente.getSolicitantes().getIdentificador01());

		return titular;
	}

	private static Funcionario construirFuncionario(String auditUser) {
		Funcionario funcionario = new Funcionario();
		if (SecurityContextHolder.getContext().getAuthentication() != null) {
			String dni = ((UserCredentials) SecurityContextHolder.getContext().getAuthentication().getCredentials())
					.getNif();
			if (validarDni(dni)) {
				funcionario.setNifFuncionario(
						((UserCredentials) SecurityContextHolder.getContext().getAuthentication().getCredentials())
								.getNif());
				funcionario.setNombreCompletoFuncionario(
						((UserCredentials) SecurityContextHolder.getContext().getAuthentication().getCredentials())
								.getFullName());
				return funcionario;
			}

		}
		// Tecnico del expediente
		funcionario.setNifFuncionario("23232323T");
		funcionario.setNombreCompletoFuncionario("Funcionario de Servidor");

		return funcionario;
	}

	private static Emisor construirEmisorImserso() {
		// Emisor
		Emisor emisor = new Emisor();
		emisor.setNifEmisor(Constantes.Nisae.EMISOR_NIF_IMSERSO);
		emisor.setNombreEmisor(Constantes.Nisae.EMISOR_NOMBRE_IMSERSO);
		return emisor;
	}

	private static Emisor construirEmisorDGP() {
		// Emisor
		Emisor emisor = new Emisor();
		emisor.setNifEmisor(Constantes.Nisae.EMISOR_NIF_DGP);
		emisor.setNombreEmisor(Constantes.Nisae.EMISOR_NOMBRE_DGP);
		return emisor;
	}

	private static Emisor construirEmisorPadron() {
		// Emisor
		Emisor emisor = new Emisor();
		emisor.setNifEmisor(Constantes.Nisae.EMISOR_NIF_PADRON);
		emisor.setNombreEmisor(Constantes.Nisae.EMISOR_NOMBRE_PADRON);
		return emisor;
	}

	private static Emisor construirEmisorIrpf() {
		// Emisor
		Emisor emisor = new Emisor();
		emisor.setNifEmisor(Constantes.Nisae.EMISOR_NIF_IRPF);
		emisor.setNombreEmisor(Constantes.Nisae.EMISOR_NOMBRE_IRPF);
		return emisor;
	}

	private static Emisor construirEmisorDiscapacidad() {
		// Emisor
		Emisor emisor = new Emisor();
		emisor.setNifEmisor(Constantes.Nisae.EMISOR_NIF_DISCAPACIDAD);
		emisor.setNombreEmisor(Constantes.Nisae.EMISOR_NOMBRE_DISCAPACIDAD);
		return emisor;
	}

	private static DatosEspecificos construirDatosEspecificosDiscapacidad(Expedientes expediente) {
		Consulta consulta = new Consulta();
		consulta.setCodigoComunidadAutonoma(Constantes.Nisae.DISCAPACIDAD_COD_COM_AUTONOMA);
		consulta.setCodigoProvincia(expediente.getDirecciones().getIdProvincia06());
		consulta.setConsentimientoTiposDiscapacidad("S");
		DatosEspecificos datos = new DatosEspecificos();
		datos.setConsulta(consulta);
		return datos;
	}

	private static Procedimiento construirProcedimiento(Expedientes expediente) {
		Procedimiento procedimiento = new Procedimiento();
		procedimiento.setCodProcedimiento(PropertiesConstantes.Props.NISAE_COD_PROCEDIMIENTO.getValue());
		// Nombre del procedimiento: Texto normativo asociado al procedimiento o
		// trámite para el que se realiza la consulta al servicio
		// El formato es: Valor Castellano - Valor Euskera
		procedimiento.setNombreProcedimiento("Solicitud de alta Teleasistencia. - Telelaguntzako alta-eskaera.");
		return procedimiento;
	}

	private static DatosEspecificos construirDatosEspecificosDGP(Expedientes expediente) {
		Consulta consulta = new Consulta();
		if (expediente.getSolicitantes().getfNacimiento01() != null) {
			Calendar c = Calendar.getInstance();
			c.setTime(expediente.getSolicitantes().getfNacimiento01());
			LOGGER.info("Esta es la C -->" + c.getTime());
			LOGGER.info("Este es el año -->" + expediente.getSolicitantes().getfNacimiento01());
			consulta.setAnioNacimiento(String.valueOf(c.get(Calendar.YEAR)));
		}

		DatosConsulta datosConsulta = new DatosConsulta();
		datosConsulta.setTipoTramite(Constantes.Nisae.DGP_CONSULTA);
		consulta.setDatosConsulta(datosConsulta);
		DatosEspecificos datos = new DatosEspecificos();
		datos.setConsulta(consulta);
		return datos;
	}

	private static DatosEspecificos construirDatosEspecificosPadron(Expedientes expediente) {
		if (null != expediente.getDirecciones()
				&& !Utilidades.esBlancoNulo(expediente.getDirecciones().getIdProvincia06())
				&& !Utilidades.esBlancoNulo(expediente.getDirecciones().getIdMunicipio06())) {
			Consulta consulta = new Consulta();
			DatosConsulta datosConsulta = new DatosConsulta();
			datosConsulta.setTerritorio(expediente.getDirecciones().getIdProvincia06());
			datosConsulta.setMunicipio(expediente.getDirecciones().getIdMunicipio06());
			datosConsulta.setFecha(
					UtilidadesFecha.getFechaSistema(com.ejie.ad74a.constantes.Constantes.FORMATO_FECHA_YYYYMMDD));
			consulta.setDatosConsulta(datosConsulta);
			DatosEspecificos datos = new DatosEspecificos();
			// DatosEntradaPadronDomiciliarioRGI datoPadron = new
			// DatosEntradaPadronDomiciliarioRGI();
			DatosEntradaPadronDomiciliario datoPadron = new DatosEntradaPadronDomiciliario();
			datoPadron.setTipoDocumento("DNI");

			datoPadron.setNumDocumento(expediente.getSolicitantes().getIdentificador01());
			datoPadron.setNombre(expediente.getSolicitantes().getNombre01());
			datoPadron.setApellido1(expediente.getSolicitantes().getApellido101());
			datoPadron.setApellido2(expediente.getSolicitantes().getApellido201());
			consulta.setDatosEntradaPadronDomiciliario(datoPadron);
			datos.setConsulta(consulta);

			return datos;
		} else {
			ManagerErrors.manageError("Es obligatorio completar la provincia y el municipio");
		}
		return null;
	}

	private static boolean validarDni(String dni) {
		Pattern patron = Pattern.compile("[0-9]{7,8}[A-Z a-z]");
		Matcher mat = patron.matcher(dni);
		return mat.matches();

	}
}