using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using compabetov2.database;
using compabetov2.database.modelos;

namespace compabetov2.database
{
    internal class service
    {
        public static bool iniciarSesion(Usuario usuario)
        {
            return DAO.iniciarSesionDAO(usuario.nombreUsuario, usuario.contra);
        }
        public static LoginModel conseguirInicioSesion(string usuario)
        {
            SQLiteDataReader reader = DAO.conseguirInicioSesionDAO(usuario);

            while (reader.Read())
            {
                return new LoginModel(
                    reader["usuario"].ToString(),
                    "",
                    reader["tipo"].ToString()
                    );
            }

            return null;
        }
        public static bool crearLogin(LoginModel loginModel, int idEmpleado)
        {
            return DAO.crearLoginDAO(loginModel, idEmpleado);
        }

        public static List<Producto> conseguirProductos()
        {
            List<Producto> productos = new List<Producto>();

            SQLiteDataReader reader = DAO.conseguirProductosDAO();

            while (reader.Read())
            {
                Categoria categoria = new Categoria();

                Producto producto = new Producto(
                    int.Parse(reader["idproducto"].ToString()),
                    reader["nombre"].ToString(), 
                    reader["descripcion"].ToString(),
                    decimal.Parse(reader["precio"].ToString()),
                    reader["img"].ToString(),
                    int.Parse(reader["stock"].ToString()),
                    categoria);

                productos.Add(producto);
            }

            return productos;
        }

        public static bool insertarProducto(Producto producto)
        {
            return DAO.insertarProductoDAO(producto);
        }
        
        public static bool insertarCliente(Cliente cliente)
        {
            return DAO.insertarClienteDAO(cliente);
        }

        public static bool eliminarCliente(Cliente cliente)
        {
            return DAO.eliminarClienteDAO(cliente);
        }

        public static List<Cliente> conseguirCliente()
        {
            List<Cliente> clientes = new List<Cliente>();

            SQLiteDataReader reader = DAO.conseguirClientesDAO();

            while (reader.Read())
            {
                Cliente cliente = new Cliente(
                    (int)reader["idCliente"],
                    reader["nombres"].ToString(),
                    reader["apellidos"].ToString(),
                    reader["calle"].ToString(),
                    reader["colonia"].ToString(),
                    reader["cp"].ToString(),
                    reader["no_ext"].ToString(),
                    reader["no_int"].ToString(),
                    reader["referencia"].ToString(),
                    reader["telefono"].ToString(),
                    reader["telefono_extra"].ToString()
                    );
                clientes.Add(cliente);
            }
            return clientes;
        }

        public static bool insertarEmpleado(Empleado empleado)
        {
            return DAO.insertarEmpleadoDAO(empleado);
        }

        public static List<Empleado> conseguirEmpleados()
        {
            List<Empleado> empleados = new List<Empleado>();

            using (SQLiteDataReader reader = DAO.conseguirEmpleadosDAO()) {
                

                while (reader.Read())
                {
                    long fkIdLoginTemp = reader.GetInt64(14);
                    int fkIdLogin = Convert.ToInt32(fkIdLoginTemp);

                    long id = reader.GetInt64(0);
                    Empleado empleado = new Empleado(
                        Convert.ToInt32(id),
                        reader["nombre"].ToString(),
                        reader["apellidos"].ToString(),
                        reader["calle"].ToString(),
                        reader["fecha_contratacion"].ToString(),
                        reader["estado"].ToString(),
                        reader["colonia"].ToString(),
                        reader["cp"].ToString(),
                        reader["no_ext"].ToString(),
                        reader["no_int"].ToString(),
                        reader["referencia"].ToString(),
                        reader["fecha_nac"].ToString(),
                        reader["telefono"].ToString(),
                        reader["img"].ToString(),
                        fkIdLogin
                        ) ;
                    empleados.Add(empleado);
                }
                return empleados;

            } 
        }

        public static bool aumentarStock(List<Producto> stockNuevo)
        {
            return DAO.aumentarStockDAO(stockNuevo);
        }

        public static bool eliminarEmpleado(Empleado empleado)
        {
            return DAO.eliminarEmpleadoDAO(empleado);
        }

        public static bool actualizarEmpleado(Empleado empleado)
        {
            return DAO.actualizarEmpleadoDAO(empleado);
        }

        public static bool verificarExistenciaLogin(LoginModel loginModel)
        {
            return DAO.verificarExistenciaLoginDAO(loginModel);
        }

        public static bool eliminarLogin(Empleado empleado)
        {
            return DAO.eliminarLoginDAO(empleado);
        }

        public static bool modificarContra(Empleado empleado, string contra)
        {
            return DAO.modificarContraDAO(empleado, contra);
        }

        public static List<Merma> conseguirMerma()
        {
            List<Merma> mermas = new List<Merma>();
            SQLiteDataReader reader = DAO.conseguirMermaDAO();

            while (reader.Read())
            {
                Merma merma = new Merma(
                    reader.GetInt64(0),
                    reader.GetString(1),
                    reader.GetString(2),
                    reader.GetString(3)
                    );
                mermas.Add(merma);
            }

            return mermas;
        }

        public static bool crearVentaDAO(VentaModel venta, List<DetalleVentaModel> detalleVentas, List<DetalleImporte> importes)
        {
            return DAO.crearVentaDAO(venta, detalleVentas,importes);
        }

        public static bool devolverImporte(List<DetalleImporte> importes)
        {
            return DAO.devolverImporteDAO(importes);
        }

        public static bool insertarMerma(Merma merma)
        {
            return DAO.insertarMermaDAO(merma);
        }

        public static bool eliminarMerma(Merma merma)
        {
            return DAO.eliminarMermaDAO(merma);
        }

        public static bool actualizarMerma(Merma merma)
        {
            return DAO.actualizarMermaDAO(merma);
        }

        public static bool crearCuenta(Cuenta cuenta, List<DetalleCuentaModel> detalleCuentas, List<DetalleImporte> importes)
        {
            return DAO.crearCuentaDAO(cuenta, detalleCuentas, importes);
        }

        public static List<Cuenta> conseguirCuentaDAO()
        {
            List<Cuenta> cuentas = new List<Cuenta>();
            SQLiteDataReader reader = DAO.conseguirCuentaDAO();

            while(reader.Read())
            {
                long idCuenta = reader.GetInt64(0);
                long total = reader.GetInt64(1);
                string fecha = reader["fecha"].ToString();
                string estado = reader["estado"].ToString();
                string descripcion = reader["descripcion"].ToString();
                string cliente = reader["cliente"].ToString();

                Cuenta cuenta = new Cuenta(
                    (int) total,
                    fecha,
                    estado,
                    descripcion,
                    cliente,
                    (int)idCuenta
                    );
                cuentas.Add(cuenta);
            }
            return cuentas;
        }

        public static List<DetalleCuentaModel> conseguirDetalleCuante(int idCuenta)
        {
            List<DetalleCuentaModel> detallesCuentas = new List<DetalleCuentaModel>();

            SQLiteDataReader reader = DAO.conseguirDetalleCuanteDAO(idCuenta);

            while (reader.Read())
            {
                int idVariaante = (int)reader.GetInt64(0);
                decimal precioCompra = reader.GetOrdinal("precioCompra");
                DetalleCuentaModel detalleCuenta = new DetalleCuentaModel(
                    new Variante(idVariaante, reader["nombre"].ToString(),0,(int)reader.GetInt64(2),"",(int)reader.GetInt64(3), precioCompra),
                    (int)reader.GetInt64(4)
                    );
                detallesCuentas.Add(detalleCuenta);
            }

            return detallesCuentas;
        }

        public static List<DetalleImporteCuenta> conseguirImportesCuenta(int idCuenta)
        {
            List<DetalleImporteCuenta> importes = new List<DetalleImporteCuenta>();

            SQLiteDataReader reader = DAO.conseguirImportesCuentaDAO(idCuenta);

            while (reader.Read())
            {
                int idImporte = (int)reader.GetInt64(1);
                DetalleImporteCuenta importe = new DetalleImporteCuenta(
                    idImporte,
                    (int)reader.GetInt64(2),//cantidad
                    (int)reader.GetDecimal(3),// precio
                    (int)reader.GetInt64(4)//fk_cuenta                                   
                    );
                importes.Add(importe);
            }

            return importes;
        }

        public static bool cancelarCuenta(int idCuenta)
        {
            return DAO.cancelarCuentaDAO(idCuenta);
        }

        public static bool saldarCuenta(Cuenta cuenta, List<DetalleCuentaModel> detallesCuentas, List<DetalleImporteCuenta> importes)
        {
            return DAO.saldarCuentaDAO(cuenta, detallesCuentas, importes);
        }

        /*public static Dictionary<string, dynamic> filtrarVentaFechaMes(DateTime fecha)
        {
            Dictionary<string, dynamic> estadisticas = new Dictionary<string, dynamic>();
            SQLiteDataReader reader = DAO.filtrarVentaFechaMesDAO(fecha);
            string formatoFecha = "dd/MM/yyyy h:mm:ss tt";
            decimal totalDia = 0;
            decimal totalMes = 0;
            List<VentaModel> ventas = new List<VentaModel>();
            while (reader.Read())
            {
                VentaModel venta = new VentaModel(
                    reader.GetDecimal(2),
                    (int)reader.GetInt64(0),
                    reader.GetString(1)
                    );
                DateTime fechaVenta = DateTime.ParseExact(venta.fecha, formatoFecha, CultureInfo.InvariantCulture);
                if (fecha.Day == fechaVenta.Day)
                {
                    totalDia += venta.total;
                }
                totalMes += venta.total;
                ventas.Add(venta);
            }

            estadisticas.Add("ventasDia", totalDia);
            estadisticas.Add("ventasMes", totalMes);
            MessageBox.Show($"{totalDia} -- {totalMes}");

            return estadisticas;
        }*/

        public static bool crearEnvio(Envio envio, List<DetalleEnvioModel> detallesEnvio, List<DetalleImporte> importes)
        {
            return DAO.crearEnvio(envio, detallesEnvio,importes);
        }

        public static List<Dictionary<string, dynamic>> conseguirEnvio()
        {
            List<Dictionary<string, dynamic>> envios = new List<Dictionary<string, dynamic>>();
            SQLiteDataReader reader = DAO.conseguirEnvioDAO();

            while (reader.Read())
            {
                Dictionary<string,dynamic> dict = new Dictionary<string,dynamic>();
                decimal total = reader.GetDecimal(6);
                Envio envio = new Envio(
                    (int)reader.GetInt64(0),
                    reader.GetString(1),
                    reader.GetString(2),
                    reader.GetString(3),
                    reader.GetString(4),
                    reader.GetString(5),
                    reader.GetString(7),
                    total
                    ) ;

                dict.Add("envio", envio);

                List<DetalleImporteEnvio> importes = new List<DetalleImporteEnvio>();
                SQLiteDataReader readerImporte = DAO.conseguirImporteEnvio(envio.id);
                while (readerImporte.Read())
                {
                    decimal precio = readerImporte.GetDecimal(3);
                    importes.Add(new DetalleImporteEnvio(
                        (int)readerImporte.GetInt64(1),//id
                        (int)readerImporte.GetInt64(2),//cantidad
                        precio,//precio
                        (int)readerImporte.GetInt64(4)//fk_envio
                        ));
                }

                dict.Add("importes",importes);
                envios.Add(dict);
            }

            return envios;
        }

        public static List<DetalleEnvioModel> conseguirDetalleEnvio(int idEnvio)
        {
            List<DetalleEnvioModel> detallesEnvio = new List<DetalleEnvioModel>();

            SQLiteDataReader reader = DAO.conseguirDetalleEnvioDAO(idEnvio);

            while (reader.Read())
            {
                int idVariante = (int)reader.GetInt64(0);
                decimal precioCompra = reader.GetOrdinal("precioCompra");
                DetalleEnvioModel detalleEnvio = new DetalleEnvioModel(
                    idEnvio,
                    new Variante(idVariante, reader["nombre"].ToString(),0,(int)reader.GetInt64(2),"", (int)reader.GetInt64(3), precioCompra),//fkproducto
                    (int)reader.GetInt64(4)//cantidad
                    );
                detallesEnvio.Add(detalleEnvio);
            }

            return detallesEnvio;
        }

        public static bool editarEnvio(Envio envio)
        {
            return DAO.editarEnvioDAO(envio);
        }


        public static bool cancelarEnvio(Envio envio, List<DetalleEnvioModel> detalles)
        {
            return DAO.cancelarEnvioDAO(envio, detalles);
        }

        public static bool concluirEnvio(Envio envio, List<DetalleEnvioModel> detallesEnvio, List<DetalleImporteEnvio> importes)
        {
            return DAO.concluirEnvioDAO(envio, detallesEnvio, importes);
        }

        public static Dictionary<string, List<Dictionary<string,dynamic>>> estadisticas(DateTime fecha)
        {
            Dictionary<string, List<Dictionary<string, dynamic>>> resumen = new Dictionary<string, List<Dictionary<string, dynamic>>>();
            List<Dictionary<string, dynamic>> listMes = new List<Dictionary<string, dynamic>>();
            List<Dictionary<string, dynamic>> listDia = new List<Dictionary<string, dynamic>>();
            SQLiteDataReader readerVentas = DAO.conseguirVentasMesDAO(fecha);
            string formato = "dd/MM/yyyy";

            while (readerVentas.Read())
            {
                Dictionary<string,dynamic> dicVenta = new Dictionary<string,dynamic>();

                VentaModel venta = new VentaModel(
                    readerVentas.GetDecimal(2),
                    (int)readerVentas.GetInt64(0),
                    readerVentas.GetString(1),
                    readerVentas.GetString(3)
                    );

                List<DetalleVentaModel> detallesVenta = new List<DetalleVentaModel>();
                SQLiteDataReader readerDetalleVenta = DAO.conseguirDetalleVenta(venta);
                while (readerDetalleVenta.Read())
                {
                    decimal precioCompra = readerDetalleVenta.GetOrdinal("precioCompra");
                    DetalleVentaModel detalleVenta = new DetalleVentaModel(
                        (int)readerDetalleVenta.GetInt64(2),
                        new Variante((int)readerDetalleVenta.GetInt64(3), 
                        readerDetalleVenta["nombre"].ToString(), 
                        readerDetalleVenta.GetDecimal(5),
                        (int)readerDetalleVenta.GetInt64(6),
                        "",
                        (int)readerDetalleVenta.GetInt64(8),
                        precioCompra)  
                    );
                    detallesVenta.Add( detalleVenta );
                }

                dicVenta.Add("venta", venta);
                dicVenta.Add("detalles", detallesVenta as List<DetalleVentaModel>);

                string[] fecha_hora = venta.fecha.Split(' ');
                string fechaVentaStr = fecha_hora[0];

                DateTime.TryParseExact(fechaVentaStr, formato, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime fechaVenta);
                if (fecha.Day == fechaVenta.Day)
                {
                    listDia.Add(dicVenta);
                }

                listMes.Add(dicVenta);
            }



            resumen.Add("mes", listMes);
            resumen.Add("dia", listDia);

            return resumen;
        }

        public static List<Variante> conseguirProductosFiltrados(string nombreProducto)
        {
            List<Variante> productos = new List<Variante>();
            SQLiteDataReader reader = DAO.conseguirProductosFiltradosDAO(nombreProducto);

            int idIndex = reader.GetOrdinal("idVariante");
            int nombreIndex = reader.GetOrdinal("nombre");
            int precioIndex = reader.GetOrdinal("precio");
            int cantidadIndex = reader.GetOrdinal("cantidad");
            int imgIndex = reader.GetOrdinal("img");
            int fkProductoIndex = reader.GetOrdinal("fk_producto");
            decimal precioCompra = reader.GetOrdinal("precioCompra");

            while (reader.Read())
            {
                
                Variante producto = new Variante(
                    reader.GetInt32(idIndex),
                    reader.GetString(nombreIndex),
                    reader.GetDecimal(precioIndex),
                    reader.GetInt32(cantidadIndex),
                    reader.GetString(imgIndex),
                    reader.GetInt32(fkProductoIndex),
                    precioCompra
                );

                productos.Add(producto);
            }
            
            return productos;
        }


        public static Dictionary<string, List<Envio>> conseguirEnvioMes(DateTime fecha)
        {
            Dictionary<string, List<Envio>> dic = new Dictionary<string, List<Envio>>();
            string formato = "dd/MM/yyyy";
            List<Envio> enviosDia = new List<Envio>();
            List<Envio> enviosMes = new List<Envio>();

            SQLiteDataReader reader = DAO.conseguirEnvioMesDAO(fecha);

            while (reader.Read()) {
                Envio envio = new Envio((int)reader.GetInt64(0),reader.GetString(1),"","", "","","",0);

                string[] fecha_hora = envio.fecha.Split(' ');
                string fechaVentaStr = fecha_hora[0];
                DateTime.TryParseExact(fechaVentaStr, formato, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime fechaVenta);
                if (fecha.Day == fechaVenta.Day)
                {
                    enviosDia.Add(envio);
                }
                enviosMes.Add(envio);
            }

            dic.Add("mes", enviosMes);
            dic.Add("dia", enviosDia);

            return dic;
        }

        public static List<Variante> conseguirVariantes()
        {
            List<Variante> variantes = new List<Variante>();
            SQLiteDataReader reader = DAO.conseguirVariantesDAO();

            while (reader.Read())
            {
                decimal precio = reader.GetDecimal(2);
                decimal precioCompra = reader.GetDecimal(6);
                int cantidad = (int)reader.GetInt64(3);
                int fkProducto = (int)reader.GetInt64(5);
                Variante vaiante = new Variante(
                    (int)reader.GetInt64(0),
                    reader["nombre"].ToString(),
                    precio,
                    cantidad,
                    reader["img"].ToString(),
                    fkProducto,
                    precioCompra
                    );
                variantes.Add(vaiante);
            }

            return variantes;
        }

        public static List<ImporteModel> conseguirImportes()
        {
            List<ImporteModel> importes = new List<ImporteModel>();
            SQLiteDataReader reader = DAO.conseguirImportesDAO();

            while (reader.Read())
            {
                ImporteModel importe = new ImporteModel(
                        (int)reader.GetInt64(0), //id
                        reader.GetString(1), //tipo
                        reader.GetDecimal(2), //precion
                        reader.GetString(3) //imagen
                    );
                importes.Add(importe);
            }
            return importes;
        }
    }
}
