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

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.mx.dla.dda.catalogos.dtos.EstudioDTO;
import com.mx.dla.dda.catalogos.dtos.IndicadorDTO;
import com.mx.dla.dda.catalogos.dtos.RegistroCatalogoDTO;
import com.mx.dla.dda.contrato.generales.daos.GeneralesDAO;
import com.mx.dla.dda.contrato.generales.daos.PoblarGeneralesDAO;
import com.mx.dla.dda.contrato.generales.dtos.ApartadoDTO;
import com.mx.dla.dda.contrato.generales.dtos.AreaAutorizadorDTO;
import com.mx.dla.dda.contrato.generales.dtos.AreaDTO;
import com.mx.dla.dda.contrato.generales.dtos.BotonDTO;
import com.mx.dla.dda.contrato.generales.dtos.FechasDTO;
import com.mx.dla.dda.contrato.generales.dtos.NumeroTitulosTransDTO;
import com.mx.dla.dda.contrato.generales.enums.CatalogoTipo;
import com.mx.dla.dda.contrato.generales.enums.Estatus;
import com.mx.dla.dda.contrato.generales.enums.Movimiento;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.global.bos.BaseBO;

@Component
public class PoblarGeneralesBO extends BaseBO{
	
	@Autowired
	private PoblarGeneralesDAO poblarGeneralesDAO;
	
	@Autowired
	private GeneralesDAO generalesDAO;
	
	public Long toLongTipoContrato(Object tipoContrato) {//para pasar el parametro que viene de sesion
		
		Long tipoContratoL = null;
		String tipoContratoS = "";
		
		if(tipoContrato != null){
			tipoContratoS = tipoContrato.toString();
			tipoContratoL = Long.parseLong(tipoContratoS);
		}
		
		return tipoContratoL;
	}
	
	public List<EstudioDTO> obtenListaEstudiosAddons() throws ResultMapException, SQLException, TransaccionException {
		
		List<EstudioDTO> estudios = null;
		
		try{
			estudios = poblarGeneralesDAO.obtenerEstudiosAddons();
		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return estudios;
	}
	
	public List<EstudioDTO> obtenListaEstudios() throws ResultMapException, SQLException, TransaccionException {
		
		List<EstudioDTO> estudios = null;
		
		try{
			estudios = poblarGeneralesDAO.obtenerEstudios();
		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return estudios;
	}
	
	@SuppressWarnings("unchecked")
	public List<? extends RegistroCatalogoDTO> obtenListaComponentes(CatalogoTipo tipo, Long tipoContrato){
		
		List<RegistroCatalogoDTO> componentes = null;
		
		if(tipo.equals(CatalogoTipo.CATEGORIA)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerCategorias();
		}else if(tipo.equals(CatalogoTipo.SERVICIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerServiciosPorTipo(tipoContrato);//tipoContrato para filtrar por tipo
		}else if(tipo.equals(CatalogoTipo.TERRITORIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerTerritorios();
		}else if(tipo.equals(CatalogoTipo.MEDIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerMediosEntrega();
		}else if(tipo.equals(CatalogoTipo.FILIAL)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerFiliales();
		}else if(tipo.equals(CatalogoTipo.TYPE)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerTypesPorTipo(tipoContrato);
		}
		
		return componentes;	
	}
	
	@SuppressWarnings("unchecked")
	public List<? extends RegistroCatalogoDTO> obtenerListaComponentesActuales(Long idContrato, CatalogoTipo tipo){
		List<RegistroCatalogoDTO> componentes = null;
		
		if(tipo.equals(CatalogoTipo.CATEGORIA)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerCategoriasActuales(idContrato);
		}else if(tipo.equals(CatalogoTipo.SERVICIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerServiciosActuales(idContrato);
		}else if(tipo.equals(CatalogoTipo.TERRITORIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerTerritoriosActuales(idContrato);
		}else if(tipo.equals(CatalogoTipo.MEDIO)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerMediosEntregaActuales(idContrato);
		}else if(tipo.equals(CatalogoTipo.FILIAL)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerFilialesActuales(idContrato);
		}else if(tipo.equals(CatalogoTipo.TYPE)) {
			componentes = (List<RegistroCatalogoDTO>) poblarGeneralesDAO.obtenerTypesActuales(idContrato);
		}
		
		return componentes;
	}
	
	public Long establecerEstatusInicial() {
		
		return Estatus.Sin.getValor();
		
	}
	
	public String obtenDescripcionEstatus(Long idEstatus) throws ResultMapException, SQLException, TransaccionException{
		String descripcion = null;
		
		try{
			descripcion = poblarGeneralesDAO.obtenerDescripcionEstatus(idEstatus);
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return descripcion;
	}
	
	public List<BotonDTO> obtenerBotones(Long idEstatus) throws ResultMapException, SQLException, TransaccionException {
		List<BotonDTO> botones = null;
			
		try{
			botones = poblarGeneralesDAO.obtenerBotones(idEstatus);
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		return botones;
	}
	
	public Long establecerMovimientoInicial(){
		return Movimiento.Original.getValor();
	}
	
	public String obtenerDescripcionMovimiento(Long idMovimiento) throws ResultMapException, SQLException, TransaccionException{
		String descripcion = null;
		
		try{
			descripcion = poblarGeneralesDAO.obtenerDescripcionMovimiento(idMovimiento);
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return descripcion;
	}
	
	public List<EstudioDTO> obtenerEstudioActual(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		
		List<EstudioDTO> estudio = null;
		
		try{
			estudio = poblarGeneralesDAO.obtenerEstudioActual(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);
        }
		
		return estudio;
	}
	
	
	public Long obtenEstudioActualV(Long idContrato) throws ResultMapException, SQLException, TransaccionException { //revisar bien para que se usa
		
		Long idEstudio = null;
		
		for(EstudioDTO estudioTemp: obtenerEstudioActual(idContrato)){
			idEstudio = estudioTemp.getIdEstudio();
		}
		
		return idEstudio;
	}
	
	public String formateaFecha(Date fecha){
		
		String respuesta = null;
		SimpleDateFormat formatoDeFecha = new SimpleDateFormat("MM/dd/yyyy");
		
		if(fecha != null) {
			respuesta = formatoDeFecha.format(fecha);
		}
		
		return respuesta;
	}
	
	public Date obtenerFechaMinContratoTitulo(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		
		Date fechaMin = null;
		
		try {
			fechaMin = poblarGeneralesDAO.obtenerFechaMinContratoTitulo(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);
        }
		
		return fechaMin;
	}
	
	public Date obtnerFechaMaxContratoTitulo(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		Date fechaMax = null;
		
		try {
			fechaMax = poblarGeneralesDAO.obtenerFechaMaxContratoTitulo(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);
        }
		
		return fechaMax;
	}
	
	public List<? extends RegistroCatalogoDTO> filtraRegistrosCatalogo(List<? extends RegistroCatalogoDTO> todos, List<? extends RegistroCatalogoDTO> seleccionados){
		
		Map<Integer, String> hashSeleccionados = new HashMap<>();
		String descripcion;
		List<RegistroCatalogoDTO> noSeleccionados = new ArrayList<>();
		
		for(RegistroCatalogoDTO registroS:seleccionados){
			hashSeleccionados.put(registroS.getId(), registroS.getDescripcion());
		}
		
		for(RegistroCatalogoDTO registroT:todos){
			descripcion = hashSeleccionados.get(registroT.getId());
			if(descripcion == null){
				noSeleccionados.add(registroT);
			}
		}
		
		return noSeleccionados;
	}

	public List<AreaAutorizadorDTO> obtenAreaAutorizador(Long idContrato) throws ResultMapException, SQLException, TransaccionException{
		List<AreaAutorizadorDTO> listaAreaAutorizador = null;
		
		try {
			listaAreaAutorizador = poblarGeneralesDAO.obtenerAreaAutorizador(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);
        }
		
		return listaAreaAutorizador;
	}
	
	public List<AreaAutorizadorDTO> habilitaSiguienteAutorizacion(List<AreaAutorizadorDTO> areaAutorizador, String expediente) {
		
		AreaDTO infoArea = generalesDAO.obtenerAreaPorExpediente(expediente);
		int i;
		
		for(i = 0; i < areaAutorizador.size(); i++){
			
			if(areaAutorizador.get(i).getExpediente() == null){
				break;
			}
		}
		
		if(i < areaAutorizador.size()){
			if(areaAutorizador.get(i).getDescripcionArea().equals(infoArea.getDescripcionArea())){
				areaAutorizador.get(i).setSeHabilita(1);
			}
		}
		
		
		
		return areaAutorizador;
	}
	
	public Integer obtenerOrdenWF(List<AreaAutorizadorDTO> areaAutorizador) {
		
		Integer resp = 0;
		
		for(AreaAutorizadorDTO aa : areaAutorizador) {
			if(aa.getExpediente() == null){
				resp = aa.getOrden();
				break;
			}
		}
		
		return resp;
	}
	
	public List<EstudioDTO> obtenerEstudioOficial() throws ResultMapException, SQLException, TransaccionException {
		List<EstudioDTO> estudiosOficiales = null;
		
		try {
			estudiosOficiales = poblarGeneralesDAO.obtenerEstudioOficial();
		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return estudiosOficiales;
	}
	
	public boolean hayContratosConVirtual(Long idEstudio, Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		
		List<Long> contratosConVirtual = null;
		
		try {
			
			contratosConVirtual = poblarGeneralesDAO.obtenContratoConVirtual(idEstudio, 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);
        }
		
		if(contratosConVirtual.size() == 0){
			return false;
		}else {
			return true;
		}
	}
	
	public List<ApartadoDTO> obtenerApartados(Long idEstudio, Long idApartado) throws ResultMapException, SQLException, TransaccionException {
		
		List<ApartadoDTO> apartados = null;
		ApartadoDTO aux = new ApartadoDTO();
		try {
			apartados = poblarGeneralesDAO.obtenerApartados(idEstudio); //se obtiene todos los apartados, eso apartir de un cambio indicado
			if(idApartado != null){
				for(int i = 0; i < apartados.size(); i++) {
					if(apartados.get(i).getIdApartado() == idApartado) {
						aux = apartados.get(i);
						apartados.remove(i);
						apartados.add(0, aux);
					}
				}
			}
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return apartados;
	}
	
	public FechasDTO obtenFechasContrato(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		
		FechasDTO fechas = null;
		
		try {
			fechas = poblarGeneralesDAO.obtenFechasContrato(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);
        }
		
		return fechas;
	}
	
	public List<Long> validaIdsCatalogo(List<Long> idsCatalogo, Long idContrato, String tipo) throws ResultMapException, SQLException, TransaccionException{
		
		List<Long> noQuitar = new ArrayList<Long>();
		Integer noVeces = 0;
		
		try {
			
			for(Long n : idsCatalogo) {
				
				if(tipo.equals("categorias")) {
					noVeces = poblarGeneralesDAO.obtenNoCategoriaEnContratoTitulo(n, idContrato);
				}else {
					noVeces = poblarGeneralesDAO.obtenNoServiciosEnContratoServicio(n, idContrato);
				}
				
				if(noVeces > 0){
					noQuitar.add(n);
				}
				
			}
			
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		
		return noQuitar;
	}

	
	
	
	public String tipoOperacionPorNumeroContrato(String numeroContrato){
		
		String tipo = "";
		
		char c = numeroContrato.charAt(numeroContrato.length() - 1);
		
		switch(c){
		case 'O':
			tipo = Movimiento.Original.getDescripcion();
			break;
		case 'A':
			tipo = Movimiento.Adendum.getDescripcion();
			break;
		case 'E':
			tipo = Movimiento.Enmienda.getDescripcion();
			break;
		case 'C':
			tipo = Movimiento.Enmienda.getDescripcion();
			break;
		case 'V':
			tipo = Movimiento.Virtual.getDescripcion();
			break;
		}
		
		return tipo;
	}
	
	public String obtenerDescripcionEstudio(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		String descripcionEstudio = "";
		
		List<EstudioDTO> estudios = obtenerEstudioActual(idContrato);
		descripcionEstudio = estudios.get(0).getDescripcionEstudio();
		
		return descripcionEstudio;
	}
	
	
	public List<IndicadorDTO> obtenerIndicadores() throws ResultMapException, SQLException, TransaccionException{
		List<IndicadorDTO> indicadores = null;
		try{
			indicadores = poblarGeneralesDAO.obtenerIndicadores(); 
		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		return indicadores;
	}
	
	public List<IndicadorDTO> obtenerIndicadoresConActual(String indicadorActual) throws ResultMapException, SQLException, TransaccionException{
		List<IndicadorDTO> indicadores = null;
		
		indicadores = obtenerIndicadores();
		if(!indicadores.isEmpty()){
			if(indicadorActual != null) {
				IndicadorDTO aux = new IndicadorDTO();
				int position = 0;
				
				for(int i = 0; i < indicadores.size(); i++){
					logger.debug("ac : [{}]  rec : [{}]", indicadorActual, indicadores.get(i).getClaveIva());
					if(indicadores.get(i).getClaveIva().equals(indicadorActual) ){
						aux = indicadores.get(i);
						position = i;
					}
				}
				
				indicadores.remove(position);
				indicadores.add(0, aux);
			}
		}
		
		return indicadores;
	}
	
	public Integer obtenerNumeroTitulosEnContratoSL(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		Integer numeroTitulos = 0;
		try {
			numeroTitulos = poblarGeneralesDAO.numeroTitulosEnContratoTL(idContrato);
			if (numeroTitulos == null)
				numeroTitulos = 0;
		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		return numeroTitulos;
	}

	public NumeroTitulosTransDTO obtenerNumeroTitulosEnContratoTrans(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		NumeroTitulosTransDTO numeroTitulos = null;

		try {
			numeroTitulos = poblarGeneralesDAO.numeroTitulosEnContratoTrans(idContrato);
			if (numeroTitulos == null)
				numeroTitulos = new NumeroTitulosTransDTO(idContrato, 0, 0, 0);
		}catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		return numeroTitulos;
	}
	
	
}
