package com.dla.dda.bussines;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dla.dda.domain.constants.FeesType;
import com.dla.dda.domain.contrato.BonoFees;
import com.dla.dda.domain.contrato.ContratoDDA;
import com.dla.dda.domain.contrato.FeesDDA;
import com.dla.dda.domain.contrato.FeesFlat;
import com.dla.dda.domain.contrato.FeesSuscriptor;
import com.dla.dda.domain.contrato.PeriodoFlat;
import com.dla.dda.domain.contrato.Rango;
import com.dla.dda.domain.contrato.TituloDDA;
import com.dla.dda.domain.exceptions.DLAIntegrationException;
import com.dla.dda.persistence.model.DdaTContrato;
import com.dla.dda.persistence.model.DdaTContratoPago;
import com.dla.dda.services.ContratoService;
import com.dla.dda.transforms.ContratoTransform;
import com.dla.dda.transforms.FeesTransform;

/**
 * @see Bussines service para extraer informacion de los contratos
 * @author montieln
 *
 */
@Service
public class ContratoBussines {

	private static Logger logger = LoggerFactory.getLogger(ContratoBussines.class);

	@Autowired
	private ContratoService contratoService;

	public List<ContratoDDA> getContratosXEstudio(Integer idEstudio) throws DLAIntegrationException {
		logger.info("getContratosXEstudio");

		// 1. consultamos los contratos
		List<DdaTContrato> contratosDDA = contratoService.findContratos(idEstudio);

		logger.info("{}", contratosDDA);
		// 2. transformamos al tipo de response
		List<ContratoDDA> response = ContratoTransform.transformToResponse(contratosDDA);
		logger.info("{}", response);

		return response;
	}

	/**
	 * @see Metodo que trae el detalle de contrato en donde incluye sus titulos
	 *      y sus fees
	 * @param idContrato
	 * @return
	 * @throws DLAIntegrationException
	 */
	public ContratoDDA getContratoDetalle(Long idContrato) throws DLAIntegrationException {

		ContratoDDA contratoDetalle = new ContratoDDA();
		
		// Nos traemos el contrato para el detalle
		DdaTContrato contrato = contratoService.getContrato(idContrato);

		// Lo agregamos al tipo de respuesta
		contratoDetalle = ContratoTransform.transformToResponse(contrato);

		// Nos traemos su fees y tipo, nos sirve para traernos su contrato pago
		// y su tipo si es suscripcion o FLAT
		List<DdaTContratoPago> fees = contratoService.findFeesByContratos(idContrato);
		
		// Nos traemos sus fees sea flat o suscripcion
		FeesDDA feesDDA = getFees(contrato, fees);
		
		// nos traemos sus fees dependien
		contratoDetalle.setFeesDDA(feesDDA);

		// nos traemos sus titulos
		List<TituloDDA> titulos = contratoService.findTitulos(idContrato);
		
		contratoDetalle.setTituloDDA(titulos);

		return contratoDetalle;
	}

	/**
	 * @see Metodo que se trae los fees del contrato pago
	 * @param fees
	 * @return
	 * @throws DLAIntegrationException
	 */
	public FeesDDA getFees(DdaTContrato contrato, List<DdaTContratoPago> fees) throws DLAIntegrationException {

		FeesDDA feesDDA = new FeesDDA();

		// para suscriptotres
		List<FeesSuscriptor> suscriFees = new ArrayList<>();

		// Para flat
		FeesFlat flatFees = new FeesFlat();
		Map<String, List<PeriodoFlat>> periodosFlat = new HashMap<String, List<PeriodoFlat>>();

		for (DdaTContratoPago pago : fees) {

			Long idContratoPago = pago.getIdContratoPago().longValue();
			String tipoPago = pago.getTipoPago();

			logger.info(" [{}] [{}]", idContratoPago, tipoPago);

			FeesType type = FeesType.getType(pago.getTipoPago());

			switch (type) {

			case SUSCRIPCION:

				Map<String, List<Rango>> periodosSuscripcion = contratoService
						.findPeriodosSuscripcionFees(idContratoPago);

				FeesSuscriptor suscriptor = FeesTransform.adapt(pago, periodosSuscripcion);
				suscriFees.add(suscriptor);

				break;
			case FLAT:
				// Consultamos periodos
				Map<String, List<PeriodoFlat>> periodos = contratoService.findPeriodosFlatFees(idContratoPago);
				FeesTransform.adaptPeriodosFlatFees(periodosFlat, pago, periodos);

				break;
			case UNKNOW:
			default:
				logger.error("Tipo desconocido [{}]", type);
				break;
			}

		}

		flatFees.setPeriodos(periodosFlat);

		// Agregamos si existe de este tipo
		feesDDA.setSuscriptor(suscriFees);
		feesDDA.setFlat(flatFees);
		
		BonoFees bono = contratoService.findBonosFlatFees(contrato.getIdContrato());
		feesDDA.setBono(bono);
		

		return feesDDA;
	}

}
