package com.mx.dla.dda.factura.general.actions;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.apache.ibatis.executor.result.ResultMapException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;

import com.mx.dla.dda.catalogos.dtos.EstudioDTO;
import com.mx.dla.dda.catalogos.dtos.IndicadorDTO;
import com.mx.dla.dda.contrato.common.actions.BaseContratoAction;
import com.mx.dla.dda.contrato.generales.bos.PoblarGeneralesBO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.factura.general.bos.FacturacionBO;
import com.mx.dla.dda.factura.general.dtos.ContratoFacturaDTO;
import com.mx.dla.dda.factura.general.dtos.FacturaGeneralDTO;
import com.mx.dla.dda.general.constants.SiNoOpcion;
import com.mx.dla.dda.factura.constants.TipoPagoFactura;
import com.opensymphony.xwork2.Action;

public class FacturacionAction extends BaseContratoAction {

	private static final long serialVersionUID = 1L;
	private FacturaGeneralDTO factura = new FacturaGeneralDTO();

	@Autowired
	private FacturacionBO facturacionBO;

	@Autowired
	private PoblarGeneralesBO poblarGeneralesBO;

	private String idEstudio;
	private String idFactura;
	private String aprobado;
	private String detalleCto;
	private String indicadorIVA;

	public String cargaFacturaGeneral() {

		try {
			String facturaId = (String) this.getSession().get("idFactura");
			Long idFactura = facturaId != null ? new Long(facturaId) : null;
			factura = facturacionBO.cargaFacturaInfoGeneral(idFactura);
			logger.info("cargaFacturaGeneral COMPLETE: " + factura);
		} catch (Exception e) {
			logger.error("Ha ocurrido el siguiente error durante la consulta. {}", e);
			addActionError("Ha ocurrido el siguiente error durante la consulta: " + e.getMessage());
		}
		bajaInfoDeSession();
		return Action.SUCCESS;
	}

	public String cargaFacturaDetalle() throws TransaccionException {

		try {
			Long idEst = new Long(Long.parseLong(idEstudio));
			Long idFactura = !this.idFactura.trim().equals("") ? new Long(this.idFactura) : null;
			Integer approved = !this.aprobado.trim().equals("") ? new Integer(this.aprobado) : null;

			factura = facturacionBO.cargaFacturaInfoGeneral(idFactura);

			factura.setIdEstudio(idEst);
			factura.setIdFactura(idFactura);
			factura.setApproved(approved);

			indicadorIVA = indicadorIVA == null || indicadorIVA.equals("") ? factura.getIndicadorIva() : indicadorIVA;

			List<ContratoFacturaDTO> detalles = facturacionBO.cargaFacturaInfoDetalle(idEst, idFactura,
					approved.intValue() == 0 ? false : true, indicadorIVA);
			factura.setContratos(detalles);
			logger.info("cargaFacturaDetalle COMPLETE: " + factura);
		} 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);
		}

		bajaInfoDeSession();
		return Action.SUCCESS;
	}

	public String guardaFactura() throws TransaccionException {

		try {
			ObjectMapper mapper = new ObjectMapper();
			logger.info("factura: {}", factura);
			List<ContratoFacturaDTO> contratos;
			contratos = mapper.readValue(detalleCto, new TypeReference<List<ContratoFacturaDTO>>() {
			});

			factura.setContratos(contratos);
			facturacionBO.guardarFactura(factura);

			if (factura.getApproved() == 1)
				facturacionBO.notificarServicioRest(factura);

		} catch (JsonParseException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (JsonMappingException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} catch (IOException e) {
			logger.error("Error. {}", e);
			throw new TransaccionException("Ocurrio un error", e);
		} 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);
		}
		this.getSession().put("idFactura", String.valueOf(factura.getIdFactura()));

		addActionMessage("La factura se ha guardado con exito");
		bajaInfoDeSession();
		return Action.SUCCESS;
	}

	public String reenvioNotificacion() {
		logger.info("Reenvio notificacion factura, idFactura: {}", idFactura);

		FacturaGeneralDTO factura = new FacturaGeneralDTO();
		factura.setIdFactura(new Long(idFactura));

		facturacionBO.notificarServicioRest(factura);

		try {
			this.factura = facturacionBO.consultaFactura(new Long(idFactura));
		} catch (ResultMapException e) {
			logger.error("Ha ocurrido el siguiente error durante el guardado. {}", e);
			addActionError("Ha ocurrido el siguiente error durante el guardad " + e.getMessage());
		} catch (NumberFormatException e) {
			logger.error("Ha ocurrido el siguiente error durante el guardado. {}", e);
			addActionError("Ha ocurrido el siguiente error durante el guardad " + e.getMessage());
		} catch (SQLException e) {
			logger.error("Ha ocurrido el siguiente error durante el guardado. {}", e);
			addActionError("Ha ocurrido el siguiente error durante el guardad " + e.getMessage());
		} catch (TransaccionException e) {
			logger.error("Ha ocurrido el siguiente error durante el guardado. {}", e);
			addActionError("Ha ocurrido el siguiente error durante el guardad " + e.getMessage());
		}

		logger.info("factura: {}", factura);

		return Action.SUCCESS;
	}

	public void bajaInfoDeSession() {
		this.setPmn((String) this.getSession().get("pmn"));
		this.setPmnReturn((String) this.getSession().get("pmnReturn"));
	}

	public FacturaGeneralDTO getFactura() {
		return factura;
	}

	public List<EstudioDTO> getEstudios() {
		try {
			return poblarGeneralesBO.obtenListaEstudios();
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			return null;
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			return null;
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			return null;
		}
	}

	public List<IndicadorDTO> getIndicadoresIva() {
		try {
			return poblarGeneralesBO.obtenerIndicadores();
		} catch (ResultMapException e) {
			logger.error("Error. {}", e);
			return null;
		} catch (SQLException e) {
			logger.error("Error. {}", e);
			return null;
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
			return null;
		}
	}

	public List<SiNoOpcion> getSiNoOpcion() {
		return Arrays.asList(SiNoOpcion.values());
	}

	public List<TipoPagoFactura> getTiposPago() {
		return Arrays.asList(TipoPagoFactura.values());
	}

	public String getIdEstudio() {
		return idEstudio;
	}

	public String getIdFactura() {
		return idFactura;
	}

	public String getAprobado() {
		return aprobado;
	}

	public String getDetalleCto() {
		return detalleCto;
	}

	public String getIndicadorIVA() {
		return indicadorIVA;
	}

	public void setFactura(FacturaGeneralDTO factura) {
		this.factura = factura;
	}

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

	public void setIdFactura(String idFactura) {
		this.idFactura = idFactura;
	}

	public void setAprobado(String aprobado) {
		this.aprobado = aprobado;
	}

	public void setDetalleCto(String detalleCto) {
		this.detalleCto = detalleCto;
	}

	public void setIndicadorIVA(String indicadorIVA) {
		this.indicadorIVA = indicadorIVA;
	}
}