package com.mx.dla.dda.contrato.fees.actions;

import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.executor.result.ResultMapException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.springframework.beans.factory.annotation.Autowired;

import com.dla.dda.domain.constants.OrigenCodes;
import com.mx.dla.dda.catalogos.bos.CatalogosBO;
import com.mx.dla.dda.catalogos.dtos.CatalogoDTO;
import com.mx.dla.dda.contrato.common.actions.BaseContratoAction;
import com.mx.dla.dda.contrato.common.bos.CommonRestBO;
import com.mx.dla.dda.contrato.common.dtos.JustificacionDTO;
import com.mx.dla.dda.contrato.fees.bos.FeesBonoBO;
import com.mx.dla.dda.contrato.fees.bos.FeesContratoBO;
import com.mx.dla.dda.contrato.fees.dtos.FeesContratoPagoDTO;
import com.mx.dla.dda.contrato.fees.dtos.FeesPagoBonoDTO;
import com.mx.dla.dda.contrato.fees.dtos.TipoSuscriptorDTO;
import com.mx.dla.dda.contrato.generales.bos.GeneralesBO;
import com.mx.dla.dda.contrato.generales.dtos.ContratoDTO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.opensymphony.xwork2.Action;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class FeesAction extends BaseContratoAction {

	private static final long serialVersionUID = 1L;

	private String operacion;
	private String msgError;
	private String msgExito;
	private String request;
	private List<FeesContratoPagoDTO> datos;
	private FeesPagoBonoDTO bonoSuscriptor;
	private List<TipoSuscriptorDTO> tipoSuscriptorLista;
	private List<CatalogoDTO> anioTipo;
	private String requestEliminar;
	private String requestBono;
	private String periodosEliminar;
	private String fechaInicioCto;
	private String fechaFinCto;
	private List<JustificacionDTO> justificaciones;
	private Integer inflacion;
	private Long edoCto;
	private String fechaCtoInicio;
	private String costoTotal;
	private Long estatus;

	private final DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");

	@Autowired
	private FeesContratoBO feesContratoBO;

	@Autowired
	private CommonRestBO commonRestBO;

	@Autowired
	private CatalogosBO catalogosBO;

	@Autowired
	private FeesBonoBO feesBonoBO;

	@Autowired
	private GeneralesBO generalesBO;

	public String justificaciones() {
		this.setIdContrato((Long) this.getSession().get("idContrato"));
		buscarJustificaciones();
		return Action.SUCCESS;
	}

	public String obtener() {
		this.setIdContrato((Long) this.getSession().get("idContrato"));
		try {
			List<String> vigencia = feesContratoBO.getVigenciaContrato(this.getIdContrato());
			edoCto = feesContratoBO.obtenerEdoContrato(this.getIdContrato());
			inflacion = feesContratoBO.getInflacionCto();
			fechaInicioCto = vigencia.get(0);
			fechaFinCto = vigencia.get(1);
			datos = feesContratoBO.getDatosFees(this.getIdContrato());
			bonoSuscriptor = feesBonoBO.getBono(this.getIdContrato());
			costoTotal = feesContratoBO.getCostoTotal(this.getIdContrato());
			ContratoDTO contrato = generalesBO.obtenContrato(this.getIdContrato());
			estatus = contrato.getIdEstatus();
			this.getCatalogos();
		} catch (ResultMapException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (PersistenceException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (TransaccionException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (SQLException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (ParseException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		}

		return Action.SUCCESS;
	}

	public String guardar() {
		this.setIdContrato((Long) this.getSession().get("idContrato"));
		try {
			logger.info("request enviado. {}", request);
			logger.info("request bono. {}", requestBono);

			feesContratoBO.guardarProcesoFees(request, requestBono, inflacion, getIdContrato(), operacion,
					periodosEliminar, requestEliminar);

			logger.info("fecha inicio cto." + fechaCtoInicio);
			commonRestBO.llamadaCostoTitulo(formatter.parse(fechaCtoInicio), this.getIdContrato(),
					OrigenCodes.REAL.name());

			if (this.getJustificacion() != null && this.getJustificacion().compareTo("") != 0)
				guardarJustificacion();

			this.getCatalogos();
			this.buscarJustificaciones();
			this.msgExito = "Se guardo correctamente los datos.";

			HashMap<String, Object> params = new HashMap<String, Object>();
			params.put("pmn", this.getPmn());

		} catch (JsonParseException | JsonGenerationException | JsonMappingException je) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", je);
		} catch (IOException ioe) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", ioe);
		} catch (ResultMapException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (PersistenceException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (TransaccionException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (SQLException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		} catch (ParseException e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
		}
		return Action.SUCCESS;
	}

	public String verificarCategoriasTitulos() {
		try {
			Long id = operacion.compareTo("1") == 0 ? Long.parseLong(request)
					: (Long) this.getSession().get("idContrato");
			int numero = feesContratoBO.verificarCategoriasTitulos(operacion, id);
			msgExito = numero > 0 ? String.valueOf(numero) : "";

		} catch (PersistenceException ibe) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", ibe);
		} catch (Exception e) {
			this.msgError = "Ocurrió un error al obtener los datos.";
			logger.error("Error. {}", e);
			logger.error("Error." + e);
		}
		return Action.SUCCESS;
	}

	public String actualizarCostosTitulos() {
		Long idContrato = (Long) this.getSession().get("idContrato");
		Double costoTotal = Double.parseDouble(request);
		logger.info("CostoTotal: " + costoTotal);
		Map<String, Object> paramNumeroContrato = new HashMap<String, Object>();
		paramNumeroContrato.put("idContrato", idContrato);
		paramNumeroContrato.put("costoTotal", costoTotal);
		paramNumeroContrato.put("response", "");
		feesContratoBO.actualizarCostoTitulos(paramNumeroContrato);
		msgExito = (String) paramNumeroContrato.get("response");
		logger.info("msgExito: " + msgExito);
		return Action.SUCCESS;
	}

	private void getCatalogos() throws TransaccionException {
		try {
			tipoSuscriptorLista = catalogosBO.obtenerTipoSuscriptor();
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		}
		anioTipo = new ArrayList<CatalogoDTO>();
		CatalogoDTO cat1 = new CatalogoDTO("Contractual", "Contractual");
		CatalogoDTO cat2 = new CatalogoDTO("Calendario", "Calendario");
		anioTipo.add(cat1);
		anioTipo.add(cat2);
	}

}