public async Task <ApiResponse> Get([FromQuery] TicketsFilterParams arg)
        {
            try
            {
                var tickets = await ticketService.GetAllAsync(arg);

                return(new ApiResponse(tickets, HttpStatusCode.OK.ToInt()));
            }
            catch (CustomException ex)
            {
                throw new ApiException(ex, ex.StatusCode);
            }
            catch (Exception ex)
            {
                throw new ApiException(ex);
            }
        }
        public async Task <PaginatedList <GetTicketDTO> > GetAllAsync(TicketsFilterParams arg)
        {
            try
            {
                var userRoles = appUser.Roles;

                IQueryable <Ticket> query;

                #region AllOfTheTicketsThatUserCanAccess
                if (arg.OnlyTicketsOfGroup)
                {
                    var groups = appUser.Groups;
                    query = db.Tickets;

                    if (groups.Length > 1)
                    {
                        foreach (var group in groups)
                        {
                            query = query.Where(w => w.NomineeGroupId.HasValue && w.NomineeGroupId == group);
                        }
                    }
                    else
                    {
                        //if user has no group with this trick we return nothing.
                        //returning null, or use of take & skip has some bugs when comes to ui.
                        query = query.Where(w => w.NomineeGroupId == int.MaxValue);
                    }
                }
                //query = db.Tickets.Where(w => appUser.Groups.Any(a =>
                //w.NomineeGroupId.HasValue && a == w.NomineeGroupId.Value));

                else if (arg.OnlyTicketsOfAssignee)
                {
                    query = db.Tickets.Where(w => w.AssigneeId == appUser.Id.ToString());
                }

                else if (arg.OnlyOpenedByUser)
                {
                    query = db.Tickets.Where(w => w.OpenedById == appUser.Id.ToString());
                }

                else if (arg.OnlyClosedByUser)
                {
                    query = db.Tickets.Where(w => w.ClosedById == appUser.Id.ToString());
                }

                else if (arg.OnlyIfUserHasCreated)
                {
                    query = db.Tickets.Where(w => w.Conversations.Any(a => a.CreatedById == appUser.Id));
                }

                //if none of above is true it means that the user want to see all of the tickets
                //based on the role of the user the result is different
                else
                {
                    //admin or observer can see all of the tickets in the system
                    query = db.Tickets.AsQueryable();

                    if (userRoles.Any(a => a == Roles.Admin || a == Roles.Observer))
                    {
                        //admin or observer can see all.
                    }

                    else if (userRoles.Any(a => a == Roles.Employee))
                    {
                        //employee can see all of the tickets that he has somehow participated in
                        query = FilterQueryForUsersThatHaveParticipatedInTheTicket(appUser, query);
                    }

                    else
                    {
                        //users can only see the tickets that has opened by them
                        query = FilterQueryForUsersThatHaveCreatedTheTicket(appUser, query);
                    }
                }
                #endregion

                #region OtherFilters
                if (arg.FromDate != null)
                {
                    query = query.Where(w => w.Created >= arg.FromDate);
                }

                if (arg.ToDate != null)
                {
                    query = query.Where(w => w.Created <= arg.ToDate);
                }

                if (arg.IsClosed)
                {
                    query = query.Where(w => w.IsClosed);
                }

                if (arg.PriorityId != 0)
                {
                    query = query.Where(w => w.PriorityId == arg.PriorityId);
                }

                if (arg.IssueUrlId != 0)
                {
                    query = query.Where(w => w.IssueUrlId == arg.IssueUrlId);
                }

                if (arg.TicketStatusId != 0)
                {
                    query = query.Where(w => w.TicketStatusId == arg.TicketStatusId);
                }

                if (arg.CustomerOrganizationId != 0)
                {
                    query = query.Where(w => w.CustomerOrganizationId == arg.CustomerOrganizationId);
                }

                if (arg.NomineeGroupId != 0)
                {
                    query = query.Where(w => w.NomineeGroupId == arg.NomineeGroupId);
                }

                if (arg.AssigneeId != null)
                {
                    query = query.Where(w => w.AssigneeId == arg.AssigneeId);
                }

                if (arg.HasAssignee != null)
                {
                    if (arg.HasAssignee.Value)
                    {
                        query = query.Where(w => w.AssigneeId != null || w.NomineeGroupId != null);
                    }
                    else
                    {
                        query = query.Where(w => w.AssigneeId == null || w.NomineeGroupId == null);
                    }
                }

                if (arg.Title != null)
                {
                    query = query.Where(w => w.Title.Contains(arg.Title) ||
                                        w.Conversations.Any(a => a.Message.Contains(arg.Title)));
                }

                #endregion

                #region Ordering
                //if user want to orderby his needs then:
                if (arg.OrderByProperty != null && query.PropertyExists(arg.OrderByProperty))
                {
                    if (arg.HowToOrder != null && arg.HowToOrder.ToLower() == "asc")
                    {
                        query = query.OrderByProperty(arg.OrderByProperty);
                    }
                    else
                    {
                        query = query.OrderByPropertyDescending(arg.OrderByProperty);
                    }
                }
                else
                {
                    //sort by date of the ticket so newer ones come first.
                    query = query.OrderByDescending(o => o.Created);
                }
                #endregion

                var list = await new PaginatedListBuilder <Ticket, GetTicketDTO>(mapper)
                           .CreateAsync(query, arg.PageNumber, arg.PageSize);

                return(list);
            }

            catch (Exception ex)
            {
                throw;
            }
        }