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.Entities;

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

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

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

        public async Task<IEnumerable<ScanAppointmentNoticeModel>> FetchAsync(ScanAppointmentNoticeModel model)
        {
            var where = " WHERE 1 = 1 ";
            //if (model.Active != null)
            //{
            //    where += $@" AND sa.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            //}
            if (!string.IsNullOrEmpty(model.FromDate) && (!string.IsNullOrEmpty(model.ToDate)))
            {
                where += $@" And (sa.""FromDate""::Date between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or    sa.""ToDate""::Date   between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or sa.""FromDate""::Date   between '{model.FromDate}'::DATE and '{model.ToDate}'::DATE
                        or '{model.FromDate}'::DATE >= sa.""FromDate""::Date  and '{model.ToDate}'::DATE <= sa.""ToDate""::Date)";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  sa.""LocationId"" = {model.LocationId} ";
            }
            if (model.MachineId > 0)
            {
                where += $@" and  sm.""ScanMachineMasterId"" = {model.MachineId} ";
            }
            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", sa.*,sm.""MachineName"", L.""Name"" ""LocationName""
	                                FROM ""ScanAppointmentNotice"" sa
	                                LEFT JOIN ""ScanMachineMaster"" sm on sm.""ScanMachineMasterId"" = sa.""MachineId""
	                                LEFT JOIN ""Location"" L on L.""LocationId"" = sa.""LocationId""
                                {where} Order by sa.""ScanAppointmentNoticeId"" DESC";
            if (model.PageIndex <= 0 || model.PageIndex == null)
            {
                return await this.unitOfWork.Current.QueryAsync<ScanAppointmentNoticeModel>(query);
            }
            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return await this.unitOfWork.Current.QueryAsync<ScanAppointmentNoticeModel>(query);
        }

        public async Task<int> InsertAsync(ScanAppointmentNoticeModel model)
        {
            var checkIf = await this.unitOfWork.ScanAppointmentNotices.FindAllAsync(m => m.MachineId == model.MachineId && m.LocationId == model.LocationId
                                       && m.FromDate >= Convert.ToDateTime(model.FromDate) && m.ToDate <= Convert.ToDateTime(model.ToDate));
            if (checkIf.AsList().Count > 0)
            {
                return -1;
            }
            var scanAppointmentNotice = new ScanAppointmentNotice
            {
                Description = model.Description,
                LocationId = model.LocationId,
                MachineId = (int)model.MachineId,
                FromDate = Convert.ToDateTime(model.FromDate),
                ToDate = Convert.ToDateTime(model.ToDate),
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                Availability = model.Availability,
                AvailableDays = model.AvailableDays
            };

            return await this.unitOfWork.ScanAppointmentNotices.InsertAsync(scanAppointmentNotice);
        }

        public async Task<int> UpdateAsync(ScanAppointmentNoticeModel model)
        {
            var checkIf = await this.unitOfWork.ScanAppointmentNotices.FindAllAsync(m => m.MachineId == model.MachineId && m.ScanAppointmentNoticeId != model.ScanAppointmentNoticeId && m.LocationId == model.LocationId
                                && m.FromDate >= Convert.ToDateTime(model.FromDate) && m.ToDate <= Convert.ToDateTime(model.ToDate));
            if (checkIf.AsList().Count > 0)
            {
                return -1;
            }

            var scanAppointmentNotices = await this.unitOfWork.ScanAppointmentNotices.FindAsync(m => m.ScanAppointmentNoticeId == model.ScanAppointmentNoticeId);
            scanAppointmentNotices.Description = model.Description;
            scanAppointmentNotices.MachineId = (int)model.MachineId;
            scanAppointmentNotices.LocationId = model.LocationId;
            scanAppointmentNotices.FromDate = Convert.ToDateTime(model.FromDate);
            scanAppointmentNotices.ToDate = Convert.ToDateTime(model.ToDate);
            scanAppointmentNotices.Active = true;
            scanAppointmentNotices.ModifiedBy = model.ModifiedBy;
            scanAppointmentNotices.ModifiedDate = DateTime.Now;
            scanAppointmentNotices.Availability = model.Availability;
            scanAppointmentNotices.AvailableDays = model.AvailableDays;
            return await this.unitOfWork.ScanAppointmentNotices.UpdateAsync(scanAppointmentNotices);
        }
    }
}
