namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Configurations;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;

    using Newtonsoft.Json;

    using Shared.DataFilters;
    using Shared.EntityModels;

    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels;

    /// <inheritdoc />
    public class TicketServices : ITicketService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <summary>
        /// The amazon s 3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration amazonS3Configuration;

        /// <inheritdoc cref="IServiceService" />
        public TicketServices(IUnitOfWork unitOfWork, IAmazonS3Configuration amazonS3Configuration)
        {
            this.unitOfWork = unitOfWork;
            this.amazonS3Configuration = amazonS3Configuration;
        }

        /// <inheritdoc/>
        public async Task<AccountModel> CheckAccountExists(string mobile, int roleId)
        {
            var query =
                $@"Select A.""AccountId"",A.""RoleId"",R.""RoleName"",A.""FullName"",A.""Mobile"",C.""CountryName"" from ""Account"" A
                                    join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                    join ""Country"" C on C.""CountryId"" = A.""CountryId""
                                    where A.""Mobile"" = '{mobile}' and A.""RoleId"" = {roleId}";
            var response = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AccountModel>(query);

            return response ?? new AccountModel();
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<SupportCategories>> GetSupportCategories(bool? isExists)
        {
            var where = "where 1=1";
            if (isExists != null)
            {
                where += $@" and (""IsShowToExisting"" is {isExists} or ""IsShowToExisting"" is null)";
            }

            var query =
                $@"Select * from ""SupportCategory""  {where}";
            return await this.unitOfWork.Current.QueryAsync<SupportCategories>(query);
        }

        /// <inheritdoc/>
        public async Task<Tuple<int, string>> GenerateTicketAsync(TicketModel model)
        {
            var ticket = new Ticket
            {
                Active = true,
                CreatedDate = DateTime.UtcNow,
                ModifiedBy = null,
                ModifiedDate = null,
                Priority = model.Priority ?? "H",
                Status = "P",
                FromWhen = model.FromWhen,
                Attachment = model.Attachment,
                Description = model.Description,
                EndDate = null,
                Mobile = model.Mobile,
                RaisedBy = model.RaisedBy,
                StartDate = DateTime.Now,
                SupportCategoryId = model.SupportCategoryId,
                SupportConversation = model.SupportConversation,
                CountryId = model.CountryId,
                DueDate = model.DueDate ?? DateTime.Now.AddDays(1),
                DueTime = model.DueTime ?? DateTime.Now.TimeOfDay,
                Comments = model.Comments,
                TicketNumber = await this.GenerateTicketNumberAsync(model.Priority ?? "H"),
                DeviceType = model.DeviceType,
                LocationId = model.LocationId
            };
            var ticketId = await this.unitOfWork.Tickets.InsertAsync(ticket);
            if (ticketId <= 0 || model.AssignedTo == null)
            {
                return new Tuple<int, string>(ticketId, ticket.TicketNumber);
            }

            var owner = new TicketAssigneeModel
            {
                CreatedBy = model.CreatedBy ?? (int)model.AssignedTo,
                AccountId = (int)model.AssignedTo,
                TicketId = ticketId,
                CreatedDate = DateTime.Now,
                Active = true,
                ModifiedBy = null,
                ModifiedDate = null,
                AssigneeAccountId = null
            };

            await this.AddTicketOwnerAsync(owner);

            var timeline = new TicketTimelineModel
            {
                AssignedTo = (int)model.AssignedTo,
                CreatedBy = model.CreatedBy ?? (int)model.AssignedTo,
                TicketId = ticketId,
                Description = null
            };
            await this.CreateTicketTimeline(timeline);

            return new Tuple<int, string>(ticketId, ticket.TicketNumber);
        }

        /// <inheritdoc/>
        public async Task<int> CreateTicketTimeline(TicketTimelineModel model)
        {
            var timeline = new TicketTimeline
            {
                AssignedDate = DateTime.Now,
                EndDate = null,
                Active = true,
                AssignedTo = model.AssignedTo,
                Description = null,
                CreatedBy = model.CreatedBy,
                Status = "P",
                TicketId = model.TicketId,
                Priority = model.Priority ?? "H",
                Comments = null,
                AssignedToUser = model.AssignedTo
            };
            return await this.unitOfWork.TicketTimeline.InsertAsync(timeline);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<TicketModel>> FetchAllTicketAsync(int pageSize, int pageIndex, int? assignedTo, bool? isAdmin, int? accountId, string priority, string status, DateTime? startDate, DateTime? endDate, string issueWith, string mobileNo, string deviceType, int? assigneeAccountId, int? locationId)
        {
            var where = @" where 1=1 ";
            if (isAdmin == null)
            {
                where += assignedTo == null
                             ? $@" and TT.""AssignedTo"" is null"
                             : $@" and TT.""AssignedTo"" = {assignedTo}";
            }

            if (assigneeAccountId != null || assigneeAccountId > 0)
            {
                where = $@" where TA.""AssigneeAccountId"" = {assigneeAccountId}";
            }

            if (accountId != null)
            {
                where = $@" where TA.""AccountId"" = {accountId}";
            }

            if (locationId != null)
            {
                where = $@" where T.""LocationId"" = {locationId} or T.""LocationId"" is null";
            }

            if (!string.IsNullOrEmpty(priority))
            {
                where += $@" and T.""Priority"" = '{priority}'";
            }

            if (!string.IsNullOrEmpty(status))
            {
                where += $@" and T.""Status"" = '{status}'";
            }

            if (startDate != null && endDate == null)
            {
                where += $@"  and T.""StartDate""::date = '{startDate:yyyy-MM-dd}' ";
            }

            else if (startDate != null && endDate != null)
            {
                where += $@"  and T.""StartDate""::date >= '{startDate:yyyy-MM-dd}' ";
                where += $@"  and T.""StartDate""::date <= '{endDate:yyyy-MM-dd}' ";
            }

            if (!string.IsNullOrEmpty(issueWith))
            {
                where += $@" and T.""SupportCategoryId"" = '{issueWith}'";
            }

            if (!string.IsNullOrEmpty(mobileNo))
            {
                where += $@" AND T.""Mobile"" ILIKE '%{mobileNo}%' ";
            }

            if (!string.IsNullOrEmpty(deviceType))
            {
                where += $@" AND T.""DeviceType"" ILIKE '%{deviceType}%' ";
            }

            var query = $@"SELECT count(T.*) over() as ""TotalItems"",TAA.""FullName"" as ""OwnerName"", T.""TicketId"", T.""TicketNumber"", T.""Priority"" ,T.""FromWhen"", T.""SupportCategoryId"",SC.""IssueWith"", T.""Description"",T.""Attachment"",
                                T.""RaisedBy"", T.""SupportConversation"", T.""Mobile"", T.""Status"", T.""DueDate"",T.""EndDate"",T.""DueTime"", TO_CHAR(T.""DueDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(T.""DueTime"", 'hh12:mi AM') AS ""DueDateTime"", T.""CreatedDate"" ,
                                A.""FullName"" as ""RaisedByName"", TT.""AssignedTo"" ,U.""FullName"" as ""AssignedToName"",AU.""FullName"" as ""NewAssigneeName"",
                                (case when U.""ThumbnailUrl"" is not null then concat('{this.amazonS3Configuration.BucketURL}',U.""Guid"",'/',U.""ThumbnailUrl"") else null end) as ""ThumbnailUrl"",R.""RoleName"",T.""DeviceType"",
                                (case when US.""ThumbnailUrl"" is not null then concat('{this.amazonS3Configuration.BucketURL}',US.""Guid"",'/',US.""ThumbnailUrl"") else null end) as ""NewThumbnailUrl""
                                FROM ""Ticket"" T 
                                join ""SupportCategory"" SC on SC.""SupportCategoryId"" = T.""SupportCategoryId""
                                left join ""Account"" A on A.""AccountId"" = T.""RaisedBy""
                                left join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                left join ""TicketTimeline"" TT on TT.""TicketId"" = T.""TicketId"" and TT.""Active"" is true
                                left join ""TicketAssignee"" TA on TA.""TicketId"" = T.""TicketId"" and TA.""Active"" is true
                                left join ""Account"" TAA on TAA.""AccountId"" = TA.""AccountId""
                                left join ""Account"" AA on AA.""AccountId"" = TT.""AssignedTo""
                                left join ""Account"" AU on AU.""AccountId"" = TA.""AssigneeAccountId""
                                left join ""User"" U on U.""UserId"" = AA.""ReferenceId"" and U.""RoleId"" = AA.""RoleId""
                                left join ""User"" US on US.""UserId"" = AU.""ReferenceId"" and US.""RoleId"" = AU.""RoleId""
                                left join ""Location"" ll on ll.""LocationId"" = T.""LocationId""
                                { where}
                                order by T.""TicketId"" desc";
            if (pageIndex < 0)
            {
                return await this.unitOfWork.Current.QueryAsync<TicketModel>(query);
            }

            pageIndex = pageIndex > 0 ? pageIndex - 1 : pageIndex;

            query += $@" limit {pageSize} offset {pageSize * pageIndex}";
            return await this.unitOfWork.Current.QueryAsync<TicketModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> ModifyTicket(TicketDetailsModel model)
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {
                var checkTicketTable = await this.unitOfWork.Tickets.FindAsync(m => m.TicketId == model.TicketId, transaction);
                var name = await this.unitOfWork.Accounts.FindAsync(m => m.AccountId == model.CreatedBy);
                var description = new List<string>();

                if (model.DueDate != checkTicketTable.DueDate)
                {
                    checkTicketTable.DueDate = model.DueDate;
                    description.Add(
                        $@"{name.FullName} has changed due date from {checkTicketTable.DueDate} to {model.DueDate} at {Convert.ToDateTime(model.AssignedDate):f}");
                }

                if (TimeSpan.Parse(model.DueTime) != checkTicketTable.DueTime)
                {
                    checkTicketTable.DueTime = TimeSpan.Parse(model.DueTime);
                }

                if (model.Status != checkTicketTable.Status)
                {
                    description.Add($@"{name.FullName} has changed status from {GetStatus(checkTicketTable.Status)} to {GetStatus(model.Status)} at {Convert.ToDateTime(model.AssignedDate):f}");
                }

                if (model.Priority != checkTicketTable.Priority)
                {
                    description.Add($@"{name.FullName} has changed priority from {GetPriority(checkTicketTable.Priority)} to {GetPriority(model.Priority)} at {Convert.ToDateTime(model.AssignedDate):f}");
                }

                var ticketTimeline = new TicketTimeline();

                var isNewRecordRequired = true;

                if (model.TicketTimelineId > 0)
                {
                    ticketTimeline = await this.unitOfWork.TicketTimeline.FindAsync(m => m.TicketTimelineId == model.TicketTimelineId, transaction);
                    var receivedTimeline = new TicketTimeline
                    {
                        AssignedDate = ticketTimeline.AssignedDate,
                        EndDate = ticketTimeline.EndDate,
                        Active = ticketTimeline.Active,
                        AssignedTo = model.AssignedTo,
                        CreatedBy = model.AssignedById,
                        Status = model.Status,
                        TicketId = model.TicketId,
                        TicketTimelineId = model.TicketTimelineId,
                        Description = model.AssigneeDescription,
                        Priority = model.Priority
                    };
                    if (JsonConvert.SerializeObject(ticketTimeline) == JsonConvert.SerializeObject(receivedTimeline))
                    {
                        isNewRecordRequired = false;
                    }
                }

                if (isNewRecordRequired)
                {
                    if (model.AssignedTo != ticketTimeline.AssignedTo)
                    {
                        var newAssignedUser =
                            await this.unitOfWork.Accounts.FindAsync(m => m.AccountId == model.AssignedTo);
                        var previousAssignedUser =
                            await this.unitOfWork.Accounts.FindAsync(m => m.AccountId == ticketTimeline.AssignedTo);

                        var message = string.Empty;
                        if (previousAssignedUser != null)
                        {
                            message = $@"{name.FullName} has changed the assigned user from {previousAssignedUser.FullName} to {newAssignedUser.FullName} at {Convert.ToDateTime(model.AssignedDate):f}";
                        }
                        else
                        {
                            message = $@"{name.FullName} has assigned the ticket to {newAssignedUser.FullName} at {Convert.ToDateTime(model.AssignedDate):f}";
                        }

                        description.Add(message);
                    }

                    var timeline = new TicketTimeline
                    {
                        AssignedDate = DateTime.UtcNow,
                        EndDate = null,
                        Active = true,
                        AssignedTo = model.AssignedTo,
                        CreatedBy = model.AssignedById,
                        Status = model.Status,
                        TicketId = model.TicketId,
                        Description = JsonConvert.SerializeObject(description),
                        Priority = model.Priority,
                        Comments = null
                    };
                    timeline.TicketTimelineId = await this.unitOfWork.TicketTimeline.InsertAsync(timeline, transaction);
                    if (timeline.TicketTimelineId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }

                if (isNewRecordRequired && model.TicketTimelineId > 0)
                {
                    ticketTimeline.EndDate = DateTime.UtcNow;
                    ticketTimeline.Active = false;
                    var update = await this.unitOfWork.TicketTimeline.UpdateAsync(ticketTimeline, transaction);
                    if (update == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }

                checkTicketTable.EndDate = (model.Status == "C" || model.Status == "R") ? DateTime.UtcNow : (DateTime?)null;
                checkTicketTable.Priority = model.Priority;
                checkTicketTable.ModifiedBy = model.AssignedById;
                checkTicketTable.ModifiedDate = DateTime.UtcNow;
                checkTicketTable.Status = model.Status;
                checkTicketTable.Comments = model.Comments;

                var ticketUpdate = await this.unitOfWork.Tickets.UpdateAsync(checkTicketTable);
                if (ticketUpdate == 0)
                {
                    transaction.Rollback();
                    return 0;
                }

                transaction.Commit();
                return 1;
            }
        }

        /// <inheritdoc/>
        public async Task<TicketDetailsModel> GetTicketDetails(long ticketId)
        {
            var query =
                $@"Select T.""TicketId"", TA.""TicketAssigneeId"",TAA.""FullName"" as ""TicketOwner"",TA.""AccountId"" as ""TicketOwnerId"",T.""TicketNumber"", T.""Priority"",T.""FromWhen"",T.""Comments"",T.""SupportCategoryId"", SC.""IssueWith"",T.""Description"", T.""Attachment"",ASA.""FullName"" as ""NewAssigneeName"",TA.""AssigneeAccountId"", 
                            T.""RaisedBy"",AA.""FullName"" as ""RaisedByName"",R.""RoleName"" as ""RaisedByRole"",
                            T.""SupportConversation"", T.""Mobile"", T.""CountryId"", T.""Status"", T.""StartDate"", T.""EndDate"", T.""DueDate"", TO_CHAR(T.""DueTime"", 'hh24:mi') ""DueTime"", TO_CHAR(T.""DueDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(T.""DueTime"", 'hh12:mi AM') AS ""DueDateTime"",
                            T.""CreatedDate"",TT.""TicketTimelineId"", TT.""AssignedTo"", TT.""AssignedDate"" as ""AssigneeStartDate"", 
                            TT.""EndDate"" as ""AssigneeEndDate"", 
                            TT.""CreatedBy"" as ""AssignedById"", TT.""Status"" as ""AssigneeStatus"", TT.""Active"" ,
                            U.""FullName"" as ""AssigneeName"" ,
                            (case when U.""ThumbnailUrl"" is not null then concat('{this.amazonS3Configuration.BucketURL}',U.""Guid"",'/',U.""ThumbnailUrl"") else null end) as ""AssigneeThumbnailUrl""        
                            from ""Ticket"" T 
                            join ""SupportCategory"" SC on SC.""SupportCategoryId"" = T.""SupportCategoryId""
                            left join ""TicketAssignee"" TA on TA.""TicketId"" = T.""TicketId"" and TA.""Active"" is true
							left Join ""Account"" TAA on TAA.""AccountId"" = TA.""AccountId""                
                            left Join ""Account"" ASA on ASA.""AccountId"" = TA.""AssigneeAccountId""
                            left join ""TicketTimeline"" TT on TT.""TicketId"" = T.""TicketId"" and TT.""Active"" is true
                            left join ""Account"" A on A.""AccountId"" = TT.""AssignedTo"" 
                            left join ""User"" U on U.""UserId"" = A.""ReferenceId""
                            left join ""Account"" AA on AA.""AccountId"" = T.""RaisedBy""
                            left join ""Role"" R on R.""RoleId"" = AA.""RoleId""
                            where T.""TicketId"" ={ticketId}";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<TicketDetailsModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<TicketTimelineModel>> FetchTicketTimeLineAsync(long ticketId)
        {
            var query = $@"Select A.""FullName"" as ""CreatedByName"",TT.""TicketTimelineId"", TT.""TicketId"", TT.""AssignedTo"",TT.""AssignedToUser"", TT.""EndDate"", TT.""AssignedDate"", TT.""CreatedBy"", TT.""Description"", 
                                    TT.""Active"", TT.""Status"",TT.""Priority"" ,AA.""FullName"" as ""AssignedToName"",TT.""Comments"",A.""FullName"" as ""AssignedToUserName""
                                    from ""TicketTimeline"" TT join ""Account"" A on A.""AccountId"" = TT.""CreatedBy""
                                    join ""Account"" AA on AA.""AccountId"" = TT.""AssignedTo""
                                    where TT.""TicketId"" = {ticketId} order by ""TicketTimelineId"" ASC";
            return await this.unitOfWork.Current.QueryAsync<TicketTimelineModel>(query);
        }

        /// <inheritdoc/>
        public async Task<TicketCountModel> GetCount(int? accountId)
        {
            var where = "where 1=1";
            if (accountId != null)
            {
                where += $@"  and TT.""AssignedTo"" = {accountId}";
            }

            var query = $@"select count(""TicketId"") ""Total"",sum(""Inprogress"") ""Inprogress"" ,sum(""Closed"") ""Closed"" ,sum(""Pending"") ""Pending"" from (
                                    select T.""TicketId"",case when T.""Status""='I' then 1 end ""Inprogress""
                                    ,case when T.""Status""='C' then 1 end ""Closed""
                                    ,case when (T.""Status""='P' or T.""Status""='O') then 1 end ""Pending""
                                    from ""Ticket"" T left join ""TicketTimeline"" TT on TT.""TicketId"" = T.""TicketId"" and TT.""Active"" Is True
                                    {where}) A";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<TicketCountModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> UpdateTicketCommentsAsync(long ticketTimelineId, string comments)
        {
            var ticketTimeline = await this.unitOfWork.TicketTimeline.FindAsync(m => m.TicketTimelineId == ticketTimelineId);
            ticketTimeline.Comments = comments;
            return await this.unitOfWork.TicketTimeline.UpdateAsync(ticketTimeline);
        }

        /// <inheritdoc/>
        public async Task<int> AddTicketOwnerAsync(TicketAssigneeModel model)
        {
            var previousOwner = await this.unitOfWork.TicketAssignees.FindAsync(m => m.TicketId == model.TicketId && m.Active);

            if (previousOwner != null && model.AssigneeAccountId != null)
            {
                var updated = await this.unitOfWork.Current.ExecuteAsync($@"Update ""TicketAssignee"" set ""AssigneeAccountId"" = {model.AssigneeAccountId}, ""ModifiedBy"" = {model.ModifiedBy},""ModifiedDate"" = now() where ""TicketAssigneeId"" = {previousOwner.TicketAssigneeId}");
                if (updated > 0)
                {
                    return -2;
                }
                return -1;
            }

            var owner = new TicketAssignee
            {
                CreatedDate = DateTime.UtcNow,
                AccountId = model.AccountId,
                Active = true,
                CreatedBy = model.CreatedBy,
                ModifiedBy = null,
                ModifiedDate = null,
                TicketId = model.TicketId,
                AssigneeAccountId = model.AccountId
            };
            return await this.unitOfWork.TicketAssignees.InsertAsync(owner);
        }

        /// <inheritdoc/>
        public async Task<int> UpdateTicketTimeline(TicketTimelineModel model)
        {
            var previousRecord =
                await this.unitOfWork.TicketTimeline.FindAsync(m => m.TicketId == model.TicketId && m.Active);
            if (previousRecord == null)
            {
                return 0;
            }

            await this.unitOfWork.Current.ExecuteAsync(
                    $@"Update ""TicketTimeline"" set ""Active"" = false where ""TicketTimelineId"" = {previousRecord.TicketTimelineId}");

            var previousOwner = await this.unitOfWork.Accounts.FindAsync(m => m.AccountId == previousRecord.AssignedTo);
            var currentOwner = await this.unitOfWork.Accounts.FindAsync(a => a.AccountId == model.AssignedTo);

            var previousUser = await this.unitOfWork.Accounts.FindAsync(m => m.AccountId == previousRecord.AssignedToUser);
            var currentUser = await this.unitOfWork.Accounts.FindAsync(a => a.AccountId == model.AssignedTouser);

            var msg = model.IsAssigneeUserUpdate == true ?
                $@"Ticket User has been changed from {previousUser.FullName} to {currentUser.FullName} at {DateTime.Now:D}" :
                $@"Ticket owner has been changed from {previousOwner.FullName} to {currentOwner.FullName} at {DateTime.Now:D}";

            var description = new List<string> { msg };

            var timeline = new TicketTimeline
            {
                EndDate = previousRecord.EndDate,
                Status = previousRecord.Status,
                Active = true,
                TicketId = model.TicketId,
                CreatedBy = model.CreatedBy,
                Priority = previousRecord.Priority,
                AssignedTo = model.AssignedTo,
                Description = JsonConvert.SerializeObject(description),
                AssignedDate = previousRecord.AssignedDate,
                Comments = null,
                AssignedToUser = model.AssignedTouser
            };
            return await this.unitOfWork.TicketTimeline.InsertAsync(timeline);
        }

        /// <inheritdoc/>
        public async Task<PerformanceModel> FetchPerformanceTime()
        {
            var query = $@"Select * from ""Performance"" where ""Active"" is true";
            return await this.unitOfWork.Current.QuerySingleOrDefaultAsync<PerformanceModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<TicketModel>> GetTicketsAsync(DateTime? startDate, string type, int? accountId)
        {
            var join = "left join";
            var where = " where 1=1";
            if (accountId != null)
            {
                join = "join";
                where = $@" and TT.""AssignedTo"" = {accountId} ";
            }

            if (startDate != null)
            {
                where += type == "today"
                             ? $@" and T.""StartDate""::date = '{Convert.ToDateTime(startDate):yyyy-MM-dd}' "
                             : $@" and T.""StartDate""::date >= '{Convert.ToDateTime(startDate):yyyy-MM-dd}' ";
            }

            var query = $@"Select count(T.""TicketId"") over() as ""Total"" ,T.""TicketNumber"",T.""TicketId"",T.""Priority"",T.""Status"",T.""StartDate"",T.""EndDate"",T.""DueDate"",TT.""AssignedTo""
                                    from ""Ticket"" T {join} ""TicketTimeline"" TT on T.""TicketId"" = TT.""TicketId"" and TT.""Active"" is true
                                    {where} order by T.""TicketId"" desc";
            return await this.unitOfWork.Current.QueryAsync<TicketModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<AccountModel>> GetSupportUsersAsync(string mobile)
        {
            var query = $@"Select A.""Email"",A.""FullName"",T.""Description"",T.""Mobile"" from ""Account"" A join ""Ticket"" T On A.""RoleId"" = {(int)Roles.Support} and A.""Active"" = true  and T.""Mobile"" = '{mobile}' order by T.""TicketId"" desc";
            return await this.unitOfWork.Current.QueryAsync<AccountModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> UpdateTicketOwnerAsync(TicketAssigneeModel model)
        {
            try
            {
                var previousOwner = await this.unitOfWork.TicketAssignees.FindAsync(m => m.TicketId == model.TicketId && m.Active);

                if (previousOwner != null && model.AccountId > 0)
                {
                    var query = $@"Update ""TicketAssignee"" set ""AccountId"" = {model.AccountId}, ""ModifiedBy"" = {model.ModifiedBy},""ModifiedDate"" = now() where ""TicketAssigneeId"" = {previousOwner.TicketAssigneeId}";
                    var updated = await this.unitOfWork.Current.ExecuteAsync(query);
                    if (updated > 0)
                    {
                        return -2;
                    }
                }
            }
            catch (Exception e)
            {

            }
            return -1;
        }

        /// <summary>
        /// The get status.
        /// </summary>
        /// <param name="status">
        /// The status.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string GetStatus(string status)
        {
            switch (status)
            {
                case "O":
                    return "ReOpen";
                case "P":
                    return "Pending";
                case "C":
                    return "Close";
                case "I":
                    return "Inprogress";
                default:
                    return "Resolved";
            }
        }

        /// <summary>
        /// The get priority.
        /// </summary>
        /// <param name="priority">
        /// The priority.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string GetPriority(string priority)
        {
            switch (priority)
            {
                case "H":
                    return "High";
                case "M":
                    return "Medium";
                default:
                    return "Low";
            }
        }

        /// <summary>
        /// The generate ticket number async.
        /// </summary>
        /// <param name="priority">
        /// The priority.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private async Task<string> GenerateTicketNumberAsync(string priority)
        {
            var ticketNumber = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<string>($@"SELECT ""TicketNumber"" FROM ""Ticket"" where ""TicketNumber"" ILIKE '%{priority}%' ORDER BY ""TicketId"" DESC");
            return CoreFilter.GetTicketNumber(ticketNumber, priority);
        }

    }
}