public HttpResponseMessage DeleteBook(string key)
        {
            try
            {
                var context = new LibrarySystemContext();
                using(context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == key);
                    if(book==null)
                    {
                        throw new ArgumentException("Няма книга с такъв уникален номер!");
                    }
                    context.Books.Remove(book);
                    context.SaveChanges();
                }

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            }
            catch(Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetUserByUniqueNumber(int uniqueNumber)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(u => u.UniqueNumber == uniqueNumber);
                    if(user==null)
                    {
                        throw new Exception("Няма такъв потребител!");
                    }

                    var booksToReturn =
                        context.UsersBooks.Where(ub => ub.User.UniqueNumber == uniqueNumber && ub.IsReturned == false);

                    var userInfo = new DetailedUserModel()
                                       {
                                           Id = user.Id,
                                           UniqueNumber = user.UniqueNumber,
                                           Name = user.Name,

                                       };
                    userInfo.BooksToReturn=new Collection<BookToReturnModel>();
                    foreach (var book in booksToReturn)
                    {
                        userInfo.BooksToReturn.Add(new BookToReturnModel()
                                                       {
                                                           Key = book.Book.Key,
                                                           Title = book.Book.Title,
                                                           AuthorName = book.Book.Author.Name,
                                                           DateToreturn = book.DateToReturn,
                                                           Year = book.Book.Year,
                                                           Description = book.Book.Description
                                                       });
                    }

                    var response = this.Request.CreateResponse(HttpStatusCode.OK, userInfo);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage AddNote(NoteModel model)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == model.BookKey);
                    var user = context.Users.FirstOrDefault(u => u.UniqueNumber == model.UserUniqueNumber);
                    if (book == null)
                    {
                        throw new ArgumentException("Няма такава книга!");
                    }
                    if (user == null)
                    {
                        throw new ArgumentException("Няма такъв потребител!");
                    }

                    book.Notes.Add(new Note()
                                       {
                                           User = user,
                                           Text = model.Text
                                       });

                    context.SaveChanges();

                    var response = this.Request.CreateResponse(HttpStatusCode.OK);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PostCreateUser(UserModel model)
        {
            try
            {
                var dbContext = new LibrarySystemContext();
                using (dbContext)
                {
                    ValidateName(model.Name);
                    var user = new User()
                                   {
                                       Name = model.Name,
                                       AuthCode = model.AuthCode
                                   };

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

                    user.SessionKey = this.GenerateSessionKey(user.Id);
                    user.UniqueNumber = user.Id + 1000;
                    dbContext.SaveChanges();

                    var loggedModel = new LoggedUserModel()
                    {
                        UniqueNumber = user.UniqueNumber,
                        SessionKey = user.SessionKey
                    };

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

            }
            catch(Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                              ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PutLogoutUser(string sessionKey)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
                    if (user == null)
                    {
                        throw new ArgumentException("Невалидна сесия.");
                    }

                    user.SessionKey = null;
                    context.SaveChanges();

                    var response = this.Request.CreateResponse(HttpStatusCode.OK);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PostLoginUser(UserModel model)
        {
            try
            {
                ValidateAuthCode(model.AuthCode);

                var context = new LibrarySystemContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(u => u.UniqueNumber == model.UniqueNumber
                        && u.AuthCode == model.AuthCode);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Грешна парола или потребителски номер");
                    }
                    if (user.SessionKey == null)
                    {
                        user.SessionKey = this.GenerateSessionKey(user.Id);
                        context.SaveChanges();
                    }

                    var loggedModel = new LoggedUserModel()
                    {
                        UniqueNumber = user.UniqueNumber,
                        SessionKey = user.SessionKey,
                        Name = user.Name
                    };

                    var response = this.Request.CreateResponse(HttpStatusCode.Created,
                                        loggedModel);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                         ex.Message);
                return response;
            }
        }
        public HttpResponseMessage SearchForBook(string query, SearchBy searchBy=SearchBy.All)
        {
            try
            {
                var context = new LibrarySystemContext();

                if (query == null || query == "")
                {
                    throw new ArgumentException("Невалидно търсене!");
                }

                IQueryable<Book> booksEntity;
                if (searchBy == SearchBy.Key)
                {
                    booksEntity = context.Books.Where(b => b.Key.Contains(query));
                }
                else if (searchBy == SearchBy.Author)
                {
                    booksEntity = context.Books.Where(b => b.Author.Name.Contains(query));
                }
                else if (searchBy == SearchBy.Title)
                {
                    booksEntity = context.Books.Where(b => b.Title.Contains(query));
                }
                else
                {
                    booksEntity = context.Books.Where(b => b.Key.Contains(query) || b.Author.Name.Contains(query)
                                                           || b.Title.Contains(query));
                }

                var books = from book in booksEntity
                            select new BookModel()
                                       {
                                           Title = book.Title,
                                           AuthorName = book.Author.Name,
                                           Description = book.Description,
                                           Key = book.Key,
                                           Year = book.Year
                                       };

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

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                           ex.Message);
                return response;
            }
        }
        public HttpResponseMessage ReturnBook(string bookCode, int userNumber)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == bookCode);
                    var user = context.Users.FirstOrDefault(u => u.UniqueNumber == userNumber);
                    if (book == null)
                    {
                        throw new ArgumentException("Няма такава книга!");
                    }
                    if (user == null)
                    {
                        throw new ArgumentException("Няма такъв потребител!");
                    }

                    var userBook=context.UsersBooks.FirstOrDefault(ub => ub.Book.Key == book.Key &&
                        ub.User.UniqueNumber == user.UniqueNumber);
                    if (userBook != null && userBook.IsReturned==false)
                    {
                        userBook.IsReturned = true;
                        context.SaveChanges();
                    }
                    else
                    {
                        throw new Exception("Тази книга не е взета от този потребител!");
                    }

                    var response = this.Request.CreateResponse(HttpStatusCode.OK);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage ModifyBook(BookModel model, string key)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == key);
                    if (book == null)
                    {
                        throw new ArgumentException("Няма книга с такъв уникален номер!");
                    }

                    var author = context.Authors.FirstOrDefault(a => a.Name == model.AuthorName);
                    if (author == null)
                    {
                        context.Authors.Add(new Author()
                        {
                            Name = model.AuthorName
                        });
                        context.SaveChanges();
                    }

                    book.Title = model.Title;
                    book.Key = model.Key;
                    book.Author = author;
                    book.Year = model.Year;
                    book.Description = model.Description;

                    context.SaveChanges();
                }

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.NotModified,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage ImportBooks(ICollection<BookModel> books)
        {
            try
            {
                int errors = 0;
                var context = new LibrarySystemContext();
                using(context)
                {
                    foreach (var book in books)
                    {
                        var author = context.Authors.FirstOrDefault(a => a.Name == book.AuthorName);
                        if(author==null)
                        {
                            author=context.Authors.Add(new Author()
                                                    {
                                                        Name = book.AuthorName
                                                    });
                            context.SaveChanges();
                        }

                        var existBook = context.Books.FirstOrDefault(b => b.Key == book.Key);
                        if(existBook==null)
                        {
                            context.Books.Add(new Book()
                                                  {
                                                      Title = book.Title,
                                                      Author = author,
                                                      Key = book.Key,
                                                      Year = book.Year,
                                                      Description = book.Description
                                                  });
                        }
                        else
                        {
                            errors++;
                        }

                    }
                    context.SaveChanges();

                }
                if (errors > 0)
                {
                    throw new Exception("Има книга със същото заглавие и тя НЕ е заменена!");
                }
                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetLBooksThatMustBeReturned()
        {
            try
            {
                var context = new LibrarySystemContext();

                var booksEntity = context.UsersBooks.Where(ub => ub.DateToReturn < DateTime.Now);

                var books = from book in booksEntity
                            select new BookToReturnModel()
                                       {
                                           Title = book.Book.Title,
                                           AuthorName = book.Book.Author.Name,
                                           Description = book.Book.Description,
                                           Key = book.Book.Key,
                                           Year = book.Book.Year,
                                           UserUniqueNumber = book.User.UniqueNumber,
                                           UserName = book.User.Name,
                                           DateToreturn = book.DateToReturn
                                       };

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

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                                           ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetLast20Books(int start)
        {
            try
            {
                var context = new LibrarySystemContext();

                var booksEntity = context.Books.OrderByDescending(b => b.Id).Skip(start).Take(20);

                    var books = from book in booksEntity
                                select new BookModel()
                                           {
                                               Title = book.Title,
                                               AuthorName = book.Author.Name,
                                               Description = book.Description,
                                               Key = book.Key,
                                               Year = book.Year,
                                           };

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

            }
            catch(Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetGotBooksFromUser(int uniqueNumber)
        {
            try
            {
                var context = new LibrarySystemContext();

                    var booksEntity = context.UsersBooks.Where(ub => ub.User.UniqueNumber == uniqueNumber)
                        .OrderByDescending(ub=>ub.DateToReturn);

                    var books = from book in booksEntity
                                select new BookToReturnModel()
                                           {
                                               Title = book.Book.Title,
                                               AuthorName = book.Book.Author.Name,
                                               Description = book.Book.Description,
                                               Key = book.Book.Key,
                                               Year = book.Book.Year,
                                               DateToreturn = book.DateToReturn
                                           };

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

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetBookDetailed(string bookKey)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == bookKey);

                    var theBook = new BookDetailsModel()
                                      {
                                          Title = book.Title,
                                          AuthorName = book.Author.Name,
                                          Description = book.Description,
                                          Key = book.Key,
                                          Year = book.Year,
                                      };

                    foreach (var note in book.Notes)
                    {
                        theBook.Notes.Add(new NoteModel()
                                              {
                                                  Text = note.Text
                                              });
                    }

                    var response = this.Request.CreateResponse(HttpStatusCode.OK, theBook);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetBook(string bookCode, int userNumber)
        {
            try
            {
                var context = new LibrarySystemContext();
                using (context)
                {
                    var book = context.Books.FirstOrDefault(b => b.Key == bookCode);
                    var user = context.Users.FirstOrDefault(u => u.UniqueNumber == userNumber);
                    if(book==null)
                    {
                        throw new ArgumentException("Няма такава книга!");
                    }
                    if(user==null)
                    {
                        throw new ArgumentException("Няма такъв потребител!");
                    }

                    var userBook = context.UsersBooks.FirstOrDefault(ub => ub.Book.Key == book.Key
                        && ub.User.UniqueNumber == user.UniqueNumber);
                    if (userBook == null)
                    {
                        context.UsersBooks.Add(new UserBook()
                                                   {
                                                       Book = book,
                                                       User = user,
                                                       IsReturned = false,
                                                       DateToReturn = DateTime.Now.AddDays(30)
                                                   });
                    }
                    else if(userBook.IsReturned==true)
                    {
                        userBook.IsReturned = false;
                        userBook.DateToReturn = DateTime.Now.AddDays(30);
                    }
                    else
                    {
                        throw new Exception("Тази книга вече е взета!");
                    }
                    context.SaveChanges();

                    var response = this.Request.CreateResponse(HttpStatusCode.OK);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                          ex.Message);
                return response;
            }
        }