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

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;

import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Autowired;

import com.mx.dla.dda.catalogos.bos.CatalogosBO;
import com.mx.dla.dda.catalogos.dtos.EstudioDTO;
import com.mx.dla.dda.contrato.common.actions.BaseContratoAction;
import com.mx.dla.dda.contrato.generales.bos.PoblarGeneralesBO;
import com.mx.dla.dda.reporte.amortizacion.bos.ReporteAmortizacionBO;
import com.mx.dla.dda.reporte.amortizacion.dtos.RegistroMontoDTO;
import com.mx.dla.dda.reporte.amortizacion.dtos.RegistroRubroDTO;
import com.mx.dla.dda.reporte.amortizacion.dtos.SortByNumeroContrato;
import com.opensymphony.xwork2.Action;

public class ReporteAmortizacionAction extends BaseContratoAction{

	private static final long serialVersionUID = -3317004330758868390L;
	
	@Autowired
	private ReporteAmortizacionBO reporteAmortizacionBO;

	@Autowired
	private CatalogosBO catalogosBO;
	
	private Long idEstudio;
	private Long idContrato;
	private String fecha;
	private List<String> fechasRango;
	private List<EstudioDTO> estudios;

	private RegistroRubroDTO totalesMontosEstudio;
	private List<RegistroRubroDTO> totalesMontosContratos;
	private Map<String, List<RegistroRubroDTO>> totalesMontosContratosSAPDLA;
	private List<RegistroRubroDTO> montosTitulos;
	private Map<String, List<RegistroRubroDTO>> totalesMontosTitulosSAPDLA;
	private Integer year;

	@Autowired
	private PoblarGeneralesBO poblarGeneralesBO;

	public String obtenerEstudios() {

		try {

			estudios = catalogosBO.obtenListaEstudios();

		} catch (PersistenceException ibe) {			
			logger.error("Error en [" + this.getClass() + "]", ibe);
		} catch (Exception e) {			
			logger.error("Error en [" + this.getClass() + "]", e);
		}
		return Action.SUCCESS;
	}
	
	public String cargaInicialReporteAmortizacionSAPDLA() {
		try {

			DateFormat entrada = new SimpleDateFormat("MM/yyyy");
			DateFormat salida = new SimpleDateFormat("MMM yyyy", new Locale("es", "ES"));
			year = Integer.parseInt(fecha.substring(3));
			Integer month = Integer.parseInt(fecha.substring(0,2));
			fecha = "01/" + year;
			totalesMontosContratosSAPDLA = reporteAmortizacionBO
					.obtenListaMontosTotalesContratoPorEstudioDLASAP(idEstudio, fecha, year, month);
			
			List<String> fechas = reporteAmortizacionBO
					.getFechasAConsultar(fecha);
			fechasRango = new ArrayList<String>();

			for (String fecha : fechas) {
				Date date = entrada.parse(fecha);
				fecha = salida.format(date).toUpperCase();
				fechasRango.add(fecha);
			}

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}
		return Action.SUCCESS;
	}

	public String cargaInicialReporteAmortizacion() {

		try {

			DateFormat entrada = new SimpleDateFormat("MM/yyyy");
			DateFormat salida = new SimpleDateFormat("MMM yyyy", new Locale("es", "ES"));

			totalesMontosEstudio = reporteAmortizacionBO
					.obtenMontosTotalesPorEstudio(idEstudio, fecha);
			totalesMontosContratos = reporteAmortizacionBO
					.obtenListaMontosTotalesContratoPorEstudio(idEstudio, fecha, 12L);

			List<String> fechas = reporteAmortizacionBO
					.getFechasAConsultar(fecha);
			fechasRango = new ArrayList<String>();

			for (String fecha : fechas) {
				Date date = entrada.parse(fecha);
				fecha = salida.format(date).toUpperCase();
				fechasRango.add(fecha);
			}

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}

		return Action.SUCCESS;
	}

	public String cargaMontoTitulosPorContrato() {

		logger.debug("ID!!! idContrato: " + idContrato + "::: fecha: " + fecha);

		try {
			
			montosTitulos = reporteAmortizacionBO
					.obtenListaMontoTitulosPorContrato(idContrato, fecha);

			logger.debug("montosTitulos !!!!: " + montosTitulos);

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}

		return Action.SUCCESS;
	}

	public String cargaInicialReporteAmortizacionSAP() {

		try {

			DateFormat entrada = new SimpleDateFormat("MM/yyyy");
			DateFormat salida = new SimpleDateFormat("MMM yyyy", new Locale("es", "ES"));

			totalesMontosEstudio = reporteAmortizacionBO
					.obtenMontosTotalesPorEstudioSAP(idEstudio, fecha);
			totalesMontosContratos = reporteAmortizacionBO
					.obtenListaMontosTotalesContratoPorEstudioSAP(idEstudio, fecha, 12L);

			List<String> fechas = reporteAmortizacionBO
					.getFechasAConsultar(fecha);
			fechasRango = new ArrayList<String>();

			for (String fecha : fechas) {
				Date date = entrada.parse(fecha);
				fecha = salida.format(date).toUpperCase();
				fechasRango.add(fecha);
			}

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}

		return Action.SUCCESS;
	}

	public String cargaMontoTitulosPorContratoSAP() {

		logger.debug("ID!!! idContrato: " + idContrato + "::: fecha: " + fecha);

		try {
			
			montosTitulos = reporteAmortizacionBO
					.obtenListaMontoTitulosPorContratoSAP(idContrato, fecha);

			logger.debug("montosTitulos !!!!: " + montosTitulos);

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}

		return Action.SUCCESS;
	}
	
	public String cargaMontoTitulosPorContratoSAPDLA() {

		logger.debug("ID!!! idContrato: " + idContrato + "::: fecha: " + fecha);

		try {
			year = Integer.parseInt(fecha.substring(3));
			Integer month = Integer.parseInt(fecha.substring(0,2));
			fecha = "01/" + year;
			totalesMontosTitulosSAPDLA = getListByYear(fecha);
			Map<String, List<RegistroRubroDTO>> totalesAnioPasado = getListByYear("01/" + (year - 1));
			Map<String, List<RegistroRubroDTO>> totalesAnioSiguiente = getListByYear("01/" + (year + 1));
			
			for(Entry<String, List<RegistroRubroDTO>> total : totalesMontosTitulosSAPDLA.entrySet()) {
				if(total.getValue().size() < 2) {
					RegistroRubroDTO emptyValue = new RegistroRubroDTO();
					List<String> meses = reporteAmortizacionBO.getFechasAConsultar(fecha);
					emptyValue.setMontoMes(reporteAmortizacionBO.obtenMontosMesesVacios(meses));
					emptyValue.setSistema(total.getValue().get(0).getSistema().equals("DDA") ? "SAP" : "DDA");
					emptyValue.setFechainicio(total.getValue().get(0).getFechainicio());
					emptyValue.setFechaFin(total.getValue().get(0).getFechaFin());
					emptyValue.setCodigoSAP(total.getValue().get(0).getCodigoSAP());
					emptyValue.setIdBroadview(total.getValue().get(0).getIdBroadview());
					total.getValue().add(emptyValue);
				}
				for (int i = 0; total.getValue().size() > i; i++) {
					if(Objects.nonNull(totalesAnioPasado.get(total.getKey())) 
							&& totalesAnioPasado.get(total.getKey()).size() > i) {
						if(Objects.nonNull(totalesAnioSiguiente.get(total.getKey()))) {
							total.getValue().get(i)
							.setAcumuladoAnterior(totalesAnioPasado
									.get(total.getKey()).get(i).getMontoMes().get(12).getMonto());
						} else {
							total.getValue().get(i).setAcumuladoAnterior(0.0);
						}
						if(Objects.nonNull(totalesAnioSiguiente.get(total.getKey()))) {
							total.getValue().get(i)
							.setAcumuladoPosterior(totalesAnioSiguiente
									.get(total.getKey()).get(i).getMontoMes().get(12).getMonto());
						} else {
							total.getValue().get(i).setAcumuladoPosterior(0.0);
						}
						Double r1 = total.getValue().get(i).getAcumuladoAnterior();
						Double r2 = total.getValue().get(i).getAcumuladoPosterior();
						int mon = 1;
						for (RegistroMontoDTO mnt : total.getValue().get(i).getMontoMes()){
							if(mon <= month) {
								r1 += mnt.getMonto();
							}
							if(mon > month && mon <= 12 ) {
								r2 += mnt.getMonto();
							}
							mon++;
						}
						total.getValue().get(i).setRemanente(r1 - r2);
					} else {
						total.getValue().get(i).setAcumuladoAnterior(0.0);
						total.getValue().get(i).setAcumuladoPosterior(0.0);
						total.getValue().get(i).setRemanente(0.0);
					}
				}
			}
			logger.debug("montosTitulos !!!!: " + montosTitulos);

		} catch (Exception e) {
			addActionError("Ha ocurrido el siguiente error durante la consulta: "
					+ e.getMessage());
		}

		return Action.SUCCESS;
	}
	
	public Map<String, List<RegistroRubroDTO>> getListByYear(String date) throws ParseException{
		montosTitulos = reporteAmortizacionBO
				.obtenListaMontoTitulosPorContratoSAP(idContrato, date);
		
		montosTitulos.addAll(reporteAmortizacionBO
				.obtenListaMontoTitulosPorContrato(idContrato, date));
		montosTitulos.sort(new SortByNumeroContrato());
		Map<String, List<RegistroRubroDTO>> totalesMontosTitulos = new LinkedHashMap<String, List<RegistroRubroDTO>>();
		for(RegistroRubroDTO total :montosTitulos) {
			if(!totalesMontosTitulos.containsKey(total.getDescripcion())) {
				totalesMontosTitulos.put(total.getDescripcion(), new ArrayList<RegistroRubroDTO>());
			}
			totalesMontosTitulos.get(total.getDescripcion()).add(total);
		}
		
		return totalesMontosTitulos;
	}

	public Long getIdEstudio() {
		return idEstudio;
	}

	public void setIdEstudio(Long idEstudio) {
		this.idEstudio = idEstudio;
	}

	public Integer getYear() {
		return year;
	}

	public void setYear(Integer year) {
		this.year = year;
	}

	public Long getIdContrato() {
		return idContrato;
	}

	public void setIdContrato(Long idContrato) {
		this.idContrato = idContrato;
	}

	public RegistroRubroDTO getTotalesMontosEstudio() {
		return totalesMontosEstudio;
	}

	public void setTotalesMontosEstudio(RegistroRubroDTO totalesMontosEstudio) {
		this.totalesMontosEstudio = totalesMontosEstudio;
	}
	
	public void setTotalesMontosContratosSAPDLA(Map<String, List<RegistroRubroDTO>> totalesMontosContratosSAPDLA) {
		this.totalesMontosContratosSAPDLA = totalesMontosContratosSAPDLA;
	}

	public Map<String, List<RegistroRubroDTO>> getTotalesMontosContratosSAPDLA() {
		return totalesMontosContratosSAPDLA;
	}

	public void setTotalesMontosTitulosSAPDLA(Map<String, List<RegistroRubroDTO>> totalesMontosTitulosSAPDLA) {
		this.totalesMontosTitulosSAPDLA = totalesMontosTitulosSAPDLA;
	}
	
	public Map<String, List<RegistroRubroDTO>> getTotalesMontosTitulosSAPDLA() {
		return totalesMontosTitulosSAPDLA;
	}

	public List<RegistroRubroDTO> getTotalesMontosContratos() {
		return totalesMontosContratos;
	}

	public void setTotalesMontosContratos(
			List<RegistroRubroDTO> totalesMontosContratos) {
		this.totalesMontosContratos = totalesMontosContratos;
	}

	public List<RegistroRubroDTO> getMontosTitulos() {
		return montosTitulos;
	}

	public void setMontosTitulos(List<RegistroRubroDTO> montosTitulos) {
		this.montosTitulos = montosTitulos;
	}

	public String getFecha() {
		return fecha;
	}

	public void setFecha(String fecha) {
		this.fecha = fecha;
	}

	public List<EstudioDTO> getListaEstudios() {
		return poblarGeneralesBO.obtenListaEstudios();
	}

	public List<String> getFechasRango() {
		return fechasRango;
	}

	public void setFechasRango(List<String> fechasRango) {
		this.fechasRango = fechasRango;
	}

	public List<EstudioDTO> getEstudios() {
		return estudios;
	}

	public void setEstudios(List<EstudioDTO> estudios) {
		this.estudios = estudios;
	}
		
}
