using Exferia_Aplicacion.Calculos;
using Exferia_Aplicacion.General;
using Exferia_Compras._1_Datos;
using Exferia_EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exferia_Compras.General
{
    public class Funciones_Compras
    {
        #region Pedidos
        public static INTERNO_ValorDevuelto_Modelo Recalcular_Situacion_PedidosCompra(List<long> _lst_idPedidoCompraLinea, List<long> _lst_idEntradaMercanciaLinea, List<long> _lst_idEntradaMercanciaCabecera)
        {
            INTERNO_ValorDevuelto_Modelo mdl_INTERNO_ValorDevuelto_Modelo = new INTERNO_ValorDevuelto_Modelo();
            mdl_INTERNO_ValorDevuelto_Modelo.TodoCorrecto = true;

            try
            {
                //Clases de negocio
                COM_PedidosComprasCabecera_Datos obj_COM_PedidosComprasCabecera_Datos = new COM_PedidosComprasCabecera_Datos();
                COM_EntradasMercanciaLineas_Datos obj_COM_EntradasMercanciaLineas_Datos = new COM_EntradasMercanciaLineas_Datos();

                //Si el listado de Entradas de mercancia linea no esta a nulo se buscan los idPedidoCompraLinea Asociados
                if (_lst_idEntradaMercanciaLinea!=null)
                {
                    _lst_idPedidoCompraLinea = obj_COM_EntradasMercanciaLineas_Datos.Obtener_IdsPedidoCompraLinea_PorListado_EntradaMercanciaLinea(_lst_idEntradaMercanciaLinea);
                }
                //Si el listado de Entradas de mercancia Cabecera no esta a nulo se buscan los idPedidoCompraLinea Asociados
                else if (_lst_idEntradaMercanciaCabecera != null)
                {
                    _lst_idPedidoCompraLinea = obj_COM_EntradasMercanciaLineas_Datos.Obtener_IdsPedidoCompraLinea_PorListado_EntradaMercanciaCabecera(_lst_idEntradaMercanciaCabecera);
                }


                if (_lst_idPedidoCompraLinea != null && _lst_idPedidoCompraLinea.Count > 0)
                {
                    //## 1º--> Listado de COM_PedidosComprasCabecera a Verificar
                    List<COM_PedidosComprasCabecera> lst_COM_PedidosComprasCabecera = obj_COM_PedidosComprasCabecera_Datos.Obtener_Por_PedidosCompraLineas(_lst_idPedidoCompraLinea);

                    if (lst_COM_PedidosComprasCabecera != null &&
                        lst_COM_PedidosComprasCabecera.Count > 0)
                    {
                        //RECORRER COM_PedidosComprasCabecera
                        foreach (COM_PedidosComprasCabecera mdl_COM_PedidosComprasCabecera in lst_COM_PedidosComprasCabecera)
                        {
                            //Inicializamos para saber la situacion de todas las filas
                            List<int> lst_Situacion_Filas = new List<int>();

                            if (mdl_COM_PedidosComprasCabecera.COM_PedidosComprasLineas != null &&
                                mdl_COM_PedidosComprasCabecera.COM_PedidosComprasLineas.Count > 0)
                            {
                                //RECORRER COM_PedidosComprasLineas
                                foreach (COM_PedidosComprasLineas mdl_COM_PedidosComprasLineas in mdl_COM_PedidosComprasCabecera.COM_PedidosComprasLineas.Where(m => m.fechaBorrado == null).ToList())
                                {
                                    //## 2º--> OBTENEMOS LOS REGISTROS YA CALCULADOS DONDE SE HA RELACIONADO YA LA LINEA DE PEDIDO DE COMPRA
                                    List<INTERNO_Calculos_CantidadesRestantes> lst_INTERNO_Calculos_CantidadesRestantes = obj_COM_EntradasMercanciaLineas_Datos.Obtener_Calculos_Para_CantidadesRestantes(mdl_COM_PedidosComprasLineas.id);

                                    //## 3º--> PASAMOS LAS CANTIDADES DE TODAS LAS LINEAS QUE HAYAN A EMBALAJE PRINCIPAL
                                    if (lst_INTERNO_Calculos_CantidadesRestantes != null &&
                                        lst_INTERNO_Calculos_CantidadesRestantes.Count > 0)
                                    {
                                        //## 4º--> RECORRER CADA CALCULO PARA PASARLO AL EMBALAJE PRINCIPAL LOS CALCULOS ################################################################################################
                                        decimal dcm_Cantidad_CALCULADOS = 0;
                                        foreach (INTERNO_Calculos_CantidadesRestantes mdl_INTERNO_Calculos_CantidadesRestantes in lst_INTERNO_Calculos_CantidadesRestantes)
                                        {
                                            if (mdl_INTERNO_Calculos_CantidadesRestantes.Cantidad != 0m)
                                            {
                                                dcm_Cantidad_CALCULADOS += Calculos_FuncionesGenerales.Calcular_Cantidad_SegunEmbalajes(mdl_INTERNO_Calculos_CantidadesRestantes.Embalaje_id,
                                                                                                                                        mdl_INTERNO_Calculos_CantidadesRestantes.Embalaje_Operacion,
                                                                                                                                        mdl_INTERNO_Calculos_CantidadesRestantes.Embalaje_Relacion,
                                                                                                                                        mdl_INTERNO_Calculos_CantidadesRestantes.Cantidad,
                                                                                                                                        mdl_INTERNO_Calculos_CantidadesRestantes.EmbalajePrincipal_idEmbalaje,
                                                                                                                                        true
                                                                                                                                        );
                                            }
                                        }

                                        decimal dcm_Porcentaje_Cancelacion = mdl_COM_PedidosComprasLineas.MAE_Articulos.porcentajeCancelacion_Compras != null ? mdl_COM_PedidosComprasLineas.MAE_Articulos.porcentajeCancelacion_Compras.Value : 0m;

                                        //COMPROBAR SI EL CALCULO ESTA HECHO EN EL EMBALAJE PRINCIPAL
                                        decimal dcm_Cantidad_Principal_PEDIDOCOMPRALINEA = Calculos_FuncionesGenerales.Calcular_Cantidad_SegunEmbalajes(mdl_COM_PedidosComprasLineas.idEmbalaje,
                                                                                                                                                        mdl_COM_PedidosComprasLineas.operacion,
                                                                                                                                                        mdl_COM_PedidosComprasLineas.relacion,
                                                                                                                                                        mdl_COM_PedidosComprasLineas.cantidad,
                                                                                                                                                        mdl_COM_PedidosComprasLineas.embalajePrincipalDelArticulo_idEmbalaje,
                                                                                                                                                        true
                                                                                                                                                        );

                                        //CANTIDAD ####################################################################################################
                                        decimal dcm_Cantidad_Principal_RESULTADO = dcm_Cantidad_Principal_PEDIDOCOMPRALINEA - dcm_Cantidad_CALCULADOS;

                                        //Si la cantidad que queda por servir es mayor o igual que el porcentaje de cancelacion , esta servida
                                        if (dcm_Porcentaje_Cancelacion != 0m && dcm_Cantidad_Principal_RESULTADO >= Funciones.RedondearDecimal(dcm_Cantidad_Principal_PEDIDOCOMPRALINEA * (dcm_Porcentaje_Cancelacion / 100), 3))
                                        {
                                            //Servida
                                            lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_SERVIDO.Codigo));
                                        }
                                        //Negativo
                                        else if (dcm_Cantidad_Principal_PEDIDOCOMPRALINEA < 0 && dcm_Cantidad_Principal_RESULTADO >= 0m)
                                        {
                                            //Servida
                                            lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_SERVIDO.Codigo));
                                        }
                                        //Positivo
                                        else if (dcm_Cantidad_Principal_RESULTADO <= 0)
                                        {
                                            //Servida
                                            lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_SERVIDO.Codigo));
                                        }
                                        //Parte Pendiente
                                        else if (dcm_Cantidad_CALCULADOS > 0)
                                        {
                                            lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PARTEPENDIENTE.Codigo));
                                        }
                                        //Pendiente
                                        else
                                        {
                                            lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PENDIENTE.Codigo));
                                        }
                                    }
                                    else
                                    {
                                        //Pendiente
                                        lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PENDIENTE.Codigo));
                                    }
                                }
                            }
                            else
                            {
                                //Pendiente
                                lst_Situacion_Filas.Add(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PENDIENTE.Codigo));
                            }

                            //Situacion Final del PedidoCompra
                            //Si tiene algun registro como parte pendiente, se ponen como parte pediente
                            if (lst_Situacion_Filas.Where(m => m.Equals(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PARTEPENDIENTE.Codigo))).Count() > 0)
                            {
                                obj_COM_PedidosComprasCabecera_Datos.Actualizar_Situacion(mdl_COM_PedidosComprasCabecera.id, int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PARTEPENDIENTE.Codigo));
                            }
                            //Si todos los registros estan como servido, se ponen como servido
                            else if (lst_Situacion_Filas.Where(m => !m.Equals(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_SERVIDO.Codigo))).Count() == 0)
                            {
                                obj_COM_PedidosComprasCabecera_Datos.Actualizar_Situacion(mdl_COM_PedidosComprasCabecera.id, int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_SERVIDO.Codigo));
                            }
                            //Si todos los registros estan como pendiente, se ponen como pendiente
                            else if (lst_Situacion_Filas.Where(m => !m.Equals(int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PENDIENTE.Codigo))).Count() == 0)
                            {
                                obj_COM_PedidosComprasCabecera_Datos.Actualizar_Situacion(mdl_COM_PedidosComprasCabecera.id, int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PENDIENTE.Codigo));
                            }
                            //Sino se pone como parte pendiente
                            else
                            {
                                obj_COM_PedidosComprasCabecera_Datos.Actualizar_Situacion(mdl_COM_PedidosComprasCabecera.id, int.Parse(Variables.G_MDL_TIPOSITUACION_PEDIDOCOMPRA_PARTEPENDIENTE.Codigo));
                            }
                        }
                    }
                }
            }
            catch (Control_Errores)
            {
                mdl_INTERNO_ValorDevuelto_Modelo.TodoCorrecto = false;
                mdl_INTERNO_ValorDevuelto_Modelo.Mensaje = Mensajes.G_STR_ERROR_GRABAR();
            }
            catch (Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(Recalcular_Situacion_PedidosCompra));
                mdl_INTERNO_ValorDevuelto_Modelo.TodoCorrecto = false;
                mdl_INTERNO_ValorDevuelto_Modelo.Mensaje = Mensajes.G_STR_ERROR_GRABAR();
            }

            return mdl_INTERNO_ValorDevuelto_Modelo;
        }
        #endregion

        #region FacturasCompra_AUX
        public static decimal[] FacturasCompraAUX_Calcular_Bruto(decimal _dcm_Base,decimal _dcm_Porcentaje_DescuentoFinalFactura, decimal _dcm_Porcentaje_DescuentoProntoPago)
        {
            decimal[] arr_ValoresFinales = new decimal[3];
            arr_ValoresFinales[0] = _dcm_Base;
            arr_ValoresFinales[1] = 0m;
            arr_ValoresFinales[2] = 0m;

            try
            {
                if (_dcm_Base!=0m)
                {
                    //1º Se calcula el Descuento ProntoPago si lo tuviera
                    if (_dcm_Porcentaje_DescuentoProntoPago != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_DescuentoProntoPago < 0m)
                        {
                            _dcm_Porcentaje_DescuentoProntoPago = _dcm_Porcentaje_DescuentoProntoPago * -1;
                        }

                        //valor Final
                        arr_ValoresFinales[0] = Funciones.RedondearDecimal(((arr_ValoresFinales[0] * 100) / (100- _dcm_Porcentaje_DescuentoProntoPago)), 2);
                        
                        //Descuento prontopago
                        arr_ValoresFinales[2] =  arr_ValoresFinales[0] - _dcm_Base;
                    }

                    //2º Se calcula el Descuento Final Factura si lo tuviera
                    if (_dcm_Porcentaje_DescuentoFinalFactura != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_DescuentoFinalFactura < 0m)
                        {
                            _dcm_Porcentaje_DescuentoFinalFactura = _dcm_Porcentaje_DescuentoFinalFactura * -1;
                        }

                        //valor Final //descuento Final factura
                        arr_ValoresFinales[0] = Funciones.RedondearDecimal(((arr_ValoresFinales[0] * 100) / (100- _dcm_Porcentaje_DescuentoFinalFactura)), 2);

                        //descuento Final factura
                        arr_ValoresFinales[1] += arr_ValoresFinales[0] - _dcm_Base;
                    }
                }
            }
            catch(Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(FacturasCompraAUX_Calcular_Bruto));
            }

            return arr_ValoresFinales;
        }

        public static decimal[] FacturasCompraAUX_Calcular_Base(decimal _dcm_Bruto, decimal _dcm_Porcentaje_DescuentoFinalFactura, decimal _dcm_Porcentaje_DescuentoProntoPago)
        {
            decimal[] arr_ValoresFinales = new decimal[3];
            arr_ValoresFinales[0] = _dcm_Bruto;
            arr_ValoresFinales[1] = 0m;
            arr_ValoresFinales[2] = 0m;

            try
            {
                if (_dcm_Bruto != 0m)
                {

                    //1º Se calcula el Descuento Final Factura si lo tuviera
                    if (_dcm_Porcentaje_DescuentoFinalFactura != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_DescuentoFinalFactura < 0m)
                        {
                            _dcm_Porcentaje_DescuentoFinalFactura = _dcm_Porcentaje_DescuentoFinalFactura * -1;
                        }

                        //Valor del Descuento Final factura
                        arr_ValoresFinales[1] = Funciones.RedondearDecimal(((arr_ValoresFinales[0] * _dcm_Porcentaje_DescuentoFinalFactura) / 100), 2);

                        //valor Final
                        arr_ValoresFinales[0] -= arr_ValoresFinales[1];
                    }

                    //2º Se calcula el Descuento ProntoPago si lo tuviera
                    if (_dcm_Porcentaje_DescuentoProntoPago != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_DescuentoProntoPago < 0m)
                        {
                            _dcm_Porcentaje_DescuentoProntoPago = _dcm_Porcentaje_DescuentoProntoPago * -1;
                        }

                        //Descuento pronto pago
                        arr_ValoresFinales[2] = Funciones.RedondearDecimal(((arr_ValoresFinales[0] * _dcm_Porcentaje_DescuentoProntoPago) / 100), 2);

                        //valor Final
                        arr_ValoresFinales[0] -= arr_ValoresFinales[2];
                    }
                }
            }
            catch (Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(FacturasCompraAUX_Calcular_Base));
            }

            return arr_ValoresFinales;
        }

        public static decimal FacturasCompraAUX_Calcular_Impuesto(decimal _dcm_Base, decimal _dcm_Porcentaje_Impuesto)
        {
            decimal dcm_ValorFinal = 0m;

            try
            {
                if (_dcm_Base != 0m)
                {

                    //1º Se calcula el impuesto si lo tuviera
                    if (_dcm_Porcentaje_Impuesto != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_Impuesto < 0m)
                        {
                            _dcm_Porcentaje_Impuesto = _dcm_Porcentaje_Impuesto * -1;
                        }

                        dcm_ValorFinal = Funciones.RedondearDecimal(((_dcm_Base * _dcm_Porcentaje_Impuesto) / 100), 2);
                    }
                }
            }
            catch (Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(FacturasCompraAUX_Calcular_Impuesto));
            }

            return dcm_ValorFinal;
        }

        public static decimal FacturasCompraAUX_Calcular_Recargo(decimal _dcm_Base, decimal _dcm_Porcentaje_Recargo)
        {
            decimal dcm_ValorFinal = 0m;

            try
            {
                if (_dcm_Base != 0m)
                {

                    //1º Se calcula el recargo si lo tuviera
                    if (_dcm_Porcentaje_Recargo != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_Recargo < 0m)
                        {
                            _dcm_Porcentaje_Recargo = _dcm_Porcentaje_Recargo * -1;
                        }

                        dcm_ValorFinal = Funciones.RedondearDecimal(((_dcm_Base * _dcm_Porcentaje_Recargo) / 100), 2);
                    }
                }
            }
            catch (Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(FacturasCompraAUX_Calcular_Recargo));
            }

            return dcm_ValorFinal;
        }


        public static decimal FacturasCompraAUX_Calcular_Retencion(decimal _dcm_Base_Retencion, decimal _dcm_Porcentaje_Retencion)
        {
            decimal dcm_ValorFinal = 0m;

            try
            {
                if (_dcm_Base_Retencion != 0m)
                {
                    //1º Se calcula la rentecion si la tuviera
                    if (_dcm_Porcentaje_Retencion != 0m)
                    {
                        //Si fuera negativo lo transformo a positivo
                        if (_dcm_Porcentaje_Retencion < 0m)
                        {
                            _dcm_Porcentaje_Retencion = _dcm_Porcentaje_Retencion * -1;
                        }

                        dcm_ValorFinal = Funciones.RedondearDecimal(((_dcm_Base_Retencion * _dcm_Porcentaje_Retencion) / 100), 2);
                    }
                }
            }
            catch (Exception ex)
            {
                Control_Errores.Errores_Log("", ex, nameof(Funciones_Compras) + "/" + nameof(FacturasCompraAUX_Calcular_Retencion));
            }

            return dcm_ValorFinal;
        }
        #endregion

    }
}
