using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using bdHerramientaCACOA.db;
using bdHerramientaCACOA.extensiones;
using Microsoft.AspNetCore.Http;
using Mysqlx.Crud;
using Org.BouncyCastle.Bcpg;
using static bdHerramientaCACOA.CASA;
using static bdHerramientaCACOA.LICITACIONES;

namespace bdHerramientaCACOA
{
    public class BAJA
    {
        public class VariablesBAJA
        {
            public double CostesVariables { get; set; } = 0.035;
            public int JornadaLaboral { get; set; } = 1800;
            public int HorasProduccionMedia { get; set; } = 80;
            public double IPCCosteIndirecto { get; set; } = 1;
        }
        public VariablesBAJA Variables { get; set; } = new VariablesBAJA();
        public double AnyoOferta { get; set; } = DateTime.Now.Year;
        double _ofertaEconomica = 0;
        public double OfertaEconomica { 
            get {
                return _ofertaEconomica;
            }
            set {
                _ofertaEconomica = value;
                CalcularBaja();
            }
        }
        double _tasaProduccion = 80;
        public double TasaProduccion {
            get
            {
                return _tasaProduccion;
            }
            set
            {
                _tasaProduccion = value;
                CalcularBaja();
            }
        }
        public List<ConvenioColectivoConcurso> ListaConvenioColectivo { get; set; } = new List<ConvenioColectivoConcurso>();
        public List<CosteDirectoIndirecto> ListaCDCI { get; set; } = new List<CosteDirectoIndirecto>();
        public string idProvincia { get; set; } = "";
        public int idGradSup { get; set; } = 0;
        public int idGradMed { get; set; } = 0;
        public int idDelin { get; set; } = 0;

        public List<DatosGrupoTrabajo> ListaDespachoProfesional { get; set; } = new List<DatosGrupoTrabajo>();
        public string Descripcion { get; set; } = "Baja "+DateTime.Now;
        public double TotalCostesPersonales { get; set; } = 0;
        public double HorasDespacho { get; set; } = 0;
        public double CosteDirectoHP { get; set; } = 0;
        public double CosteIndirecto { get; set; } = 0;
        public double CosteVariable { get; set; } = 0;
        public double TotalCosteHP { get; set; } = 0;
        public double TiempoEjecucionTrabProf { get; set; } = 0;
        public double SemanasProduccion { get; set; } = 0;

        public void Inicializar(bdHerramientaCACOA.dbcontext.tsHerramientasCACOA bd)
        {
            var grupoPuestoTrabajo = bd.gruposenumeraciones.FirstOrDefault(x => x.Grupo == "PUESTOTRABAJO");
            var puestos = bd.enumeraciones.Where(x => x.idGrupoEnumeracion == grupoPuestoTrabajo.idGrupoEnumeracion).ToList();
            var convColectivo = bd.conveniocolectivo.Where(x => x.idProvincia == "41").ToList();
            Variables.CostesVariables= (double)bd.enumeraciones.First(x => x.Codigo == "VARCASA.COSTESVARIABLES").ValorNumerico1;
            Variables.JornadaLaboral = (int)bd.enumeraciones.First(x => x.Codigo == "VARCASA.JORLABANUAL").ValorNumerico1;
            Variables.HorasProduccionMedia = (int)bd.enumeraciones.First(x => x.Codigo == "VARCASA.HORPRODMEDIA").ValorNumerico1;
            Variables.IPCCosteIndirecto = (double)bd.enumeraciones.First(x => x.Codigo == "VARCASA.IPCCD").ValorNumerico1;

            idGradSup = bd.enumeraciones.First(x => x.Codigo == "PUESTOTRABAJO.TECGRADSUP").idEnumeracion;
            idGradMed = bd.enumeraciones.First(x => x.Codigo == "PUESTOTRABAJO.GESTPROY").idEnumeracion;
            idDelin = bd.enumeraciones.First(x => x.Codigo == "PUESTOTRABAJO.DELINPROY").idEnumeracion;

            foreach (enumeraciones enu in puestos) {
                DatosGrupoTrabajo dgt = new DatosGrupoTrabajo();
                dgt.idGrupoTrabajo = enu.idEnumeracion;
                dgt.Descripcion = enu.ValorAlfabetico1;
                dgt.CosteAnualTrabajador = convColectivo.First(x => x.idEnumeracion == enu.idEnumeracion).CosteAnualTrabajador;
                dgt.HorasSemanales = 40;
                ListaDespachoProfesional.Add(dgt);
            }
            //ListaCostesDespacho=bd.costedespachoprofesional.ToList();
            var lisConvCol = bd.conveniocolectivo.ToList();
            ListaConvenioColectivo = ListaConvenioColectivoCASA(lisConvCol);
            ListaCDCI = CalcularTabla("");
        }
        public void ActualizarDatosGrupoTrabajo(DatosGrupoTrabajo dgt)
        {
            int indice = ListaDespachoProfesional.ToList().IndexOf(dgt);
            ListaDespachoProfesional[indice] = dgt;

            CalcularBaja();
        }
        public void CalcularBaja() {
            TotalCostesPersonales = CalcularCostesPersonales();
            HorasDespacho = CalcularHorasDespacho();
            CosteDirectoHP = CalcularCosteDirectoHP();
            CosteIndirecto = CalcularCostesIndirectos();
            CosteVariable = CalcularCostesVariables();
            TotalCosteHP = CalcularTotalCosteHP();
            TiempoEjecucionTrabProf = Math.Round(CalcularTiempoEjecTrabajo(),2,MidpointRounding.AwayFromZero);
            SemanasProduccion = Math.Round(CalcularSemanasProduccion(), 2, MidpointRounding.AwayFromZero);
        }

        private double CalcularCostesPersonales()
        {
            double suma = 0;
            foreach (DatosGrupoTrabajo dgt in ListaDespachoProfesional) {
                suma += dgt.NumTrabajadores * dgt.CosteAnualTrabajador * dgt.HorasSemanales / 40;
            }
            return suma.DosDecimales();
        }
        private double CalcularHorasDespacho()
        {
            double suma = 0;
            foreach (DatosGrupoTrabajo dgt in ListaDespachoProfesional)
            {
                if (dgt.NumTrabajadores > 0)
                {
                    suma += dgt.NumTrabajadores * dgt.HorasSemanales / 40;
                }
            }
            return (suma*Variables.JornadaLaboral).DosDecimales();
        }
        private double CalcularCosteDirectoHP()
        {
            if((HorasDespacho * TasaProduccion) == 0)
            {
                return 0;
            }
            return (TotalCostesPersonales / (HorasDespacho * (TasaProduccion/100))).DosDecimales();
        }
        private double CalcularCostesIndirectos()
        {
            var horasProducidas = HorasDespacho * (TasaProduccion/100);
            if (horasProducidas < 2880)
            {
                return 12.7;
            }
            return ObtenerCITabla(horasProducidas);
        }
        private double ObtenerCITabla(double horas) {
            double valor = 0;
            var a = ListaCDCI.OrderByDescending(x => x.NumeroTrabajadores);
            foreach (CosteDirectoIndirecto cdp in a)
            {
                if (horas <= cdp.HorasProduccionAnuales)
                {
                    valor = cdp.CostesIndirectos;
                }
            }
            return valor;
            //double valor = 0;
            //foreach (costedespachoprofesional cdp in ListaCostesDespacho) {
            //    //if (horas >= cdp.HorasProduccionAnuales) {
            //    if (horas <= cdp.HorasProduccionAnuales) {
            //        valor = cdp.CostesIndirectos;
            //    }
            //}
            //return valor;
        }

        private double CalcularCostesVariables()
        {
            return ((CosteDirectoHP+CosteIndirecto) * Variables.CostesVariables).DosDecimales();
        }

        private double CalcularTotalCosteHP()
        {
            return (CosteDirectoHP + CosteIndirecto + CosteVariable).DosDecimales();
        }

        private double CalcularTiempoEjecTrabajo()
        {
            return (OfertaEconomica / TotalCosteHP).DosDecimales();
        }

        private double CalcularSemanasProduccion()
        {
            double horasSemanales = CalcularHorasSemanales();
            if (horasSemanales == 0) return 0;

            return (TiempoEjecucionTrabProf / CalcularHorasSemanales()).DosDecimales();
        }
        private double CalcularHorasSemanales() {
            double suma = 0;
            foreach (DatosGrupoTrabajo dgt in ListaDespachoProfesional) {
                suma+= dgt.NumTrabajadores * dgt.HorasSemanales;
            }
            return (suma).DosDecimales();
        }


        public List<ConvenioColectivoConcurso> ListaConvenioColectivoCASA(List<conveniocolectivo> lista)
        {
            List<ConvenioColectivoConcurso> lcc = new List<ConvenioColectivoConcurso>();
            foreach (conveniocolectivo enu in lista)
            {
                lcc.Add(convenioColectivoACASA(enu));
            }
            return lcc;
        }
        public ConvenioColectivoConcurso convenioColectivoACASA(conveniocolectivo cc)
        {
            return new ConvenioColectivoConcurso()
            {
                idConvenioColectivo = cc.idConvenioColectivo,
                idEnumeracion = cc.idEnumeracion,
                idProvincia = cc.idProvincia,
                SalarioBase = cc.SalarioBase,
                OtrosCostes = cc.OtrosCostes,
                CosteAnualTrabajador = cc.CosteAnualTrabajador
            };
        }
        public List<CosteDirectoIndirecto> CalcularTabla(string idProvincia)
        {
            List<CosteDirectoIndirecto> listaCDCI = new List<CosteDirectoIndirecto>();
            //Obtenemos variables a utilizar
            if (idProvincia == "") { idProvincia = null; }

            double ValorTecSuperior = ListaConvenioColectivo.FirstOrDefault(x => x.idProvincia == idProvincia && x.idEnumeracion == idGradSup) != null ? ListaConvenioColectivo.First(x => x.idProvincia == idProvincia && x.idEnumeracion == idGradSup).CosteAnualTrabajador : 0;
            double ValorTecMedio = ListaConvenioColectivo.FirstOrDefault(x => x.idProvincia == idProvincia && x.idEnumeracion == idGradMed) != null ? ListaConvenioColectivo.First(x => x.idProvincia == idProvincia && x.idEnumeracion == idGradMed).CosteAnualTrabajador : 0;
            double ValorDelineante = ListaConvenioColectivo.FirstOrDefault(x => x.idProvincia == idProvincia && x.idEnumeracion == idDelin) != null ? ListaConvenioColectivo.First(x => x.idProvincia == idProvincia && x.idEnumeracion == idDelin).CosteAnualTrabajador : 0; ;

            double masCaro = Math.Max(ValorTecSuperior, Math.Max(ValorTecMedio, ValorDelineante));
            double masBarato = Math.Min(ValorTecSuperior, Math.Min(ValorTecMedio, ValorDelineante));

            //Se calcula 
            //listaCDCI.Add(new CosteDirectoIndirecto(1, 1 * ValorTecSuperior, 1 * ValorTecSuperior, jornadaLaboralAnual, horasProdMedia, porcentajeCostesVariables));
            for (int i = 2; i <= 20; i++)
            {
                double costeMinimo = ValorTecSuperior + (masBarato * (i - 1));
                double costeMaximo = ValorTecSuperior + (masCaro * (i - 1));
                CosteDirectoIndirecto cdci = new CosteDirectoIndirecto(i, costeMinimo, costeMaximo, Variables.JornadaLaboral, Variables.HorasProduccionMedia, Variables.CostesVariables, Variables.IPCCosteIndirecto);
                listaCDCI.Add(cdci);
            }
            return listaCDCI;
        }
    }
    public class DatosGrupoTrabajo {
        public int idGrupoTrabajo { get; set; } = 0;
        public string Descripcion { get; set; } = "";
        public double NumTrabajadores { get; set; } = 0;
        public double HorasSemanales { get; set; } = 0;

        public double CosteAnualTrabajador { get;set; } = 0;

    }
}