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

    /// <summary> The chat service.</summary>
    public class ChatService : IChatService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IChatService" />
        public ChatService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <summary> The fetch async.</summary>
        /// <param name="senderId"> The sender id.</param>
        /// <param name="senderType"> The sender type.</param>
        /// <param name="receiverId"> The receiver id.</param>
        /// <param name="receiverType"> The receiver type.</param>
        /// <param name="date"> The date.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        public async Task<IEnumerable<ChatModel>> FetchAsync(
            string senderId,
            string senderType,
            string receiverId,
            string receiverType,
            string date)
        {
            var where = " WHERE 1 = 1 ";

            if (!string.IsNullOrEmpty(senderId) && !string.IsNullOrEmpty(receiverId))
            {
                where += $@" and ""SenderId"" in ({senderId},{receiverId}) and ""ReceiverId"" in ({senderId},{receiverId})";
            }

            if (!string.IsNullOrEmpty(date))
            {
                where += $@" and ""CreatedDate"":: date ={date}";
            }

            var query = $@"Select * From ""Chat"" {where} order by ""CreatedDate"" ";
            return await this.unitOfWork.Current.QueryAsync<ChatModel>(query);
        }

        /// <summary>The save async.</summary>
        /// <param name="chatModel"> The chat model.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        public async Task<int> SaveAsync(ChatModel chatModel)
        {
            var model = new Chat()
            {
                SenderId = chatModel.SenderId,
                SenderType = chatModel.SenderType,
                ReceiverId = chatModel.ReceiverId,
                ReceiverType = chatModel.ReceiverType,
                Message = chatModel.Message,
                CreatedDate = DateTime.Now
            };
            if (chatModel.ChatId == 0)
            {
                return await this.unitOfWork.Chats.InsertAsync(model);
            }
            else
            {
                model.ChatId = chatModel.ChatId;
                return await this.unitOfWork.Chats.UpdateAsync(model);
            }
        }

        /// <summary> The delete async.</summary>
        /// <param name="chatId"> The chat id.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        public async Task<int> DeleteAsync(long chatId)
        {
            var query = $@"DELETE FROM ""Chat"" WHERE ""ChatId""= {chatId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <summary> The find async.</summary>
        /// <param name="chatId"> The chat id.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        public async Task<ChatModel> FindAsync(long chatId)
        {
            var query = $@"SELECT * FROM ""Chat"" WHERE ""ChatId"" = {chatId}";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<ChatModel>(query);
        }
    }
}
