package com.ejie.ad74a.control;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;

import com.ejie.ad74a.dao.DocumentosBanTelDao;
import com.ejie.ad74a.exceptions.Ad74aWebserviceException;
import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.model.DocumentosBanTel;
import com.ejie.ad74a.model.DocumentosTarea;
import com.ejie.ad74a.model.Expedientes;
import com.ejie.ad74a.model.FirmaInfo;
import com.ejie.ad74a.model.MaestroTiposDoc;
import com.ejie.ad74a.model.Solicitantes;
import com.ejie.ad74a.service.ExpedientesService;
import com.ejie.ad74a.service.MaestroTiposDocService;
import com.ejie.ad74a.service.documentos.DocumentosService;
import com.ejie.ad74a.service.interoperabilidad.InteroperabilidadService;
import com.ejie.ad74a.util.comun.UtilSeguridad;
import com.ejie.ad74a.util.comun.UtilWeb;
import com.ejie.ad74a.util.comun.Utilidades;
import com.ejie.ad74a.util.pid.Ad74aPIDws;
import com.ejie.ad74a.util.pif.Ad74aPIFws;
import com.ejie.ad74a.ws.client.dokusi.gestDocumental.T65Content;
import com.ejie.ad74a.ws.client.dokusi.service.DokusiService;
import com.ejie.ad74a.ws.client.platea.expedienteElectronico.TAuthorizationTraceType;
import com.ejie.ad74a.ws.client.platea.expedienteElectronico.TBoolean;
import com.ejie.ad74a.ws.client.platea.expedienteElectronico.TPersonIDName;
import com.ejie.ad74a.ws.client.platea.service.PlateaService;
import com.ejie.dossierDokusi.xml.Root;
import com.ejie.x38.control.bind.annotation.RequestJsonBody;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.security.UserCredentials;
import com.ejie.x38.util.DateTimeManager;

import v90.padoc.stub.W43DfDocument;

/**
 * ExpedientesController generated by UDA, 10-feb-2023 12:13:21.
 * 
 * @author UDA
 */

@Controller
@RequestMapping(value = "/documentos")

public class DocumentosController {

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

	@Autowired
	private ExpedientesService expedientesService;

	@Autowired
	private DokusiService dokusiService;

	@Autowired
	private MaestroTiposDocService maestroTiposDocService;

	@Autowired
	private DocumentosService documentosService;

	@Autowired
	private DocumentosBanTelDao documentosBanTelDao;

	@Autowired
	private InteroperabilidadService interoperabilidadService;

	@Autowired
	private PlateaService plateaService;

	@Autowired
	private Properties appConfiguration;

	@Autowired
	private Ad74aPIDws pidWS;

	@InitBinder
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws ServletException {
		binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
		binder.registerCustomEditor(Date.class,
				new CustomDateEditor(DateTimeManager.getDateTimeFormat(LocaleContextHolder.getLocale()), true));
	}

	@RequestMapping(value = "/downloadDocument/{oid}", method = RequestMethod.GET)
	public void downloadDocument(@PathVariable String oid, @RequestParam(required = true) String nombreDoc,
			HttpServletResponse response) throws IOException, Ad74aWebserviceException {

		String rutaPif = "";
		if (!Utilidades.esBlancoNulo(oid)) {
			try {
				T65Content t65Content = this.dokusiService.retrieveDocumentOrSuperLocator(oid);
				rutaPif = t65Content.getPifId();
				DocumentosController.logger.info(
						"DocumentosController.downloadDocument - Ad74aPIFws.getInstance().downloadDocument path = {}",
						rutaPif);
				InputStream inputStream = Ad74aPIFws.getInstance().downloadDocument(rutaPif);
				UtilWeb.downloadFile(nombreDoc, t65Content.getFormat().getMimeType(), 0, inputStream, response, "");
			} catch (Exception e) {
				ManagerErrors.manageException(e, "Error al descargar el documento");
			} finally {
				Ad74aPIFws.getInstance().deleteDocument(rutaPif);
			}
		}
	}

	@RequestMapping(value = "/downloadDocumentNoExp/{oid}", method = RequestMethod.GET)
	public void downloadDocumentNoExp(@PathVariable String oid, @RequestParam(required = true) String nombreDoc,
			HttpServletResponse response) throws IOException, Ad74aWebserviceException {

		String rutaPif = "";
		if (!Utilidades.esBlancoNulo(oid)) {
			try {

				rutaPif = this.appConfiguration.getProperty("webservice.dokusi.pif.dir");
				W43DfDocument docPid = pidWS.get(oid, rutaPif);
				rutaPif = docPid.getContent().getPath();
				DocumentosController.logger.info(
						"DocumentosController.downloadDocumentNoExp - Ad74aPIFws.getInstance().downloadDocument path = {}",
						rutaPif);
				InputStream inputStream = Ad74aPIFws.getInstance().downloadDocument(rutaPif);
				UtilWeb.downloadFile(nombreDoc, docPid.getContent().getFormat().getMimeType(), 0, inputStream, response,
						"");
			} catch (Exception e) {
				ManagerErrors.manageException(e, "Error al descargar el documento");
			} finally {
				Ad74aPIFws.getInstance().deleteDocument(rutaPif);
			}
		}
	}

	@RequestMapping(value = "/downloadDocumentFromPif", method = RequestMethod.GET)
	public void downloadDocumentFromPif(@RequestParam(required = true) String nombreArchivo,
			HttpServletResponse response) throws IOException, Exception {
		String rutaPif = Ad74aPIFws.getInstance().buildPath("/", "ad74a", "/", nombreArchivo);

		if (!Utilidades.esBlancoNulo(rutaPif)) {
			try {
				DocumentosController.logger.info(
						"DocumentosController.downloadDocumentFromPif - Ad74aPIFws.getInstance().downloadDocument path = {}",
						rutaPif);
				InputStream inputStream = Ad74aPIFws.getInstance().downloadDocument(rutaPif);
				UtilWeb.downloadFile(nombreArchivo, "application/pdf", 0, inputStream, response, "");
			} catch (Exception e) {
				ManagerErrors.manageException(e, "Error al descargar el documento");
			} finally {
				// Ad74aPIFws.getInstance().deleteDocument(rutaPif);
			}
		}

	}

	@RequestMapping(value = "/getTraceCert/{iopTraceID}", method = RequestMethod.GET)
	public void getTraceCert(@PathVariable String iopTraceID, HttpServletResponse response)
			throws IOException, Ad74aWebserviceException {
		TPersonIDName person = new TPersonIDName();
		person.setID(
				((UserCredentials) SecurityContextHolder.getContext().getAuthentication().getCredentials()).getNif());
		String pifPath = interoperabilidadService.getAuthorizationTrace("", iopTraceID,
				Ad74aPIFws.getInstance().buildPath("/", "ad74a", "/", iopTraceID + ".html"),
				TAuthorizationTraceType.SIMPLE, person);
		DocumentosController.logger.info(
				"DocumentosController.getTraceCert - Ad74aPIFws.getInstance().downloadDocument path = {}", pifPath);
		InputStream is = Ad74aPIFws.getInstance().downloadDocument(pifPath);
		UtilWeb.downloadFile(iopTraceID + " .html", "text/html", 0, is, response, "");

	}

	/**
	 * Operación de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterDocumentos Bean Documentos que contiene los parámetros de
	 *                         filtrado a emplear.
	 * @param tableRequestDto  Dto que contiene los parámetros de configuración
	 *                         propios del RUP_TABLE a aplicar en el filtrado.
	 *
	 * @return TableResourceResponseDto<Documentos> Dto que contiene el resultado
	 *         del filtrado realizado por el componente RUP_TABLE.
	 * @throws ParseException
	 */
	@GetMapping(value = "/documentosExpedienteSol")
	public @ResponseBody Map<String, List<DocumentosTarea>> documentosExpedienteSol(
			@RequestParam(value = "idSolicitante01", required = false) Long idSolicitante01,
			@RequestParam(value = "idExpediente00", required = false) Long idExpediente00) throws ParseException {
		HashMap<String, List<DocumentosTarea>> result = new HashMap<String, List<DocumentosTarea>>();
		DocumentosController.logger.info("[POST - filter] : Obtener Documentoss");
		if (idSolicitante01 == null && idExpediente00 != null) {
			documentosService.recuperarDocExpedientes(idExpediente00, result);
		} else if (idSolicitante01 != null && idExpediente00 == null) {
			Expedientes expedientesFilter = new Expedientes();
			expedientesFilter.setSolicitantes(new Solicitantes(idSolicitante01));
			List<Expedientes> listaExp = this.expedientesService.findAllLikeRelacionados(expedientesFilter);
			for (Expedientes exp : listaExp) {
				documentosService.recuperarDocExpedientes(exp.getIdExpediente00(), result);
			}

		}
		return result;
	}

	/**
	 * Operación de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterDocumentos Bean Documentos que contiene los parámetros de
	 *                         filtrado a emplear.
	 * @param tableRequestDto  Dto que contiene los parámetros de configuración
	 *                         propios del RUP_TABLE a aplicar en el filtrado.
	 *
	 * @return TableResourceResponseDto<Documentos> Dto que contiene el resultado
	 *         del filtrado realizado por el componente RUP_TABLE.
	 * @throws ParseException
	 * @throws IOException
	 */

	@RequestMapping(value = "/aportados/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> filterAportados(
			@RequestJsonBody(param = "filter") DocumentosTarea filterExpediente,
			@RequestJsonBody final TableRequestDto tableRequestDto) throws IOException {
		DocumentosController.logger.info("[POST - filter] : aportadosFilter");
		return documentosService.filterByDocu(filterExpediente, tableRequestDto);
	}

	/**
	 * Operación de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterDocumentos Bean Documentos que contiene los parámetros de
	 *                         filtrado a emplear.
	 * @param tableRequestDto  Dto que contiene los parámetros de configuración
	 *                         propios del RUP_TABLE a aplicar en el filtrado.
	 *
	 * @return TableResourceResponseDto<Documentos> Dto que contiene el resultado
	 *         del filtrado realizado por el componente RUP_TABLE.
	 * @throws ParseException
	 * @throws IOException
	 */

	@RequestMapping(value = "/consentimiento/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> filterConsentimiento(
			@RequestJsonBody(param = "filter") DocumentosTarea filterExpediente,
			@RequestJsonBody final TableRequestDto tableRequestDto) throws IOException {
		DocumentosController.logger.info("[POST - filter] : consentimientoFilter");
		return documentosService.filterByDocu(filterExpediente, tableRequestDto);
	}

	/**
	 * Operación de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterDocumentos Bean Documentos que contiene los parámetros de
	 *                         filtrado a emplear.
	 * @param tableRequestDto  Dto que contiene los parámetros de configuración
	 *                         propios del RUP_TABLE a aplicar en el filtrado.
	 *
	 * @return TableResourceResponseDto<Documentos> Dto que contiene el resultado
	 *         del filtrado realizado por el componente RUP_TABLE.
	 * @throws ParseException
	 * @throws IOException
	 */

	@RequestMapping(value = "/generados/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> filterGenerados(
			@RequestJsonBody(param = "filter") DocumentosTarea filterExpediente,
			@RequestJsonBody final TableRequestDto tableRequestDto) throws IOException {
		DocumentosController.logger.info("[POST - filter] : generadosFilter");
		return documentosService.filterByDocu(filterExpediente, tableRequestDto);

	}

	@RequestMapping(value = "/noAsociadosExpediente/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> filterNoExpediente(
			@RequestJsonBody(param = "filter") Solicitantes solicitante,
			@RequestJsonBody final TableRequestDto tableRequestDto) throws IOException {

		DocumentosController.logger.info("[POST - filter] : generadosFilter");
		return documentosService.getDocumentsNoAportadosExp(solicitante.getIdSolicitante01(), tableRequestDto);
	}

	@PostMapping(value = "/iopCall")
	public @ResponseBody String authorizationCall(@RequestBody HashMap<String, Object> filter) throws Exception {

		documentosService.authorizationCall((String) filter.get("authorizationID"), (String) filter.get("proceedingID"),
				Long.parseLong(filter.get("idExpediente00").toString()), filter.get("roleID").toString());

		return "ok";

	}

	@RequestMapping(value = "/getDocumentos/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> getDocumentos(
			@RequestJsonBody(param = "filter") DocumentosTarea filterDocumentosTarea,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		DocumentosController.logger.info("[POST - filterByExpediente] : Obtener DocumentosTareas");
		return this.documentosService.filterByExpediente(filterDocumentosTarea, tableRequestDto);
	}

	@RequestMapping(value = "/changeRoleDocument", method = RequestMethod.POST)
	public @ResponseBody String changeRoleDocument(@RequestBody HashMap<String, Object> filter) {
		DocumentosController.logger.info("changeRoleDocument");

		MaestroTiposDoc tipoDoc = new MaestroTiposDoc();
		DocumentosBanTel documentoEntrada = new DocumentosBanTel();

		String oidDokusi = (String) filter.get("oidDocumento");
		String roleIDOld = (String) filter.get("roleIDOld");

		tipoDoc.setRoleid36((String) filter.get("roleID"));
		List<MaestroTiposDoc> listaTiposDoc = this.maestroTiposDocService.findAll(tipoDoc, null);

		if (roleIDOld.equalsIgnoreCase(tipoDoc.getRoleid36())) {
			ManagerErrors.manageError("error.tipificar.mismoRoleId");
		}

		String senderID = UtilSeguridad.getUsuarioConectado().getNif();
		String senderName = UtilSeguridad.getUsuarioConectado().getFullName();

		TPersonIDName person = new TPersonIDName();
		person.setID(senderID);
		person.setName(senderName);

		TBoolean resultado = this.plateaService.documentChangeRoleID(oidDokusi, listaTiposDoc.get(0).getRoleid36(),
				person, (String) filter.get("procedureID"));

		if (TBoolean.TRUE.equals(resultado)) {
			documentoEntrada.setOiddokusi15(oidDokusi);
			documentoEntrada.setIdTipodocReal15(listaTiposDoc.get(0).getIdTipoDoc36());
			documentoEntrada.setUsuModif15(senderID);
			this.documentosBanTelDao.updateRoleDocument(documentoEntrada);

		} else {
			ManagerErrors.manageError("error.tipificar.generico");
		}

		return String.valueOf(resultado);
	}

	@GetMapping(value = "/retrieveSignaturesInfo/{oid}")
	public @ResponseBody List<FirmaInfo> retrieveSignaturesInfo(@PathVariable String oid) throws Exception {
		return dokusiService.retrieveSignaturesInfo(oid);
	}

	@PostMapping(value = "/searchDocumentsDossier")
	public @ResponseBody List<DocumentosTarea> searchDocumentsDossier(@RequestBody HashMap<String, Object> filter)
			throws Exception {
		List<DocumentosTarea> result = new ArrayList<DocumentosTarea>();
		Root rootDossier = dokusiService.searchDocumentsDossier((String) filter.get("documentType"),
				(String) filter.get("senderID"), null, 0);

		for (com.ejie.dossierDokusi.xml.Object docu : rootDossier.getObject()) {
			DocumentosTarea docRes = new DocumentosTarea();
			docRes.setNaturalezaRolId(docu.getEjgvNaturaleza());
			docRes.setNombreDocumento(docu.getObjectName());
			docRes.setFechaDocumento(
					DateTimeManager.getTimestampFormat(LocaleContextHolder.getLocale()).parse(docu.getRCreationDate()));

			docRes.setFechaDocumentoTimestamp(docu.getRCreationDate());
			docRes.setOidDocumento(docu.getID());
			result.add(docRes);
		}

		return result;

	}

	@RequestMapping(value = "/dossier/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<DocumentosTarea> filterDossier(
			@RequestJsonBody(param = "filter") DocumentosTarea filterExpediente,
			@RequestJsonBody final TableRequestDto tableRequestDto) throws IOException {
		DocumentosController.logger.info("[POST - filter] : dossierFilter");
		return documentosService.filterByDocu(filterExpediente, tableRequestDto);

	}
}
