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

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import com.mx.dla.dda.contrato.fees.daos.FeesContratoDAO;
import com.mx.dla.dda.contrato.fees.dtos.FeesContratoPagoBD;
import com.mx.dla.dda.contrato.fees.dtos.FeesContratoPagoDTO;
import com.mx.dla.dda.contrato.fees.dtos.FeesFlatBD;
import com.mx.dla.dda.contrato.fees.dtos.FeesPagoFlat;
import com.mx.dla.dda.contrato.fees.dtos.FeesSuscriptorBD;
import com.mx.dla.dda.contrato.fees.dtos.PagoFlatAnioDTO;
import com.mx.dla.dda.contrato.minimoseleccion.bos.MinimoSeleccionBO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.global.bos.BaseBO;

@Service
public class FeesFlatBO extends BaseBO {

	@Autowired
	private FeesContratoDAO feesContratoDAO;

	@Autowired
	private MinimoSeleccionBO minimoSeleccionBO;

	private int ANIO_FLAT = 6;

	public FeesContratoPagoDTO crearFlat(FeesContratoPagoBD pagoBD, List<FeesFlatBD> feeBD) throws ParseException {
		FeesContratoPagoDTO fee = new FeesContratoPagoDTO();
		int numAnios = ANIO_FLAT;

		if (feeBD == null) {
			List<FeesPagoFlat> flats = new ArrayList<FeesPagoFlat>();
			flats.add(new FeesPagoFlat(0L, "", numAnios));

			fee = new FeesContratoPagoDTO(-1L, 0L, 0L, "", "", "", "", "nuevo", null, flats);
			fee.setFlats(flats);
			fee.setMaxAnios(numAnios);
		} else {
			List<FeesPagoFlat> flats = new ArrayList<FeesPagoFlat>();
			for (FeesFlatBD itemBD : feeBD) {
				boolean existente = false;
				for (FeesPagoFlat item : flats) {
					if (item.getIdCategoria().longValue() == itemBD.getIdCategoria().longValue()) {
						item.getAnios()
								.add(new PagoFlatAnioDTO(itemBD.getIdFlat(), itemBD.getAnio(), itemBD.getCosto()));
						existente = true;
					}
				}
				if (!existente) {
					FeesPagoFlat pago = new FeesPagoFlat(itemBD.getIdCategoria(), itemBD.getDesCategoria(), 0);
					pago.getAnios().add(new PagoFlatAnioDTO(itemBD.getIdFlat(), itemBD.getAnio(), itemBD.getCosto()));
					flats.add(pago);
				}
			}

			numAnios = flats.get(0).getAnios().size();
			fee = new FeesContratoPagoDTO(pagoBD.getIdContratoPago(), pagoBD.getIdContrato(),
					pagoBD.getIdTipoSuscriptor(), this.getFecha(pagoBD.getFechaInicio()),
					this.getFecha(pagoBD.getFechaFin()), pagoBD.getTipoAnio(), pagoBD.getTipoPago(), "editar", null,
					flats);
			fee.setMaxAnios(numAnios);
			fee.setAnioContrato(pagoBD.getAnioContrato());
		}
		return fee;
	}

	public void guardarFlat(FeesContratoPagoDTO periodo, Long idContrato) throws ParseException, TransaccionException {

		FeesContratoPagoBD contratoPago = new FeesContratoPagoBD(0L, idContrato, periodo.getIdSuscriptor(),
				periodo.getTipoPago(), periodo.getTipoAnio(), this.crearFecha(periodo.getFechaInicio()),
				this.crearFecha(periodo.getFechaFin()));

		try {
			contratoPago.setAnioContrato(periodo.getAnioContrato());
			feesContratoDAO.guardarContratoPago(contratoPago);
			this.guardarFlat(periodo, contratoPago);
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void guardarFlat(FeesContratoPagoDTO periodo, FeesContratoPagoBD contratoPago)
			throws ParseException, TransaccionException {
		List<FeesSuscriptorBD> minSelAnio = new ArrayList<FeesSuscriptorBD>();
		List<FeesSuscriptorBD> minSelCat = new ArrayList<FeesSuscriptorBD>();
		List<FeesFlatBD> flats = new ArrayList<FeesFlatBD>();
		boolean primero = true;

		for (FeesPagoFlat flat : periodo.getFlats()) {
			for (PagoFlatAnioDTO anio : flat.getAnios()) {
				if (primero)
					minSelAnio.add(new FeesSuscriptorBD(contratoPago.getIdContratoPago(), anio.getAnio().intValue()));
				flats.add(new FeesFlatBD(0L, contratoPago.getIdContratoPago(), flat.getIdCategoria(),
						anio.getAnio().intValue(), anio.getCosto()));
				minSelCat.add(new FeesSuscriptorBD(contratoPago.getIdContratoPago(), anio.getAnio().intValue(),
						flat.getIdCategoria()));

			}
			primero = false;
		}
		try {
			minimoSeleccionBO.guardarMinSeleccionXAnio(minSelAnio); // Se guarda el minimo de seleccion por anio
			logger.info("Se ha guardado minimo sel por anio");

			feesContratoDAO.guardarPagoFlatAll(flats); // Se guardan los pagos flat
			logger.info("Se ha guardado los pagos flats. " + flats.toString());

			minimoSeleccionBO.guardarMinSeleccionXCatAnio(minSelCat); // Se guarda el minimo de seleccion por categoria
																		// con el anio asociado
			logger.info("Se ha guardado el minimo sel." + minSelCat.toString());
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void editarFlat(FeesContratoPagoDTO periodo) throws ParseException, TransaccionException {

		try {
			logger.info("Se edita flat.");

			FeesContratoPagoBD contratoPago = new FeesContratoPagoBD(periodo.getIdContratoPago(),
					periodo.getIdContrato(), periodo.getIdSuscriptor(), periodo.getTipoPago(), periodo.getTipoAnio(),
					this.crearFecha(periodo.getFechaInicio()), this.crearFecha(periodo.getFechaFin()));
			contratoPago.setAnioContrato(periodo.getAnioContrato());
			feesContratoDAO.actualizarContratoPago(contratoPago);
			this.guardarFlat(periodo, contratoPago);
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void eliminarFlats(Long idContrato) throws TransaccionException {

		try {
			this.eliminarPagosFlat(idContrato); // Se eliminan los pagos flat
			minimoSeleccionBO.eliminarMinSeleccionXCto(idContrato);
			feesContratoDAO.eliminarContratoPagoXCto(idContrato);
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void eliminarFlat(FeesContratoPagoDTO periodo) throws TransaccionException {
		try {
			feesContratoDAO.eliminarPagoFlat(periodo.getIdContratoPago()); // Se eliminan los pagos flat
			minimoSeleccionBO.eliminarMinSeleccion(periodo.getIdContratoPago(), null); // Se elimina minimum seleccion
			feesContratoDAO.eliminarContratoPago(periodo.getIdContratoPago()); // Se elimina el contratopago
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void eliminarPagosFlat(Long idContrato) throws TransaccionException {
		try {
			feesContratoDAO.eliminarPagoFlatxCto(idContrato); // Se eliminan los pagos flat de todo el contrato
			minimoSeleccionBO.eliminarMinSeleccionXCto(idContrato); // Se elimina minimum seleccion de todo el contrato
			logger.info("Se han eliminado los pago flat");
		} catch (PersistenceException e) {
			throw new TransaccionException("Error al cargar los datos.", e);
		} catch (DataAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public Date crearFecha(String valor) throws ParseException {
		DateFormat formatter1 = new SimpleDateFormat("MM/dd/yyyy");
		Date fecha = formatter1.parse(valor);
		return fecha;
	}

	public String getFecha(Date fecha) {
		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		return sdf.format(fecha);
	}
}
