public IQueryable<ProductModel> GetByIdCategories(
           [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey, int id)
        {
            var context = new StoreContext();
            using (context)
            {
                var user = UsersController.GetUserBySessionKey(sessionKey);
                if (user == null)
                {
                    throw new ArgumentException("There is no user with such sessionKey!");
                }

                var newProductModel =
                    (from product in context.Products
                     where product.Category.CategoryId==id
                     select new ProductModel()
                     {
                         ProductId=product.ProductId,
                         ProductsName=product.ProductName
                     }).ToList();

                return newProductModel.AsQueryable();
            }

        }
        public ProductFullModel GetProductById(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey, int id)
        {
            var context = new StoreContext();
            using (context)
            {
                var user = UsersController.GetUserBySessionKey(sessionKey);
                if (user == null)
                {
                    throw new ArgumentException("There is no user with such sessionKey!");
                }

                var productById = context.Products.FirstOrDefault(p => p.ProductId == id);

                var newProductModel = new ProductFullModel()
                {
                    ProductId = productById.ProductId,
                    Price = productById.Price,
                    Category = productById.Category.CategoryName,
                    DateOfCreation = productById.DateOfCreation,
                    Description = productById.Description,
                    Manufacturer = productById.Manufacturer,
                    ProductName = productById.ProductName,
                    Quantity = productById.Quantity
                };

                return newProductModel;
            }
        }
        public HttpResponseMessage PostRegisterUser([FromBody]UserModel userModel)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
                () =>
                {
                    var context = new StoreContext();
                    using (context)
                    {
                        this.ValidateUsername(userModel.Username);
                        this.ValidateAuthCode(userModel.Password);
                        var usernameToLower = userModel.Username.ToLower();
                        var user = context.Users.FirstOrDefault(
                            usr => usr.Username.ToLower() == usernameToLower);

                        if (user != null)
                        {
                            throw new InvalidOperationException("User exists");
                        }

                        user = new User()
                        {
                            Username = usernameToLower,
                            Password = userModel.Password,
                            Email = userModel.Email,
                            Role = userModel.Role,
                            FirstName = userModel.FirstName,
                            LastName = userModel.LastName,
                        };

                        context.Users.Add(user);
                        context.SaveChanges();

                        user.SessionKey = this.GenerateSessionKey(user.UserId);
                        context.SaveChanges();

                        var loggedModel = new LoggedUserModel()
                        {
                            DisplayName = user.FirstName + " " + user.LastName,
                            SessionKey = user.SessionKey,
                            Role = user.Role
                        };

                        var response =
                            this.Request.CreateResponse(HttpStatusCode.Created,
                            loggedModel);

                        return response;
                    }
                });

            return responseMsg;
        }
        public HttpResponseMessage PostProductByAdmin(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey, ProductFullModel product)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
                () =>
                {
                    var context = new StoreContext();
                    using (context)
                    {
                        var user = UsersController.GetUserBySessionKey(sessionKey);
                        if (user == null)
                        {
                            throw new ArgumentException("There is no user with such sessionKey!");
                        }

                        if (!CheckUserIsAdmin(user.UserId))
                        {
                            throw new ArgumentException("You are not admin");
                        }

                        var cat = context.Categories.Where(c => c.CategoryName == product.Category).FirstOrDefault();
                        var newCategory = new Category();
                        if (cat == null)
                        {
                            newCategory.CategoryName = product.ProductName;
                        }

                        var newProduct =
                            new Product()
                            {
                                ProductId = product.ProductId,
                                Price = product.Price,
                                Category = newCategory,
                                DateOfCreation = product.DateOfCreation,
                                Description = product.Description,
                                Manufacturer = product.Manufacturer,
                                ProductName = product.ProductName,
                                Quantity = product.Quantity

                            };

                        context.Products.Add(newProduct);
                        context.SaveChanges();

                        var response =
                              this.Request.CreateResponse(HttpStatusCode.OK);

                        return response;
                    }
                });
            return responseMsg;
        }
        public IQueryable<CategoryModel> GetCategories(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var context = new StoreContext();
            using (context)
            {
                var user = UsersController.GetUserBySessionKey(sessionKey);
                if (user == null)
                {   
                    throw new ArgumentException("There is no user with such sessionKey!");
                }

                var newCategoryModel =
                    (from category in context.Categories
                     select new CategoryModel()
                     {
                         CategoryId=category.CategoryId,
                         CategoryName=category.CategoryName
                     }).ToList();

                return newCategoryModel.AsQueryable();
            }
             
        }
        public HttpResponseMessage PostLoginUser(UserModel userModel)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
              () =>
              {
                  var context = new StoreContext();
                  using (context)
                  {
                      this.ValidateUsername(userModel.Username);
                      this.ValidateAuthCode(userModel.Password);
                      var usernameToLower = userModel.Username.ToLower();
                      var user = context.Users.FirstOrDefault(
                          usr => usr.Username == usernameToLower
                          && usr.Password == userModel.Password);

                      if (user == null)
                      {
                          throw new InvalidOperationException("Invalid Username or password");
                      }
                      if (user.SessionKey == null)
                      {
                          user.SessionKey = this.GenerateSessionKey(user.UserId);
                          context.SaveChanges();
                      }

                      var loggedModel = new LoggedUserModel()
                      {
                          DisplayName = user.FirstName + " " + user.LastName,
                          SessionKey = user.SessionKey,
                          Role = user.Role
                      };

                      var response =
                          this.Request.CreateResponse(HttpStatusCode.Created,
                          loggedModel);

                      return response;
                  }
              });

            return responseMsg;
        }
        public static User GetUserBySessionKey(string sessionKey)
        {
            var context = new StoreContext();

            var user = context.Users.Where(usr => usr.SessionKey == sessionKey).FirstOrDefault();

            return user;
        }
        public IQueryable<UserModel> GetAllUsers(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var context = new StoreContext();
            using (context)
            {
                var user = UsersController.GetUserBySessionKey(sessionKey);
                if (user == null)
                {
                    throw new ArgumentException("There is no user with such sessionKey!");
                }
                if (user.Role != "admin")
                {
                    throw new ArgumentException("You are not admin!");
                }

                var productsModels =
                    (from p in user.Products
                     select new ProductModel()
                     {
                         ProductId = p.ProductId,
                         ProductsName = p.ProductName
                     }).AsQueryable();

                var newUserModel =
                    (from usr in context.Users
                     select new UserModel()
                     {
                         Username = usr.Username,
                         FirstName = usr.FirstName,
                         LastName = usr.LastName,
                         Email = usr.Email,
                         SessionKey = usr.SessionKey,
                         Password = usr.Password,
                         Role = usr.Role,
                         //Products = productsModels
                     }).ToList();

                return newUserModel.AsQueryable();
            }
        }
        public HttpResponseMessage PutLogoutUser(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
                () =>
                {
                    var context = new StoreContext();
                    using (context)
                    {
                        User user = UsersController.GetUserBySessionKey(sessionKey);

                        if (user == null)
                        {
                            throw new ArgumentException("There is no user with such sessionKey!");
                        }

                        context.Users.
                            FirstOrDefault(usr => usr.SessionKey == sessionKey).
                            SessionKey = null;
                        context.SaveChanges();

                        var response =
                          this.Request.CreateResponse(HttpStatusCode.OK);

                        return response;
                    }
                });

            return responseMsg;
        }
        private bool CheckUserIsAdmin(int id)
        {
            var context = new StoreContext();
            using (context)
            {
                var user = context.Users.FirstOrDefault(u => u.UserId == id && u.Role == "admin");

                if (user == null)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
        public HttpResponseMessage PutProduct(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey, int id)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
                () =>
                {
                    var context = new StoreContext();
                    using (context)
                    {
                        var user = context.Users.Where(usr => usr.SessionKey == sessionKey).FirstOrDefault();
                        if (user == null)
                        {
                            throw new ArgumentException("There is no user with such sessionKey!");
                        }

                        var productToUpdate = context.Products.FirstOrDefault(p => p.ProductId == id);

                        productToUpdate.Quantity--;

                        user.Products.Add(productToUpdate);

                        context.SaveChanges();

                        var productModel = new ProductFullModel()
                        {
                            ProductId = productToUpdate.ProductId,
                            ProductName = productToUpdate.ProductName,
                            Price = productToUpdate.Price,
                            Category = productToUpdate.Category.CategoryName,
                            DateOfCreation = productToUpdate.DateOfCreation,
                            Description = productToUpdate.Description,
                            Manufacturer = productToUpdate.Manufacturer,
                            Quantity = productToUpdate.Quantity
                        };

                        var response =
                              this.Request.CreateResponse(HttpStatusCode.OK, productModel);

                        return response;
                    }
                });
            return responseMsg;
        }
        public HttpResponseMessage DeleteProductByAdmin(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey, int id)
        {

            var responseMsg = this.PerformOperationAndHandleExceptions(
            () =>
            {
                var context = new StoreContext();
                using (context)
                {
                    var product = context.Products.FirstOrDefault(p => p.ProductId == id);
                    if (product == null)
                    {
                        throw new ArgumentNullException("No product found");
                    }

                    context.Products.Remove(product);
                    context.SaveChanges();

                    var response =
                      this.Request.CreateResponse(HttpStatusCode.OK);

                    return response;
                }
            });
            return responseMsg;
        }