/// <summary>
        /// Edits the <see cref="OperatingLocation"/> using <see cref="EditOperatingLocationServiceModel"/>.
        /// </summary>
        /// <param name="model">Number of modified entities.</param>
        /// <returns>Service model with <c>Id</c>, <c>Town</c>, <c>Address</c>, <c>Description</c>, <c>ImageUrl</c> and <c>DepartmentsIds</c> with associated <c>PhoneIds</c>.</returns>
        public async Task <int> EditAsync(EditOperatingLocationServiceModel model)
        {
            int modifiedEntities = 0;

            OperatingLocation operatingLocation = this.dbContext.OperatingLocations.Find(model.Id);

            operatingLocation.Town        = model.Town;
            operatingLocation.Address     = model.Address;
            operatingLocation.Description = model.Description;
            operatingLocation.ImageUrl    = model.ImageUrl;

            // Clear the operatingLocation departments
            operatingLocation.Departments.Clear();

            // First set each Department's OperatingLocationId with this OperatingLocation to null and make corresponding phones internal
            var deps = this.dbContext.Departments.Where(x => x.OperatingLocationId == operatingLocation.Id).ToList();

            for (int i = 0; i < deps.Count; i++)
            {
                deps[i].OperatingLocationId = null;
                foreach (var phone in deps[i].Phones)
                {
                    bool result = this.phonesService.IsPhoneContainedInOtherDepartments(phone.Phone.PhoneNumber);

                    // Only if the Phone is not contained within other Departments and is Public -> Set Phone to Internal
                    // Just in One Department and is Public -> set Phone to Internal
                    if (result == false && phone.Phone.IsInternal == false)
                    {
                        this.dbContext.Phones.FirstOrDefault(x => x.Id == phone.PhoneId).IsInternal = true;
                    }
                    // In Many Departments and is Internal -> set Phone to Public
                    else if (result == true && phone.Phone.IsInternal == false)
                    {
                        this.dbContext.Phones.FirstOrDefault(x => x.Id == phone.PhoneId).IsInternal = true;
                    }
                }
            }

            modifiedEntities += await this.dbContext.SaveChangesAsync();

            var departments = this.departmentsService.GetAllDepartmentsWithSelectedPhones(model.DepartmentIds);

            foreach (var departmentFromModel in departments)
            {
                // Set Department's OperatingLocationId, because it is null
                Department department = this.dbContext.Departments.FirstOrDefault(x => x.Id == departmentFromModel.Id);
                department.OperatingLocation = operatingLocation;

                // Set Department's selected phones from the user to public phones (IsInternal = false)
                foreach (var phoneFromModel in departmentFromModel.Phones)
                {
                    department.Phones.Where(p => p.PhoneId == phoneFromModel.Id).FirstOrDefault().Phone.IsInternal = false;
                }
            }

            modifiedEntities += await this.dbContext.SaveChangesAsync();

            return(modifiedEntities);
        }
        public void EditAsync_ReturnsCorrectNumberOfModifiedEntries()
        {
            var options = new DbContextOptionsBuilder <ApplicationDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

            using (var dbContext = new ApplicationDbContext(options))
            {
                JobPosition jobPosition = new JobPosition()
                {
                    Name = "newJobPos",
                };
                dbContext.JobPositions.Add(jobPosition);
                dbContext.SaveChanges();

                OperatingLocation operatingLocation = new OperatingLocation()
                {
                    Town     = "Sofia",
                    Address  = "test street",
                    ImageUrl = "kgkkkgk",
                };
                dbContext.OperatingLocations.Add(operatingLocation);
                dbContext.SaveChanges();

                Employee employee = new Employee()
                {
                    FirstName           = "Ivan",
                    MiddleName          = "Ivanov",
                    LastName            = "Ivanov",
                    PhoneNumber         = "0897924218",
                    Email               = "*****@*****.**",
                    Town                = "Sofia",
                    Address             = "address 1",
                    ImageUrl            = "aasdfag",
                    OperatingLocationId = operatingLocation.Id,
                    JobPositionId       = jobPosition.Id,
                };

                var employeesService = new EmployeesService(dbContext);
                dbContext.Employees.Add(employee);
                dbContext.SaveChanges();
                var employeeObj = dbContext.Employees.FirstOrDefaultAsync();

                EditEmployeeServiceModel model = new EditEmployeeServiceModel
                {
                    Id        = employeeObj.Result.Id,
                    FirstName = "new name",
                };

                var result = employeesService.EditAsync(model);

                Assert.Equal(1, result.Result);
            }
        }
        //--------------- METHODS -----------------
        /// <summary>
        /// Creates a new <see cref="Service"/> using the <see cref="CreateServiceServiceModel"/>.
        /// If such <see cref="Service"/> already exists in the database, fetches it's (int)<c>Id</c> and returns it.
        /// If such <see cref="Service"/> doesn't exist in the database, adds it and return it's (int)<c>Id</c>.
        /// </summary>
        /// <param name="model">Service model with <c>ServiceTypeId</c>, <c>Name</c>, <c>Description</c> and <c>IsShownInMenu</c></param>
        /// <returns>Service ID</returns>
        public async Task <int> CreateAsync(CreateServiceServiceModel model)
        {
            int serviceId = this.dbContext.Services.Where(x => x.Name == model.ServiceName && x.VehicleTypeId == model.VehicleTypeId)
                            .Select(x => x.Id)
                            .FirstOrDefault();

            if (serviceId != 0)   // If serviceId is different than 0 (default int value), service with such name and vehicleType already exists, so return it's id.
            {
                return(serviceId);
            }

            Service service = new Service
            {
                ServiceTypeId    = model.ServiceTypeId,
                VehicleTypeId    = model.VehicleTypeId,
                Name             = model.ServiceName,
                Description      = model.ServiceDescription,
                IsShownInSubMenu = model.IsShownInSubMenu,
                Price            = model.Price,
            };

            foreach (var operatingLocationDropdown in model.OperatingLocations)
            {
                OperatingLocation operatingLocation = this.dbContext.OperatingLocations.FirstOrDefault(x => x.Id == operatingLocationDropdown.Id);
                await this.dbContext.ServiceOperatingLocations.AddAsync(new ServiceOperatingLocation
                {
                    Service           = service,
                    OperatingLocation = operatingLocation,
                });
            }

            foreach (var documentDropdown in model.Documents)
            {
                Document document = this.dbContext.Documents.FirstOrDefault(x => x.Id == documentDropdown.Id);
                await this.dbContext.ServiceDocuments.AddAsync(new ServiceDocument
                {
                    Service  = service,
                    Document = document,
                });
            }

            await this.dbContext.Services.AddAsync(service);

            await this.dbContext.SaveChangesAsync();

            return(service.Id);
        }
        public void Exist_ReturnsTrue()
        {
            var options = new DbContextOptionsBuilder <ApplicationDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

            using (var dbContext = new ApplicationDbContext(options))
            {
                JobPosition jobPosition = new JobPosition()
                {
                    Name = "newJobPos",
                };
                dbContext.JobPositions.Add(jobPosition);
                dbContext.SaveChanges();

                OperatingLocation operatingLocation = new OperatingLocation()
                {
                    Town     = "Sofia",
                    Address  = "test street",
                    ImageUrl = "kgkkkgk",
                };
                dbContext.OperatingLocations.Add(operatingLocation);
                dbContext.SaveChanges();

                Employee employee = new Employee()
                {
                    FirstName           = "Ivan",
                    MiddleName          = "Ivanov",
                    LastName            = "Ivanov",
                    PhoneNumber         = "0897924218",
                    Email               = "*****@*****.**",
                    Town                = "Sofia",
                    Address             = "address 1",
                    ImageUrl            = "aasdfag",
                    OperatingLocationId = operatingLocation.Id,
                    JobPositionId       = jobPosition.Id,
                };

                dbContext.Employees.Add(employee);
                dbContext.SaveChanges();

                var employeesService = new EmployeesService(dbContext);
                var result           = employeesService.Exists(employee.Id);

                Assert.True(result);
            }
        }
        //--------------- METHODS -----------------
        /// <summary>
        /// Creates a new <see cref="OperatingLocation"/> using the <see cref="CreateOperatingLocationServiceModel"/>.
        /// If such <see cref="OperatingLocation"/> already exists in the database, fetches it's (int)<c>Id</c> and returns it.
        /// If such <see cref="OperatingLocation"/> doesn't exist in the database, adds it and return it's (int)<c>Id</c>.
        /// </summary>
        /// <param name="model">Service model with <c>Town</c>, <c>Address</c>, <c>Description</c>, <c>ImageUrl</c> and a collection <c>Departments</c></param>
        /// <returns>OperatingLocation ID</returns>
        public async Task <int> CreateAsync(CreateOperatingLocationServiceModel model)
        {
            int operatingLocationId = this.dbContext.OperatingLocations.Where(x => x.Town == model.Town && x.Address == model.Address)
                                      .Select(x => x.Id)
                                      .FirstOrDefault();

            if (operatingLocationId != 0) // If operatingLocationId is different than 0 (default int value), operatingLocation with such town and address already exists, so return it's id.
            {
                return(operatingLocationId);
            }

            OperatingLocation operatingLocation = new OperatingLocation
            {
                Town        = model.Town,
                Address     = model.Address,
                Description = model.Description,
                ImageUrl    = model.ImageUrl,
            };

            await this.dbContext.OperatingLocations.AddAsync(operatingLocation);

            await this.dbContext.SaveChangesAsync();

            foreach (var departmentFromModel in model.Departments)
            {
                // Set Department's OperatingLocationId, because it is null by default
                Department department = this.dbContext.Departments.FirstOrDefault(x => x.Id == departmentFromModel.Id);
                department.OperatingLocation = operatingLocation;

                // Set Department's selected phones from the user to public phones (IsInternal = false)
                foreach (var phoneFromModel in departmentFromModel.Phones)
                {
                    department.Phones.Where(p => p.PhoneId == phoneFromModel.Id).FirstOrDefault().Phone.IsInternal = false;
                }

                await this.dbContext.SaveChangesAsync();
            }

            return(operatingLocation.Id);
        }
        /// <summary>
        /// Removes a <see cref="OperatingLocation"/> with the given <c>Id</c> from the database.
        /// </summary>
        /// <param name="id">OperatingLocation ID</param>
        /// <returns>True - removed entity. False - no such entity found.</returns>
        public async Task <bool> RemoveAsync(int id)
        {
            OperatingLocation operatingLocation = this.dbContext.OperatingLocations.Find(id);

            if (operatingLocation == null)
            {
                return(false);
            }

            // First Set each Department's OperatingLocationId to null for that Operating Location
            foreach (var department in this.dbContext.Departments.Where(x => x.OperatingLocationId == operatingLocation.Id))
            {
                department.OperatingLocationId = null;
            }

            // Then Delete cascade all employees with that operatingLocation
            for (int i = 0; i < operatingLocation.Employees.Count; i++)
            {
                await this.employeesService.RemoveAsync(operatingLocation.Employees.ToArray()[i].Id);

                i--;
            }

            // Then Delete all serviceOperatingLocation related entities (Mapping table)
            this.dbContext.ServiceOperatingLocations.RemoveRange(operatingLocation.Services);

            // And lastly Delete the operatingLocation itself
            this.dbContext.OperatingLocations.Remove(operatingLocation);

            int deletedEntities = await this.dbContext.SaveChangesAsync();

            if (deletedEntities == 0)
            {
                return(false);
            }
            return(true);
        }