using System;
using System.Collections.Generic;
using System.Text;

using Dapper;
using System.Threading.Tasks;
using Hims.Domain.Repositories.UnitOfWork;
using Hims.Domain.Services;
using Hims.Shared.UserModels;
using Hims.Domain.Repositories.UnitOfWork;
using Hims.Domain.Entities;

namespace Hims.Infrastructure.Services
{
    public class DoctorAppointmentNoticeService : IDoctorAppointmentNoticeService
    {
        private readonly IUnitOfWork unitOfWork;
        /// <inheritdoc cref="IDoctorAppointmentNoticeService" />
        public DoctorAppointmentNoticeService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        public async Task<int> DeleteAsync(int doctorAppointmentNoticeId)
        {
            var query = $@"DELETE FROM ""DoctorAppointmentNotice"" WHERE ""DoctorAppointmentNoticeId""= {doctorAppointmentNoticeId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }



        /// <inheritdoc />
        public async Task<int> ModifyStatusAsync(DoctorAppointmentNoticeModel model)
        {
            var query = $@"UPDATE ""DoctorAppointmentNotice""
	                           SET ""ModifiedBy""={model.CreatedBy}, ""ModifiedDate""=now(), ""Active""= {model.Active}
	                           WHERE ""DoctorAppointmentNoticeId""= {model.DoctorAppointmentNoticeId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<IEnumerable<DoctorAppointmentNoticeModel>> FetchAsync(DoctorAppointmentNoticeModel model)
        {

            var where = " WHERE 1 = 1 ";
            //if (model.Active != null)
            //{
            //    where += $@" AND Da.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            //}
            if (model.CreatedBy != null)
            {
                where += $@" AND Da.""CreatedBy"" = {model.CreatedBy}";
            }
            if (!string.IsNullOrEmpty(model.FromDate) && (!string.IsNullOrEmpty(model.ToDate)))
            {
                where += $@" And (Da.""FromDate""::Date between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or    Da.""ToDate""::Date   between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or Da.""FromDate""::Date   between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or '{model.FromDate}'::DATE >= Da.""FromDate""::Date  and '{model.ToDate}'::DATE <= Da.""ToDate""::Date)";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  Da.""LocationId"" ={model.LocationId} ";
            }
            if (model.ProviderId > 0)
            {
                where += $@" and  Pr.""ProviderId"" ={model.ProviderId} ";
            }
            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", Da.*, Pr.""FullName"" ""ProviderName"",  L.""Name"" ""LocationName"",CA.""FullName"" AS ""CreatedByName"" , MA.""FullName"" AS ""ModifiedByName""
	                                FROM ""DoctorAppointmentNotice"" Da
	                                LEFT JOIN ""Provider"" Pr ON Pr.""ProviderId"" = Da.""ProviderId""
	                                LEFT JOIN ""Location"" L ON L.""LocationId"" = Da.""LocationId""
									LEFT JOIN ""Account"" CA ON CA.""AccountId"" = Da.""CreatedBy""
                       				LEFT JOIN ""Account"" MA ON MA.""AccountId"" = Da.""ModifiedBy""
                                {where} Order by Da.""DoctorAppointmentNoticeId"" DESC";

            if (model.PageIndex <= 0 || model.PageIndex == null)
            {
                return await this.unitOfWork.Current.QueryAsync<DoctorAppointmentNoticeModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return await this.unitOfWork.Current.QueryAsync<DoctorAppointmentNoticeModel>(query);
        }

        public async Task<int> InsertAsync(DoctorAppointmentNoticeModel model)
        {


            //var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""DoctorAppointmentNoticeId"") FROM ""DoctorAppointmentNotice"" WHERE TRIM(UPPER(""ChargeName"")) = '{model.ChargeName.ToUpper().Trim()}'");
            var checkIf = await this.unitOfWork.DoctorAppointmentNotices.FindAllAsync(m => m.ProviderId == model.ProviderId && m.LocationId == model.LocationId
                                && m.FromDate >= Convert.ToDateTime(model.FromDate) && m.ToDate <= Convert.ToDateTime(model.ToDate));
            if (checkIf.AsList().Count > 0)
            {
                return -1;
            }

            var doctorAppointmentNotice = new DoctorAppointmentNotice
            {
                Description = model.Description,
                LocationId = model.LocationId,
                ProviderId = (int)model.ProviderId,
                FromDate = Convert.ToDateTime(model.FromDate),
                ToDate = Convert.ToDateTime(model.ToDate),
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
            };

            return await this.unitOfWork.DoctorAppointmentNotices.InsertAsync(doctorAppointmentNotice);
        }

        public async Task<int> UpdateAsync(DoctorAppointmentNoticeModel model)
        {
            var checkIf = await this.unitOfWork.DoctorAppointmentNotices.FindAllAsync(m => m.ProviderId == model.ProviderId && m.DoctorAppointmentNoticeId != model.DoctorAppointmentNoticeId && m.LocationId == model.LocationId
                                && m.FromDate >= Convert.ToDateTime(model.FromDate) && m.ToDate <= Convert.ToDateTime(model.ToDate));

            if (checkIf.AsList().Count > 0)
            {
                return -1;
            }

            var doctorAppointmentNotices = await this.unitOfWork.DoctorAppointmentNotices.FindAsync(m => m.DoctorAppointmentNoticeId == model.DoctorAppointmentNoticeId);
            doctorAppointmentNotices.Description = model.Description;
            doctorAppointmentNotices.ProviderId = (int)model.ProviderId;
            doctorAppointmentNotices.LocationId = model.LocationId;
            doctorAppointmentNotices.FromDate = Convert.ToDateTime(model.FromDate);
            doctorAppointmentNotices.ToDate = Convert.ToDateTime(model.ToDate);
            doctorAppointmentNotices.Active = true;
            doctorAppointmentNotices.ModifiedBy = model.ModifiedBy;
            doctorAppointmentNotices.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.DoctorAppointmentNotices.UpdateAsync(doctorAppointmentNotices);
        }
    }
}
