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

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

        /// <summary>
        /// Initializes a new instance of the <see cref="AccountSessionServices"/> class.
        /// </summary>
        /// <param name="unitOfWork">
        /// The unit of work.
        /// </param>
        public AccountSessionServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> FetchAsync(int accountId)
        {
            var query = $@"SELECT * FROM ""AccountSession"" WHERE ""AccountId"" = '{accountId}' AND ""Active"" IS TRUE order by ""CreatedDate"" desc ";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> FetchDeviceTokenAsync(int referenceId, Roles role)
        {
            var query = $@"SELECT * FROM ""AccountSession"" WHERE ""AccountId"" = (select ""AccountId"" from ""Account""  WHERE ""ReferenceId"" = {referenceId} and ""RoleId""={(int)role} ) AND ""Active"" IS TRUE order by ""CreatedDate"" desc ";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<AccountSessionModel> FindAsync(int accountSessionId)
        {
            var query = $@"SELECT * FROM ""AccountSession"" WHERE ""AccountSessionId"" = '{accountSessionId}' AND ""Active"" IS TRUE order by ""CreatedDate"" desc";
            return this.unitOfWork.Current.QueryFirstOrDefaultAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public async Task<int> CreateAsync(AccountSessionModel model)
        {
            // await this.unitOfWork.Current.ExecuteAsync($@"DELETE FROM ""AccountSession"" WHERE ""AccountId"" = '{model.AccountId}' AND ""DeviceType"" = '{model.DeviceType}'");
            var accountSession = new AccountSession
            {
                AccountId = model.AccountId,
                DeviceType = model.DeviceType,
                DeviceId = model.DeviceId,
                Active = true,
                CreatedDate = DateTime.UtcNow,
                Description = model.Description,
                DeviceToken = model.DeviceToken
            };

            return await this.unitOfWork.AccountSessions.InsertAsync(accountSession);
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int accountSessionId)
        {
            var where = $@" WHERE ""AccountSessionId"" = '{accountSessionId}'";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int accountId, DeviceType deviceType, string deviceId)
        {
            var where = $@" WHERE ""AccountId"" = '{accountId}' AND ""DeviceType"" = '{(short)deviceType}' and   ""DeviceId""= '{deviceId}'";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int accountId, string deviceId)
        {
            var where = $@" WHERE ""AccountId"" = '{accountId}' and ""DeviceId""= '{deviceId}' ";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> WebLogoutAsync(int accountId, DeviceType deviceType)
        {
            var where = $@" WHERE ""AccountId"" = '{accountId}' and ""DeviceType"" = '{(short)deviceType}' ";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> DeleteAllAsync(int accountId)
        {
            var where = $@" WHERE ""AccountId"" = '{accountId}'";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> DeleteOthersAsync(int accountId, string deviceId)
        {
            var where = $@" WHERE ""AccountId"" = '{accountId}' and ""DeviceId"" not in  ('{deviceId}')";
            var query = $@"DELETE FROM ""AccountSession"" {where}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }
    }
}