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 Hims.Shared.Library;
    using Shared.EntityModels;
    using Shared.UserModels.Filters;

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

        /// <inheritdoc cref="IWardService" />
        public WardService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<WardModel>> FetchAsync(WardFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            
            if (model.FloorId > 0)
            {
                where += $@" AND F.""FloorId"" = {model.FloorId}";
            }
            if (model.LocationId > 0)
            {
                where += $@" AND F.""LocationId"" = {model.LocationId}";
            }
            if (model.WardId > 0)
            {
                where += $@" AND W.""WardId"" = {model.WardId}";
            }

            if (!string.IsNullOrEmpty(model.FloorName))
            {
                where += $@" and F.""FloorName"" ilike '%{model.FloorName}%' ";
            }

            if (!string.IsNullOrEmpty(model.WardName))
            {
                where += $@" and W.""WardName"" ilike '%{model.WardName}%' ";
            }
            //if (model.LocationId > 0)
            //{
            //    where += $@" AND F.""LocationId""  = {model.LocationId}";
            //}
           
            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"",W.""Active"",
                        W.""WardId"",  W.""WardName"" ,CA.""FullName"" AS ""CreatedByName"" , MA.""FullName"" AS ""ModifiedByName"" , W.""CreatedDate"", W.""ModifiedDate"",
                         F.""FloorName"", F.""FloorId"",L.""Name"" as ""LocationName"" ,L.""LocationId""
                       FROM ""Ward"" W
                       JOIN ""Floor"" F on F.""FloorId""=W.""FloorId""
                       Join ""Location"" L on L.""LocationId""=F.""LocationId""
                       Left Join ""Account"" CA ON CA.""AccountId"" = W.""CreatedBy""         
                       Left Join ""Account"" MA ON MA.""AccountId"" = W.""ModifiedBy""
                                {where} Order by ""WardId"" DESC";
            if (model.PageIndex <= 0)
            {
                return this.unitOfWork.Current.QueryAsync<WardModel>(query);
            }

            model.PageIndex -= 1;
             query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            return this.unitOfWork.Current.QueryAsync<WardModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<Resource>> FetchWardAsync(WardFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.FloorId > 0)
            {
                where += $@" AND F.""FloorId"" = {model.FloorId}";
            }
            if (model.LocationId > 0)
            {
               where += $@" and F.""LocationId"" = {model.LocationId}";
            }
            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"",W.""Active"",
                        W.""WardId"" AS ""Id"",W.""WardName"" AS ""Value"" ,F.""FloorName"" AS ""OptionalText1"", L.""Name"" AS ""OptionalText""
                                FROM ""Ward"" W
                                JOIN ""Floor"" F on F.""FloorId""=W.""FloorId""
                                 Join ""Location"" L on F.""LocationId"" = L.""LocationId""
                                {where} and  W.""Active"" = true Order by ""WardId"" DESC";          
            return this.unitOfWork.Current.QueryAsync<Resource>(query);
        }


        /// <inheritdoc />
        public async Task<int> AddAsync(WardModel model)
        {
            
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""WardId"")  FROM ""Ward"" WHERE TRIM(UPPER(""WardName"")) = '{model.WardName.ToUpper().Trim()}' and ""FloorId"" ={model.FloorId}");
            if (checkIf > 0)
            {
                return -1;
            }
            var ward = new Ward
            {
                Active = true,
                WardName = model.WardName,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                FloorId = model.FloorId,
            };
            return await this.unitOfWork.Wards.InsertAsync(ward);
        }
       
        /// <inheritdoc />
        public async Task<int> UpdateAsync(WardModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""WardId"")  FROM ""Ward"" WHERE TRIM(UPPER(""WardName"")) = '{model.WardName.ToUpper().Trim()}' and ""FloorId"" ={model.FloorId}");
            var ward = await this.unitOfWork.Wards.FindAsync(m => m.WardId == model.WardId);
            ward.WardName = model.WardName;
            ward.Active = model.Active;
            ward.ModifiedBy = model.ModifiedBy;
            ward.ModifiedDate = DateTime.Now;
            ward.FloorId = model.FloorId;

            if (model.updateStatus==true)
                return await this.unitOfWork.Wards.UpdateAsync(ward);
            if (checkIf > 0)
            {
                return -1;
            }
            


            
            return await this.unitOfWork.Wards.UpdateAsync(ward);
        }

        /// <inheritdoc />
        public async Task<int> DeleteAsync(int wardId)
        {
            var query1 = $@"select count(""BedId"") from ""Admission"" where ""IsDischarged"" is false and ""Active"" is true and ""BedId"" in (select b.""BedId"" from ""Bed"" b join ""Room"" r on r.""RoomId"" = b.""RoomId"" where r.""WardId"" = {wardId}) ";
            var response1 = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query1);
            if (response1 > 0)
            {
                return -2;
            }
            var query = $@"DELETE FROM ""Ward"" WHERE ""WardId""= {wardId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<string> FindNameByWardId(int wardId)
        {
            var query = $@"SELECT ""WardName"" FROM ""Ward"" WHERE ""WardId"" = {wardId}";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
            return response;
        }

        /// <summary>
        /// Changes the status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public async Task<int> ChangeStatusAsync(WardModel model)
        {
            var query = $@"select count(""BedId"") from ""Admission"" where ""IsDischarged"" is false and ""Active"" is true and ""BedId"" in (select b.""BedId"" from ""Bed"" b join ""Room"" r on r.""RoomId"" = b.""RoomId"" where r.""WardId"" = {model.WardId}) ";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
            if (response > 0)
            {
                return -2;
            }
            var ward = await this.unitOfWork.Wards.FindAsync(m => m.WardId == model.WardId);
            if (ward == null)
            {
                return -1;
            }
            ward.Active = model.Active;
            ward.ModifiedBy = model.ModifiedBy;
            ward.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.Wards.UpdateAsync(ward);
        }

    }
}