package com.ejie.ad74a.service;

import com.ejie.ad74a.dao.FacturacionAyuntamientosDao;
import com.ejie.ad74a.exceptions.Ad74aException;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;
import com.ejie.x38.util.DateTimeManager;
import com.lowagie.text.Document;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
import org.odftoolkit.odfdom.doc.table.OdfTable;
import org.odftoolkit.odfdom.doc.table.OdfTableRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ad74a.model.FacturacionAyuntamientos;
import com.ejie.ad74a.model.Mensualidades;
import com.ejie.ad74a.model.Pagos;
import com.ejie.ad74a.model.Procesos;
import com.ejie.ad74a.model.Solicitantes;
import com.ejie.ad74a.model.ae01b.CopagosGestionImpagos;
import com.ejie.ad74a.service.ae01b.CopagosGestionImpagosServiceImpl;
import com.ejie.ad74a.util.comun.UtilLiterales;
import com.ejie.ad74a.util.comun.UtilSeguridad;
import com.ejie.ad74a.util.comun.UtilidadesFecha;
import com.ejie.ad74a.util.constantes.EstadosProcesosBatchEnum;
import com.ejie.ad74a.util.constantes.ProcesosBatchEnum;
import com.ejie.ad74a.ws.client.liquidaciones.CabeceraType;
import com.ejie.ad74a.ws.client.liquidaciones.ConceptoType;
import com.ejie.ad74a.ws.client.liquidaciones.DatosBancariosType;
import com.ejie.ad74a.ws.client.liquidaciones.DatosDireccionType;
import com.ejie.ad74a.ws.client.liquidaciones.DatosEmisionType;
import com.ejie.ad74a.ws.client.liquidaciones.DatosIdentificacionType;
import com.ejie.ad74a.ws.client.liquidaciones.Exception_Exception;
import com.ejie.ad74a.ws.client.liquidaciones.LiquidacionesService;
import com.ejie.ad74a.ws.client.liquidaciones.RespuestaType;
import com.ejie.ad74a.ws.client.liquidaciones.TipoOperacionEnum;
import com.ejie.ad74a.ws.client.liquidaciones.DatosEmisionType.Conceptos;

/**
 * FacturacionAyuntamientosServiceImpl generated by UDA, 18-jul-2024 14:25:16.
 * 
 * @author UDA
 */

@Service(value = "facturacionAyuntamientosService")
public class FacturacionAyuntamientosServiceImpl implements FacturacionAyuntamientosService {

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

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

	@Autowired
	private FacturacionAyuntamientosDao facturacionAyuntamientosDao;

	@Autowired
	private LiquidacionesService liquidacionesService;

	@Autowired
	private ProcesosService procesosService;

	/**
	 * Inserts a single row in the FacturacionAyuntamientos table.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 * @return FacturacionAyuntamientos
	 */
	@Transactional(rollbackFor = Throwable.class)
	public FacturacionAyuntamientos add(FacturacionAyuntamientos facturacionAyuntamientos) {
		return this.facturacionAyuntamientosDao.add(facturacionAyuntamientos);
	}

	/**
	 * Updates a single row in the FacturacionAyuntamientos table.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 * @return FacturacionAyuntamientos
	 */
	@Transactional(rollbackFor = Throwable.class)
	public FacturacionAyuntamientos update(FacturacionAyuntamientos facturacionAyuntamientos) {
		return this.facturacionAyuntamientosDao.update(facturacionAyuntamientos);
	}

	/**
	 * Finds a single row in the FacturacionAyuntamientos table.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 * @return FacturacionAyuntamientos
	 */
	public FacturacionAyuntamientos find(FacturacionAyuntamientos facturacionAyuntamientos) {
		return (FacturacionAyuntamientos) this.facturacionAyuntamientosDao.find(facturacionAyuntamientos);
	}

	/**
	 * Deletes a single row in the FacturacionAyuntamientos table.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(FacturacionAyuntamientos facturacionAyuntamientos) {
		this.facturacionAyuntamientosDao.remove(facturacionAyuntamientos);
	}

	/**
	 * Finds a list of rows in the FacturacionAyuntamientos table.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto          TableRequestDto
	 * @return List<FacturacionAyuntamientos>
	 */
	public List<FacturacionAyuntamientos> findAll(FacturacionAyuntamientos facturacionAyuntamientos,
			TableRequestDto tableRequestDto) {
		return (List<FacturacionAyuntamientos>) this.facturacionAyuntamientosDao.findAll(facturacionAyuntamientos,
				tableRequestDto);
	}

	/**
	 * Finds rows in the FacturacionAyuntamientos table using like.
	 *
	 * @param facturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto          TableRequestDto
	 * @param startsWith               Boolean
	 * @return List<FacturacionAyuntamientos>
	 */
	public List<FacturacionAyuntamientos> findAllLike(FacturacionAyuntamientos facturacionAyuntamientos,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return (List<FacturacionAyuntamientos>) this.facturacionAyuntamientosDao.findAllLike(facturacionAyuntamientos,
				tableRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the FacturacionAyuntamientos table.
	 *
	 * @param tableRequestDto TableRequestDto
	 */
	public void removeMultiple(TableRequestDto tableRequestDto) {
		this.facturacionAyuntamientosDao.removeMultiple(tableRequestDto);
	}

	/**
	 * Filter method in the FacturacionAyuntamientos table.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 * @param startsWith                     Boolean
	 * @return TableResponseDto<FacturacionAyuntamientos>
	 */
	public TableResponseDto<FacturacionAyuntamientos> filter(FacturacionAyuntamientos filterFacturacionAyuntamientos,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<FacturacionAyuntamientos> listaFacturacionAyuntamientos = this.facturacionAyuntamientosDao
				.findAllLike(filterFacturacionAyuntamientos, tableRequestDto, false);
		Long recordNum = this.facturacionAyuntamientosDao
				.findAllLikeCount(filterFacturacionAyuntamientos != null ? filterFacturacionAyuntamientos
						: new FacturacionAyuntamientos(), false);

		TableResponseDto<FacturacionAyuntamientos> tableResponseDto = new TableResponseDto<FacturacionAyuntamientos>(
				tableRequestDto, recordNum, listaFacturacionAyuntamientos);

//		if (tableRequestDto.getMultiselection().getSelectedIds() != null) {
//			List<TableRowDto<FacturacionAyuntamientos>> reorderSelection = this.facturacionAyuntamientosDao
//					.reorderSelection(filterFacturacionAyuntamientos, tableRequestDto, startsWith);
//			tableResponseDto.setReorderedSelection(reorderSelection);
//			tableResponseDto.addAdditionalParam("reorderedSelection", reorderSelection);
//			tableResponseDto.addAdditionalParam("selectedAll", tableRequestDto.getMultiselection().getSelectedAll());
//		}
		if (tableRequestDto.getSeeker().getSelectedIds() != null) {
			tableRequestDto.setMultiselection(tableRequestDto.getSeeker());
			List<TableRowDto<FacturacionAyuntamientos>> reorderSeeker = this.facturacionAyuntamientosDao
					.reorderSelection(filterFacturacionAyuntamientos, tableRequestDto, startsWith);
			tableResponseDto.setReorderedSeeker(reorderSeeker);
			tableResponseDto.addAdditionalParam("reorderedSeeker", reorderSeeker);
		}
		return tableResponseDto;
	}

	public TableResponseDto<FacturacionAyuntamientos> filterFacturacion(
			FacturacionAyuntamientos filterFacturacionAyuntamientos, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		List<FacturacionAyuntamientos> listaFacturacionAyuntamientos = this.facturacionAyuntamientosDao
				.findAllLikeFacturacion(filterFacturacionAyuntamientos, tableRequestDto, false);
		Long recordNum = this.facturacionAyuntamientosDao
				.findAllLikeCountFacturacion(filterFacturacionAyuntamientos != null ? filterFacturacionAyuntamientos
						: new FacturacionAyuntamientos(), false);

		TableResponseDto<FacturacionAyuntamientos> tableResponseDto = new TableResponseDto<FacturacionAyuntamientos>(
				tableRequestDto, recordNum, listaFacturacionAyuntamientos);

		return tableResponseDto;
	}

	/**
	 * Searches rows in the FacturacionAyuntamientos table.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param searchFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 * @param startsWith                     Boolean
	 * @return List<TableRowDto<FacturacionAyuntamientos>>
	 */
	public List<TableRowDto<FacturacionAyuntamientos>> search(FacturacionAyuntamientos filterFacturacionAyuntamientos,
			FacturacionAyuntamientos searchFacturacionAyuntamientos, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.facturacionAyuntamientosDao.search(filterFacturacionAyuntamientos, searchFacturacionAyuntamientos,
				tableRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in FacturacionAyuntamientos table.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 * @param startsWith                     Boolean
	 * @return Object
	 */
	public Object reorderSelection(FacturacionAyuntamientos filterFacturacionAyuntamientos,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.facturacionAyuntamientosDao.reorderSelection(filterFacturacionAyuntamientos, tableRequestDto,
				startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

	/**
	 * Finder method in the hierarchical the FacturacionAyuntamientos table.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 * @param startsWith                     Boolean
	 * @return TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>>
	 */
	public TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>> jerarquia(
			FacturacionAyuntamientos filterFacturacionAyuntamientos, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		List<JerarquiaDto<FacturacionAyuntamientos>> listaFacturacionAyuntamientos = this.facturacionAyuntamientosDao
				.findAllLikeJerarquia(filterFacturacionAyuntamientos, tableRequestDto);
		Long recordNum = this.facturacionAyuntamientosDao.findAllLikeCountJerarquia(filterFacturacionAyuntamientos,
				tableRequestDto);
		return new TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>>(tableRequestDto, recordNum,
				listaFacturacionAyuntamientos);
	}

	/**
	 * Finder method for siblings rows in the hierarchical the
	 * FacturacionAyuntamientos table.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 * @return TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>>
	 */
	public TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>> jerarquiaChildren(
			FacturacionAyuntamientos filterFacturacionAyuntamientos, TableRequestDto tableRequestDto) {
		TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>> tableResponseDto = new TableResponseDto<JerarquiaDto<FacturacionAyuntamientos>>();
		tableResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.facturacionAyuntamientosDao.findAllChild(filterFacturacionAyuntamientos, tableRequestDto));
		return tableResponseDto;
	}

	/**
	 * Exporta Datos al clipBoard
	 *
	 */
	public List<FacturacionAyuntamientos> getMultiple(FacturacionAyuntamientos filterFacturacionAyuntamientos,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.facturacionAyuntamientosDao.getMultiple(filterFacturacionAyuntamientos, tableRequestDto,
				startsWith);
	}

	/**
	 * Devuelve un fichero en el formato deseado que contiene los datos exportados
	 * de la tabla.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param columns                        String[]
	 * @param fileName                       String
	 * @param sheetTitle                     String
	 * @param reportsParams                  ArrayList<?>
	 * @param tableRequestDto                TableRequestDto
	 * @param request                        HttpServletRequest
	 * @param response                       HttpServletResponse
	 */
	@Override
	public void generateReport(FacturacionAyuntamientos filterFacturacionAyuntamientos, String[] columns,
			String[] columnsName, String fileName, String sheetTitle, TableRequestDto tableRequestDto,
			HttpServletRequest request, HttpServletResponse response) {
		// Accede a la DB para recuperar datos
		List<FacturacionAyuntamientos> filteredData = getDataForReports(filterFacturacionAyuntamientos,
				tableRequestDto);
		String extension = null;

		// Comprobar si las siguientes variables estan vacias, en caso de estarlo se las
		// asigna un valor generico
		fileName = (fileName != null && !fileName.isEmpty()) ? fileName : "report";
		sheetTitle = (sheetTitle != null && !sheetTitle.isEmpty()) ? sheetTitle
				: FacturacionAyuntamientos.class.getSimpleName();

		// Obtener el formato de fecha especifico del locale
		SimpleDateFormat formatter = DateTimeManager.getDateTimeFormat(request.getLocale());

		// Se transforma el columns en un arraylist para eliminar el ultimo valor,
		// una vez eliminado, se sobrescribe el columns sin ese ultimo valor

		ArrayUtils.removeElement(columns, "informesStrExcel");
		List<String> columnList = new ArrayList<>(Arrays.asList(columns));
		columnList.remove(columnList.size() - 1);
		columns = columnList.toArray(new String[0]);

		if (columnsName == null) {
			columnsName = columns;
		}

		String servletPath = request.getServletPath();
		String reportType = null;
		if (servletPath.contains("/") && (servletPath.lastIndexOf("/") + 1 != servletPath.length())) {
			reportType = servletPath.substring(servletPath.lastIndexOf("/") + 1, servletPath.length());
		} else {
			reportType = servletPath.substring(0, servletPath.length());
		}

		if (reportType.equals("xlsReport")) {
			extension = ".xls";
			generateExcelReport(filteredData, columns, columnsName, fileName, sheetTitle, extension, formatter,
					response);
		} else if (reportType.equals("xlsxReport")) {
			extension = ".xlsx";
			generateExcelReport(filteredData, columns, columnsName, fileName, sheetTitle, extension, formatter,
					response);
		} else if (reportType.equals("pdfReport")) {
			extension = ".pdf";
			generatePDFReport(filteredData, columns, columnsName, fileName, response);
		} else if (reportType.equals("odsReport")) {
			extension = ".ods";
			generateODSReport(filteredData, columns, columnsName, fileName, sheetTitle, response);
		} else if (reportType.equals("csvReport")) {
			extension = ".csv";
			// Obtener idioma
			String language = request.getLocale().getLanguage();
			generateCSVReport(filteredData, columns, columnsName, fileName, sheetTitle, language, response);
		}

	}

	@Override
	public void generateReportDetail(FacturacionAyuntamientos filterFacturacionAyuntamientos, String[] columns,
			String[] columnsName, String fileName, String sheetTitle, TableRequestDto tableRequestDto,
			HttpServletRequest request, HttpServletResponse response) {
		// Accede a la DB para recuperar datos
		List<FacturacionAyuntamientos> filteredData = this.facturacionAyuntamientosDao
				.findAllLikeFacturacionExcel(filterFacturacionAyuntamientos, tableRequestDto, false);
		String extension = null;

		// Comprobar si las siguientes variables estan vacias, en caso de estarlo se las
		// asigna un valor generico
		fileName = (fileName != null && !fileName.isEmpty()) ? fileName : "report";
		sheetTitle = (sheetTitle != null && !sheetTitle.isEmpty()) ? sheetTitle
				: FacturacionAyuntamientos.class.getSimpleName();

		// Obtener el formato de fecha especifico del locale
		SimpleDateFormat formatter = DateTimeManager.getDateTimeFormat(request.getLocale());

		// Se transforma el columns en un arraylist para eliminar el ultimo valor,
		// una vez eliminado, se sobrescribe el columns sin ese ultimo valor

		ArrayUtils.removeElement(columns, "informesStrExcel");
		List<String> columnList = new ArrayList<>(Arrays.asList(columns));
		columnList.remove(columnList.size() - 1);
		columns = columnList.toArray(new String[0]);

		// Cuando no se definen columnas porque se quieren obtener todas
		if (columns == null) {
			Field[] fields = FacturacionAyuntamientos.class.getDeclaredFields();
			ArrayList<String> tempColumns = new ArrayList<String>();

			for (int i = 0; i < fields.length; i++) {
				try {
					String methodName = fields[i].getName();
					methodName = methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
					FacturacionAyuntamientos.class.getMethod("get" + methodName);
					tempColumns.add(fields[i].getName());
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}

			}
			columns = tempColumns.toArray(new String[0]);
		}

		// si no se definen el nombre de las columnas , se dejan las de por defecto.
		if (columnsName == null) {
			columnsName = columns;
		}

		String servletPath = request.getServletPath();
		String reportType = null;
		if (servletPath.contains("/") && (servletPath.lastIndexOf("/") + 1 != servletPath.length())) {
			reportType = servletPath.substring(servletPath.lastIndexOf("/") + 1, servletPath.length());
		} else {
			reportType = servletPath.substring(0, servletPath.length());
		}

		if (reportType.equals("xlsReport")) {
			extension = ".xls";
			generateExcelReport(filteredData, columns, columnsName, fileName, sheetTitle, extension, formatter,
					response);
		} else if (reportType.equals("xlsxReport")) {
			extension = ".xlsx";
			generateExcelReport(filteredData, columns, columnsName, fileName, sheetTitle, extension, formatter,
					response);
		} else if (reportType.equals("pdfReport")) {
			extension = ".pdf";
			generatePDFReport(filteredData, columns, columnsName, fileName, response);
		} else if (reportType.equals("odsReport")) {
			extension = ".ods";
			generateODSReport(filteredData, columns, columnsName, fileName, sheetTitle, response);
		} else if (reportType.equals("csvReport")) {
			extension = ".csv";
			// Obtener idioma
			String language = request.getLocale().getLanguage();
			generateCSVReport(filteredData, columns, columnsName, fileName, sheetTitle, language, response);
		}

	}

	/**
	 * Devuelve un fichero excel que contiene los datos exportados de la tabla.
	 *
	 * @param filteredData List<FacturacionAyuntamientos>
	 * @param columns      String[]
	 * @param fileName     String
	 * @param sheetTitle   String
	 * @param extension    String
	 * @param formatter    SimpleDateFormat
	 * @param response     HttpServletResponse
	 */
	private void generateExcelReport(List<FacturacionAyuntamientos> filteredData, String[] columns,
			String[] columnsName, String fileName, String sheetTitle, String extension, SimpleDateFormat formatter,
			HttpServletResponse response) {
		try {
			// Creacion del Excel
			Workbook workbook = null;
			if (extension == ".xlsx") {
				workbook = new XSSFWorkbook();
				response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
			} else {
				workbook = new HSSFWorkbook();
				response.setContentType("application/vnd.ms-excel");
			}

			response.setHeader("Content-Disposition", "attachment; filename=" + fileName + extension + "");

			// Creacion de una hoja y asignacion de su nombre
			Sheet sheet = workbook.createSheet(sheetTitle);

			// Se crea una fuente para estilizar las cabeceras
			Font headerFont = workbook.createFont();
			headerFont.setBold(true);
			headerFont.setFontHeightInPoints((short) 12);

			// Se crea un CellStyle con la fuente
			CellStyle headerCellStyle = workbook.createCellStyle();
			headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
			headerCellStyle.setFont(headerFont);

			// Inicializar contador de filas
			int rowNumber = 0;

			// Se crea la fila para insertar los titulos de las columnas
			Row row = sheet.createRow(rowNumber++);

			// Añadir titulos
			for (int i = 0; i < columnsName.length; i++) {
				Cell cell = row.createCell(i);
				cell.setCellValue(
						UtilLiterales.getLiteralMessage(appMessageSource, "excelReportLiteral." + columnsName[i]));

				cell.setCellStyle(headerCellStyle);

			}
			CellStyle CellStyleRight = workbook.createCellStyle();
			CellStyleRight.setAlignment(HorizontalAlignment.RIGHT);
			// CreationHelper ayudara a mantener la compatibilidad del DataFormat tanto si
			// se crea un .xls como un .xlsx
			CreationHelper createHelper = workbook.getCreationHelper();

			// Se crea un CellStyle para añadir el formateador de fechas
			CellStyle dateCellStyle = workbook.createCellStyle();
			dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat(formatter.toPattern()));

			// Añadir datos
			for (FacturacionAyuntamientos rowFacturacionAyuntamientos : filteredData) {
				int cellNumber = 0;
				row = sheet.createRow(rowNumber++);

				// Se iteran las columnas y se insertan los datos respetando el orden que tenian
				// las columnas en la tabla
				for (String column : columns) {
					Cell cellFacturacionAyuntamientos = row.createCell(cellNumber++);
					if (column.equals("importeFacturado90Str")) {
						cellFacturacionAyuntamientos.setCellStyle(CellStyleRight);
					}

					cellFacturacionAyuntamientos.setCellValue(getCellValue(column, rowFacturacionAyuntamientos));
				}
			}

			// Se adapta el ancho de las columnas al contenido
			for (int i = 0; i < columns.length; i++) {
				sheet.autoSizeColumn(i);
			}

			// Se añade el fichero excel al response
			workbook.write(response.getOutputStream());
			workbook.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Devuelve un fichero pdf que contiene los datos exportados de la tabla.
	 *
	 * @param filteredData List<FacturacionAyuntamientos>
	 * @param columns      String[]
	 * @param fileName     String
	 * @param response     HttpServletResponse
	 */
	private void generatePDFReport(List<FacturacionAyuntamientos> filteredData, String[] columns, String[] columnsName,
			String fileName, HttpServletResponse response) {
		try {
			// Se añade el fichero excel al response y se añade el contenido
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".pdf");
			response.setContentType("application/pdf");

			Document document = new Document();
			// Se añade el fichero pdf al response
			PdfWriter.getInstance(document, response.getOutputStream());

			document.open();

			PdfPTable table = new PdfPTable(columns.length);

			for (String column : columnsName) {
				PdfPCell header = new PdfPCell();
				header.setBorderWidth(2);
				header.setPhrase(new Phrase(column));
				table.addCell(header);
			}

			// Añadir datos
			for (FacturacionAyuntamientos rowFacturacionAyuntamientos : filteredData) {
				// Se iteran las columnas y se insertan los datos respetando el orden que tenian
				// las columnas en la tabla
				for (String column : columns) {
					table.addCell(getCellValue(column, rowFacturacionAyuntamientos));
				}
			}

			document.add(table);
			document.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Devuelve un fichero ods que contiene los datos exportados de la tabla.
	 *
	 * @param filteredData List<FacturacionAyuntamientos>
	 * @param columns      String[]
	 * @param fileName     String
	 * @param sheetTitle   String
	 * @param response     HttpServletResponse
	 */
	private void generateODSReport(List<FacturacionAyuntamientos> filteredData, String[] columns, String[] columnsName,
			String fileName, String sheetTitle, HttpServletResponse response) {
		try {
			// Se añade el fichero ods al response y se añade el contenido
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".ods");
			response.setContentType("application/vnd.oasis.opendocument.spreadsheet");

			OdfSpreadsheetDocument ods = OdfSpreadsheetDocument.newSpreadsheetDocument();
			ods.getOrCreateDocumentStyles();

			// Hay que eliminar la hoja que se genera por defecto
			ods.getTableByName("Sheet1").remove();

			// Hoja nueva
			OdfTable table = OdfTable.newTable(ods, filteredData.size() + 1, columns.length);
			table.setTableName(sheetTitle);

			// Inicializar contador de filas
			int rowNumber = 0;

			// Cabeceras
			OdfTableRow row = table.getRowByIndex(rowNumber++);
			for (int i = 0; i < columnsName.length; i++) {
				row.getCellByIndex(i).setStringValue(columnsName[i]);
			}

			// Añadir datos
			for (FacturacionAyuntamientos rowFacturacionAyuntamientos : filteredData) {
				row = table.getRowByIndex(rowNumber++);
				int cellNumber = 0;

				// Se iteran las columnas y se insertan los datos respetando el orden que tenian
				// las columnas en la tabla
				for (String column : columns) {
					row.getCellByIndex(cellNumber++).setStringValue(getCellValue(column, rowFacturacionAyuntamientos));
				}
			}

			// Se añade el fichero ods al response
			ods.save(response.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Devuelve un fichero csv que contiene los datos exportados de la tabla.
	 *
	 * @param filteredData List<FacturacionAyuntamientos>
	 * @param columns      String[]
	 * @param fileName     String
	 * @param sheetTitle   String
	 * @param language     String
	 * @param response     HttpServletResponse
	 */
	private void generateCSVReport(List<FacturacionAyuntamientos> filteredData, String[] columns, String[] columnsName,
			String fileName, String sheetTitle, String language, HttpServletResponse response) {
		try {
			// Se añade el fichero excel al response y se añade el contenido
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".csv");
			response.setContentType("text/csv");

			// Separador de campos dependiendo del idioma
			String separator = ";";
			if (language.equals("en")) {
				separator = ",";
			}

			// Se añade el fichero csv al response
			OutputStream out = response.getOutputStream();
			// Añadir titulos
			boolean addTitles = true;

			// Añadir datos
			for (FacturacionAyuntamientos rowFacturacionAyuntamientos : filteredData) {
				int cellNumber = 1;
				StringBuilder columnsTitles = new StringBuilder();
				StringBuilder row = new StringBuilder();

				// Se iteran las columnas y se insertan los datos respetando el orden que tenian
				// las columnas en la tabla
				for (String column : columns) {
					String cellValue = getCellValue(column, rowFacturacionAyuntamientos);

					if (cellNumber < columns.length) {
						if (addTitles) {
							columnsTitles.append("\"");
							columnsTitles.append(column);
							columnsTitles.append("\"");
							columnsTitles.append(separator);
						}
						row.append("\"");
						row.append(cellValue);
						row.append("\"");
						row.append(separator);
						cellNumber++;
					} else {
						if (addTitles) {
							columnsTitles.append("\"");
							columnsTitles.append(column);
							columnsTitles.append("\"\n");
						}
						row.append("\"");
						row.append(cellValue);
						row.append("\"\n");
					}
				}

				if (addTitles) {
					out.write(columnsTitles.toString().getBytes());
					addTitles = false;
				}
				out.write(row.toString().getBytes());
			}
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Devuelve los datos recuperados de la DB.
	 *
	 * @param filterFacturacionAyuntamientos FacturacionAyuntamientos
	 * @param tableRequestDto                TableRequestDto
	 */
	private List<FacturacionAyuntamientos> getDataForReports(FacturacionAyuntamientos filterFacturacionAyuntamientos,
			TableRequestDto tableRequestDto) {
		if (tableRequestDto.getMultiselection().getSelectedAll()
				&& tableRequestDto.getMultiselection().getSelectedIds().isEmpty()) {
			if (filterFacturacionAyuntamientos != null) {
				return this.facturacionAyuntamientosDao.findAllLikeExcel(filterFacturacionAyuntamientos,
						tableRequestDto, false);
			} else {
				return this.facturacionAyuntamientosDao.findAllLikeExcel(filterFacturacionAyuntamientos,
						tableRequestDto, false);
			}
		} else {
			return this.facturacionAyuntamientosDao.findAllLikeExcel(filterFacturacionAyuntamientos, tableRequestDto,
					false);
		}
	}

	/**
	 * Obtiene los valores de las celdas.
	 *
	 * @param column                      String
	 * @param rowFacturacionAyuntamientos FacturacionAyuntamientos
	 */
	private String getCellValue(String column, FacturacionAyuntamientos rowFacturacionAyuntamientos) {
		String cellValue = "";
		try {
			if (column.equals("indDomic") && rowFacturacionAyuntamientos.getIndDomic() != null) {
				if (rowFacturacionAyuntamientos.getIndDomic().equals("0")) {
					rowFacturacionAyuntamientos.setIndDomic(UtilLiterales.getLiteralMessage(appMessageSource,
							LocaleContextHolder.getLocale(), "comun.no"));
				} else {
					rowFacturacionAyuntamientos.setIndDomic(UtilLiterales.getLiteralMessage(appMessageSource,
							LocaleContextHolder.getLocale(), "comun.si"));
				}
			}
			cellValue = BeanUtils.getProperty(rowFacturacionAyuntamientos, column) != null
					? BeanUtils.getProperty(rowFacturacionAyuntamientos, column)
					: "";
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}

		return cellValue;
	}

	@Override
	public FacturacionAyuntamientos emitirLiquidacion(FacturacionAyuntamientos facturacionAyuntamientos) {

		return facturacionAyuntamientos;
	}

	private RespuestaType prepararLlamadaLiquidacion(CopagosGestionImpagos impagos, Solicitantes solicitante) {

		RespuestaType respuesta = new RespuestaType();
		CabeceraType cabecera = new CabeceraType();
		cabecera.setTipoOperacion(TipoOperacionEnum.EMITIR);
		cabecera.setFComunicacion(UtilidadesFecha.formatearDateToString(UtilidadesFecha.getFechaSistema(),
				com.ejie.ad74a.constantes.Constantes.ES_DATE_MASK));
		cabecera.setUsuario(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);

		DatosEmisionType datosEmision = new DatosEmisionType();
		datosEmision.setTipoIngreso("TLIMP");

		ConceptoType conceptoType = new ConceptoType();
////			conceptoType.setIdConcepto(2);
		BigDecimal deudaMultiplicada = impagos.getDeuda().multiply(new BigDecimal(100));
		Integer deudaInt = deudaMultiplicada.intValueExact();
		conceptoType.setImporte(deudaInt);
		Conceptos conceptos = new Conceptos();
		conceptos.getConcepto().add(conceptoType);
		datosEmision.setConceptos(conceptos);

//		String nuevoOrigen = this.getNuevoOrigen().toString();
//		datosEmision.setOrigen(nuevoOrigen);
//		Mensualidades mensualidades = new Mensualidades();
//		mensualidades.setIdSolicitante89(solicitante.getIdSolicitante01());
//		mensualidades.setGrupoImpago89(Long.valueOf(nuevoOrigen));

		// datosEmision.setImporte

//			datosEmision.setFLimitePago("24/09/2024");
//		datosEmision.setExpediente(solicitante.getNumAbonado01());
//		datosEmision.setConcepto("Teleasistencia. Copagos pendientes: " + this.obtenerDesdeHastaMesAnyo(impagos));
//		int territorio = 0;
//		if (impagos.getTerritorio().equals("48")) {
//			territorio = 3;
//		} else if (impagos.getTerritorio().equals("20")) {
//			territorio = 2;
//		} else {
//			territorio = 1;
//		}
//		datosEmision.setTerritorio(territorio);

		DatosIdentificacionType datosIdentificacionType = new DatosIdentificacionType();
		datosIdentificacionType.setTipoIdentificador(Integer.parseInt(impagos.getTipoIdentificador()));
		datosIdentificacionType.setIdentificador(impagos.getIdentificador());
		datosIdentificacionType.setNombre(impagos.getNombre());
		datosIdentificacionType.setApellido1(impagos.getApellido1());
		datosIdentificacionType.setApellido2(impagos.getApellido2());
		datosEmision.setDatosIdentificacion(datosIdentificacionType);

		DatosDireccionType datosDireccionType = new DatosDireccionType();

		datosDireccionType.setResidente(1);
		datosDireccionType.setProvincia(null != solicitante.getDirecciones().getProvinciaNORA()
				&& null != solicitante.getDirecciones().getProvinciaNORA().getCodProvincia()
						? solicitante.getDirecciones().getProvinciaNORA().getCodProvincia()
						: null);
		datosDireccionType.setMunicipio(null != solicitante.getDirecciones().getMunicipioNORA()
				&& null != solicitante.getDirecciones().getMunicipioNORA().getCodMunicipio()
						? solicitante.getDirecciones().getMunicipioNORA().getCodMunicipio()
						: null);
		datosDireccionType.setCodLocalidad(null != solicitante.getDirecciones().getLocalidadNORA()
				&& null != solicitante.getDirecciones().getLocalidadNORA().getCodLocalidad()
						? solicitante.getDirecciones().getLocalidadNORA().getCodLocalidad()
						: null);
		datosDireccionType.setLocalidad(null != solicitante.getDirecciones().getLocalidadNORA()
				&& null != solicitante.getDirecciones().getLocalidadNORA().getDescripcion()
						? solicitante.getDirecciones().getLocalidadNORA().getDescripcion()
						: null);
		datosDireccionType.setTipoVia(null != solicitante.getDirecciones().getCalleNORA()
				&& null != solicitante.getDirecciones().getCalleNORA().getTipoVia()
						? solicitante.getDirecciones().getCalleNORA().getTipoVia()
						: null);
		datosDireccionType.setCalle(null != solicitante.getDirecciones().getCalleNORA()
				&& null != solicitante.getDirecciones().getCalleNORA().getDescripcion()
						? solicitante.getDirecciones().getCalleNORA().getDescripcion()
						: null);
		datosDireccionType.setPortal(null != solicitante.getDirecciones().getPortalNORA()
				&& null != solicitante.getDirecciones().getPortalNORA().getCodPortal()
				&& null != solicitante.getDirecciones().getPortalNORA().getCodPortal().toString()
						? solicitante.getDirecciones().getPortalNORA().getCodPortal().toString()
						: null);
		datosDireccionType.setLetra(
				null != solicitante.getDirecciones().getLetra06() ? solicitante.getDirecciones().getLetra06() : null);
		datosDireccionType.setPiso(
				null != solicitante.getDirecciones().getPiso06() ? solicitante.getDirecciones().getPiso06() : null);
		datosDireccionType.setCodigoPostal(
				null != solicitante.getDirecciones().getCp06() ? solicitante.getDirecciones().getCp06() : null);
		datosDireccionType.setEscalera(
				null != solicitante.getDirecciones().getEscalera06() ? solicitante.getDirecciones().getEscalera06()
						: null);
		datosEmision.setDatosDireccion(datosDireccionType);

		DatosBancariosType datosBancarios = new DatosBancariosType();
		datosBancarios.setDomiciliacion(0);
		datosEmision.setDatosBancarios(datosBancarios);

//		try {
//			respuesta = this.liquidacionesService.emitirLiquidacion(cabecera, datosEmision);
//		} catch (Exception_Exception e) {
//			throw new Ad74aException(e.getMessage());
//		}
//		if (respuesta.getIdLiquidacion() != null) {
//			mensualidades = this.actualizarImpagos(mensualidades);
//		} else {
//			throw new Ad74aException(respuesta.getMensaje());
//		}

		StringBuilder respuestaStr = new StringBuilder();

		respuestaStr.append("codRespuesta: " + respuesta.getCodRespuesta());
		respuestaStr.append("mensaje: " + respuesta.getMensaje());
		respuestaStr.append("idLiquidacion: " + respuesta.getIdLiquidacion());
		respuestaStr.append("fecha: " + respuesta.getFRespuesta());
		FacturacionAyuntamientosServiceImpl.logger.info(respuestaStr.toString());
		// model.addAttribute("msg", respuestaStr.toString());
		// return "accessDeniedIntegrado";
		return respuesta;

	}

	public Procesos emitirLiquidacionAytos(FacturacionAyuntamientos facturacionAyuntamientos,
			HttpServletRequest request) {

		// 1- Insertar el nuevo proceso en la tabla 98
		Procesos proceso = new Procesos();
		proceso.setTipoProceso98(ProcesosBatchEnum.COPAGO_AYTOS_FACT.getId());
		proceso.setProceso98(facturacionAyuntamientos.getIdFacturacion90().toString());
		proceso.setEstado98(EstadosProcesosBatchEnum.PENDIENTE.getId());
		proceso.setUsuAlta98(UtilSeguridad.getNameUsuarioConectado());
		proceso = this.procesosService.add(proceso);

		// 2.- llamada a la O75
		try {
			String result = this.procesosService.lanzarPeticion_emitirLiquidacionAyuntamientos_O75(proceso,
					facturacionAyuntamientos, request);
			proceso.setResultadoPeticion(result);
		} catch (Exception e) {
			// Actualizar a error el proceso
			proceso.setEstado98(EstadosProcesosBatchEnum.ERROR.getId());
			proceso.setError98(e.getMessage().substring(0, Math.min(e.getMessage().length(), 799))); // Máximo 800
			this.procesosService.actualizarAError(proceso);
			throw new Ad74aException(e.getMessage());
		}

		return proceso;

	}

	public Procesos ayuntamientosExcel(FacturacionAyuntamientos facturacionAyuntamientos, HttpServletRequest request) {

		// 1- Insertar el nuevo proceso en la tabla 98
		Procesos proceso = new Procesos();
		proceso.setTipoProceso98(ProcesosBatchEnum.COPAGO_AYTOS_EXCEL.getId());
		proceso.setProceso98(facturacionAyuntamientos.getIdFacturacion90().toString());
		proceso.setEstado98(EstadosProcesosBatchEnum.PENDIENTE.getId());
		proceso.setUsuAlta98(UtilSeguridad.getNameUsuarioConectado());
		proceso = this.procesosService.add(proceso);

		// 2.- llamada a la O75
		try {
			String result = this.procesosService.lanzarPeticion_ayuntamientosExcel_O75(proceso,
					facturacionAyuntamientos, request);
			proceso.setResultadoPeticion(result);
		} catch (Exception e) {
			// Actualizar a error el proceso
			proceso.setEstado98(EstadosProcesosBatchEnum.ERROR.getId());
			proceso.setError98(e.getMessage().substring(0, Math.min(e.getMessage().length(), 799))); // Máximo 800
			this.procesosService.actualizarAError(proceso);
			throw new Ad74aException(e.getMessage());
		}

		return proceso;

	}

}
