package com.mx.dla.dda.reporte.amortizacion.bos;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
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.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mx.dla.dda.contrato.titulo.dtos.Titulo;
import com.mx.dla.dda.excelMapper.bos.ExcelMapperTransform;
import com.mx.dla.dda.excelMapper.context.ExcelMapperContext;
import com.mx.dla.dda.excelMapper.dtos.ExcelMapper;
import com.mx.dla.dda.reporte.amortizacion.daos.ReporteAmortizacionDAO;
import com.mx.dla.dda.reporte.amortizacion.dtos.MesesAmortizacionDTO;
import com.mx.dla.dda.reporte.amortizacion.dtos.RegistroRubroDTO;
import com.mx.dla.global.bos.BaseBO;

@Service
public class ReporteExcelAmortizacionBO extends BaseBO {
	
	@Autowired
	protected ExcelMapperTransform excelMapperTransform;
	
	@Autowired
	private ExcelMapperContext excelMapperContext;
	
	@Autowired
	private ReporteAmortizacionDAO reporteAmortizacionDAO;
	
	private final String[] smeses = {"ENE", "FEB", "MAR", "ABR", "MAY", "JUN", "JUL", "AGO", "SEP", "OCT", "NOV", "DIC" };
	
	public byte[] generaReporteAmortizacion(Long idEstudio, String fecha) {				
		List<MesesAmortizacionDTO> reporte = null;
		byte[] fileExcel = null;											
		
		try 
		{			
			reporte = reporteAmortizacionDAO.obtenerMesesAmortizacion(idEstudio, fecha);
			if(reporte.isEmpty())
				reporte.add(getVacio());
			logger.debug("{}", reporte);
		}catch(Exception e) {
			logger.error("Error: " + e);
		}
						
		fileExcel = this.generarExcel(fecha, reporte);
		return fileExcel;
	}
	
	public byte[] generaReporteAmortizacionSAP(Long idEstudio, String fecha) {				
		List<MesesAmortizacionDTO> reporte = null;
		byte[] fileExcel = null;											
		
		try 
		{			
			reporte = reporteAmortizacionDAO.obtenerMesesAmortizacionSAP(idEstudio, fecha);
			if(reporte.isEmpty())
				reporte.add(getVacio());
			logger.debug("{}" , reporte);
			
		}catch(Exception e) {
			logger.error("Error: " + e);
		}
						
		fileExcel = this.generarExcel(fecha, reporte);
		return fileExcel;
	}
	
	public byte[] generaReporteAmortizacionSAPDLA(Long idEstudio, String fecha) {				
		ByteArrayOutputStream baos = null;										
		try 
		{	
			Integer year = Integer.parseInt(fecha.substring(3));
			Integer month = Integer.parseInt(fecha.substring(0,2));
			String day = "01/";
			Map<String, List<MesesAmortizacionDTO>> reporte = getResults(idEstudio, day.concat(year.toString()));
			Map<String, List<MesesAmortizacionDTO>> reporteAnt = getResults(idEstudio, day + (year - 1) );
			Map<String, List<MesesAmortizacionDTO>> reporteSig = getResults(idEstudio, day + (year + 1) );
			Workbook workbook = new XSSFWorkbook();

			Sheet sheet = workbook.createSheet("Conciliacion DDA vs SAP");
			addHeaders(sheet, workbook, year);
			int row = 1;
			for(Entry<String, List<MesesAmortizacionDTO>> rep : reporte.entrySet()) {
				if(rep.getValue().size() < 2) {
					MesesAmortizacionDTO emptyValue = new MesesAmortizacionDTO(0.0);
					emptyValue.setSistema(rep.getValue().get(0).getSistema().equals("DDA") ? "SAP" : "DDA");
					emptyValue.setDescripcion(rep.getValue().get(0).getDescripcion());
					emptyValue.setTemporada(rep.getValue().get(0).getTemporada());
					emptyValue.setIdContrato(rep.getValue().get(0).getIdContrato());
					rep.getValue().add(emptyValue);
				}
				CellStyle headerStyle;
				int i = 0;
				for(MesesAmortizacionDTO line : rep.getValue()) {
					if(Objects.nonNull(reporteAnt.get(rep.getKey())) && reporteAnt.get(rep.getKey()).size() > i) {
						if(Objects.nonNull(reporteAnt.get(rep.getKey())) ) {
							line.setAcumuladoAnt(reporteAnt.get(rep.getKey()).get(i).getAcumulado());
						} else {
							line.setAcumuladoAnt(0.0);
						}
						if(Objects.nonNull(reporteSig.get(rep.getKey()))) {
							line.setAcumuladoSig(reporteSig.get(rep.getKey()).get(i).getAcumulado());
						} else {
							line.setAcumuladoSig(0.0);
						}
					} else {
						line.setAcumuladoAnt(0.0);
						line.setAcumuladoSig(0.0);
					}
					line.calculaRemanente(month);
					int cell = 0;
					if (row == 1 || row == 2) {
						headerStyle = getStyle(workbook, IndexedColors.LIGHT_ORANGE.getIndex(), CellStyle.SOLID_FOREGROUND, Short.parseShort("10"), false);
					}else {
						if(Objects.nonNull(line.getIdContrato())) {
							headerStyle = getStyle(workbook, IndexedColors.LIGHT_GREEN.getIndex(), CellStyle.SOLID_FOREGROUND, Short.parseShort("10"), false);
						} else {
							headerStyle = getStyle(workbook, IndexedColors.LIGHT_YELLOW.getIndex(), CellStyle.SOLID_FOREGROUND, Short.parseShort("10"), false);
						}
					}
					Row header = sheet.createRow(row++);
					fillCell(header, header.createCell(cell++), headerStyle, line.getDescripcion());
					fillCell(header, header.createCell(cell++), headerStyle, line.getTemporada());
					fillCell(header, header.createCell(cell++), headerStyle, line.getSistema());
					fillCell(header, header.createCell(cell++), headerStyle, line.getAcumuladoAnt());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes1());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes2());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes3());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes4());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes5());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes6());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes7());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes8());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes9());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes10());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes11());
					fillCell(header, header.createCell(cell++), headerStyle, line.getMes12());
					fillCell(header, header.createCell(cell++), headerStyle, line.getAcumulado());
					fillCell(header, header.createCell(cell++), headerStyle, line.getAcumuladoSig());
					fillCell(header, header.createCell(cell++), headerStyle, line.getRemanente());
					i++;
				}
				sheet.addMergedRegion(new CellRangeAddress((row - 2), (row - 1), 0, 0));
			}
			baos = new ByteArrayOutputStream();
	        workbook.write(baos);
			
			
		}catch(Exception e) {
			logger.error("Error: " + e);
			e.printStackTrace();
		}
						
		return baos.toByteArray();
	}
	
	public void addHeaders(Sheet sheet, Workbook workbook, Integer year) {
		CellStyle headerStyle = getStyle(workbook, IndexedColors.RED.getIndex(), CellStyle.SOLID_FOREGROUND, 
				Short.parseShort("12"), true);
		Row header = sheet.createRow(0);
		fillCell(header, header.createCell(0), headerStyle, "Descripción");
		fillCell(header, header.createCell(1), headerStyle, "Temporada");
		fillCell(header, header.createCell(2), headerStyle, "Sistema");
		fillCell(header, header.createCell(3), headerStyle, "Acumulado " + (year - 1));
		fillCell(header, header.createCell(4), headerStyle, "ENE");
		fillCell(header, header.createCell(5), headerStyle, "FEB");
		fillCell(header, header.createCell(6), headerStyle, "MAR");
		fillCell(header, header.createCell(7), headerStyle, "ABR");
		fillCell(header, header.createCell(8), headerStyle, "MAY");
		fillCell(header, header.createCell(9), headerStyle, "JUN");
		fillCell(header, header.createCell(10), headerStyle, "JUL");
		fillCell(header, header.createCell(11), headerStyle, "AGO");
		fillCell(header, header.createCell(12), headerStyle, "SEP");
		fillCell(header, header.createCell(13), headerStyle, "OCT");
		fillCell(header, header.createCell(14), headerStyle, "NOV");
		fillCell(header, header.createCell(15), headerStyle, "DIC");
		fillCell(header, header.createCell(16), headerStyle, "Acumulado");
		fillCell(header, header.createCell(17), headerStyle, "Acumulado " + (year + 1));
		fillCell(header, header.createCell(18), headerStyle, "Remanente");
	}
	
	public Map<String, List<MesesAmortizacionDTO>> getResults(Long idEstudio, String fecha) {
		Map<String, List<MesesAmortizacionDTO>> reporte = new LinkedHashMap<>();
		List<MesesAmortizacionDTO> registros = new LinkedList<>();
		registros.addAll(reporteAmortizacionDAO.obtenerMesesAmortizacion(idEstudio, fecha));
		registros.addAll(reporteAmortizacionDAO.obtenerMesesAmortizacionSAP(idEstudio, fecha));
		for (MesesAmortizacionDTO registro : registros) {
			String temporada = Objects.nonNull(registro.getTemporada()) ? registro.getTemporada() : StringUtils.EMPTY;
			String numContrato = Objects.nonNull(registro.getNumContrato()) ? registro.getNumContrato() : StringUtils.EMPTY;
			if(!reporte.containsKey(registro.getDescripcion() + temporada + numContrato)) {
				reporte.put(registro.getDescripcion() + temporada + numContrato, new ArrayList<MesesAmortizacionDTO>());
			}
			reporte.get(registro.getDescripcion() + temporada + numContrato).add(registro);
		}
		
		return reporte;
	}
	
	private void fillCell(Row header, Cell headerCell, CellStyle headerStyle, Double data) {
		headerCell.setCellValue(data);
		headerCell.setCellStyle(headerStyle);
	}
	
	private void fillCell(Row header, Cell headerCell, CellStyle headerStyle, String data) {
		headerCell.setCellValue(data);
		headerCell.setCellStyle(headerStyle);
	}
	
	private CellStyle getStyle(Workbook workbook, short color, short pattern, short size, boolean isBold) {
		CellStyle headerStyle = workbook.createCellStyle();
		headerStyle.setFillForegroundColor(color);
		headerStyle.setFillPattern(pattern);

		XSSFFont font = ((XSSFWorkbook) workbook).createFont();
		font.setFontName("Arial");
		font.setFontHeightInPoints(size);
		font.setBold(isBold);
		headerStyle.setFont(font);
		return headerStyle;
	}
		
	private MesesAmortizacionDTO getVacio(){
		MesesAmortizacionDTO v = new MesesAmortizacionDTO();
		v.setDescripcion("");
		v.setMes1(0.0);
		v.setMes2(0.0);
		v.setMes3(0.0);
		v.setMes4(0.0);
		v.setMes5(0.0);
		v.setMes6(0.0);
		v.setMes7(0.0);
		v.setMes8(0.0);
		v.setMes9(0.0);
		v.setMes10(0.0);
		v.setMes11(0.0);
		v.setMes12(0.0);
		v.setAcumulado(0.0);
		return v;
	}
	
	public byte[] generarExcel(String fecha, List<MesesAmortizacionDTO> reporte){
		byte[] fileExcel  = null;		
		String[] mesAnnio = fecha.split("/");		
		int mes   = Integer.parseInt(mesAnnio[0]);
		int annio = Integer.parseInt(mesAnnio[1]);
		
		ExcelMapper mapper = excelMapperContext.getExcelMapper("mesesAmortizacion");
		
		for(int i = 1 ; i <= 12; i++) 
		{			
			String headerFormated = String.format(mapper.getRules().get(i).getHeader(),  smeses[mes - 1], annio);  
			mapper.getRules().get(i).setHeader(  headerFormated );
			mes++;
			if(mes > 12) {
				annio++;
				mes = 1;
			}			
		}
		
		try 
		{	
			fileExcel = excelMapperTransform.transformObjectToExcel(reporte, mapper , MesesAmortizacionDTO.class);	
		}catch(Exception e) {
			logger.error("Error : " + e);
		}
		return fileExcel;
	}
	
	//---metodos de prueba
	public byte[] generaReporteAmortizacion_old() {
		
		List<Titulo> reporte = new ArrayList<Titulo>();
		Titulo titulo = new Titulo();
		byte[] fileExcel = null;
		
		titulo.setTipoTitulo("tipo");
		titulo.setNombreUnico("Nombre Unico");
		titulo.setEpisodio("Episodio");
		reporte.add(titulo);
		
		try{
			fileExcel = excelMapperTransform.transformObjectToExcel(reporte, "titulo" ,Titulo.class);
			logger.debug("" + fileExcel.length);
			
		}catch(Exception e){
			logger.error("Error : " + e);
		}

		return fileExcel;
	}
	
	
	public byte[] generaReporteAmortizacionOK() {
		byte[] fileExcel = null;
		
		List<MesesAmortizacionDTO> reporte = new ArrayList<MesesAmortizacionDTO>();
		MesesAmortizacionDTO meses = new MesesAmortizacionDTO();
		meses.setAcumulado(100.0);
		meses.setDescripcion("Descripcion");
		meses.setIdContrato(1L);
		meses.setMes1(1.0);
		meses.setMes2(2.0);
		meses.setMes3(3.0);
		meses.setMes4(4.0);
		meses.setMes5(5.0);
		
		reporte.add(meses);
		
		try{
			fileExcel = excelMapperTransform.transformObjectToExcel(reporte, "mesesAmortizacion" , MesesAmortizacionDTO.class);
			logger.debug("" + fileExcel.length);
			
		}catch(Exception e){
			logger.error("Error : " + e);
		}
		
		return fileExcel;
	} 
	
	public byte[] generaReporteAmortizacionOK2(Integer anio) {
	
		byte[] fileExcel = null;
		List<MesesAmortizacionDTO> reporte = new ArrayList<MesesAmortizacionDTO>();
		MesesAmortizacionDTO meses = new MesesAmortizacionDTO();
		meses.setAcumulado(100.0);
		meses.setDescripcion("Descripcion");
		meses.setIdContrato(1L);
		meses.setMes1(1.0);
		meses.setMes2(2.0);
		meses.setMes3(3.0);
		meses.setMes4(4.0);
		meses.setMes5(5.0);
		reporte.add(meses);
		
		ExcelMapper mapper = excelMapperContext.getExcelMapper("mesesAmortizacion");
		
		for(int i = 1 ; i<=12;i++)
		{
			String s = String.format(mapper.getRules().get(i).getHeader(), anio+i-1);  
			mapper.getRules().get(i).setHeader(  s );
		}
		
		try{
			fileExcel = excelMapperTransform.transformObjectToExcel(reporte,mapper , MesesAmortizacionDTO.class);
			logger.debug("" + fileExcel.length);			
			
		}catch(Exception e){
			logger.error("Error : " + e);
		}
		return fileExcel;
	}

}
