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.UserModels.DoctorScheduleVisits;

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

        /// <inheritdoc cref="IDoctorScheduleVisitsService" />
        public DoctorScheduleVisitsService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public async Task<IEnumerable<ViewModel>> FetchAsync(FilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.LocationId != null)
            {
                where += $@" AND PAS.""LocationId"" = {model.LocationId}";
            }
            if ((model.ProviderId != 0) && (model.ProviderId != null))
            {
                where += $@" AND PAS.""ProviderId"" = {model.ProviderId}";
            }
            if ((model.SpecializationId != 0) && (model.SpecializationId != null))
            {
                where += $@" AND PAS.""SpecializationId"" = {model.SpecializationId}";
            }
            if (model.CreatedBy != null)
            {
                where += $@" AND PAS.""CreatedBy"" = {model.CreatedBy}";
            }

            if (model.Active == true)
            {
                where += $@" AND PAS.""Active"" is true";
            }
            else
            {
                where += $@" AND PAS.""Active"" is false";

            }

            var query = $@"Select distinct COUNT(*) OVER () AS ""TotalItems"",PAS.""DoctorAvailabilityVisitTypeId"" ,PAS.""LocationId"", PAS.""Duration"",PAS.""Active"",PAS.""CreatedDate""::date,PAS.""ModifiedDate""::date, PAS.""SpecializationId"",PAS.""ProviderId""
                            ,L.""Name""as ""LocationName"",
							p.""FullName"" as ""ProviderName"",
							PAS.""CreatedBy"",ac.""FullName"" as ""CreatedByName"",PAS.""ModifiedBy"",cc.""FullName"" as ""ModifiedByName"",
				                    sp.""SpecializationName""
                                    from ""DoctorAvailabilityVisitType"" PAS
									left join ""Account"" ac on ac.""AccountId"" = PAS.""CreatedBy""
									left join ""Account"" cc on cc.""AccountId"" = PAS.""ModifiedBy""
                                    left join ""Provider"" p on p.""ProviderId"" = PAS.""ProviderId""
                                    left join ""Specialization"" sp on sp.""SpecializationId""=PAS.""SpecializationId""
                                    join ""Location"" L on L.""LocationId"" = PAS.""LocationId""
                            {where}
									group by PAS.""DoctorAvailabilityVisitTypeId"" ,PAS.""Duration"",PAS.""LocationId"", PAS.""Active"",PAS.""CreatedDate""::date,PAS.""ModifiedDate""::date,PAS.""SpecializationId"",PAS.""ProviderId"",L.""Name"",p.""FullName"",
									sp.""SpecializationName"",PAS.""CreatedBy"",ac.""FullName"",PAS.""ModifiedBy"",cc.""FullName"""

                                    ;

            if (model.PageIndex <= 0)
            {
                _ = await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);


            return await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
        }


        /// <inheritdoc />
        public async Task<int> AddAsync(InsertModel model)
        {
            try
            {
                var where = $@"where 1=1 ";
                if (model.ProviderId != null)
                {
                    where += $@" and ""ProviderId"" = {model.ProviderId}";
                }
                if (model.SpecializationId != null)
                {
                    where += $@" and ""SpecializationId"" = {model.SpecializationId}";
                }
                if (model.ProviderId == null)
                {
                    where += $@" and ""ProviderId"" is null ";
                }
                if (model.SpecializationId == null)
                {
                    where += $@" and ""SpecializationId"" is null";
                }
                if (model.LocationId != null)
                {
                    where += $@" and ""LocationId"" = {model.LocationId}";
                }
                var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(*) FROM ""DoctorAvailabilityVisitType"" {where}");
                if (checkIf > 0)
                {
                    return -1;
                }
                //var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(*) FROM ""ProviderAvailabilityVisitType"" WHERE ""ProviderId"" = {model.ProviderId} and ""SpecializationId"" = {model.SpecializationId}");
                //if (checkIf > 0)
                //{
                //    return -1;
                //}

                //Provider Availability visits

                var DoctorAvailabilityVisitType = new DoctorAvailabilityVisitType
                {
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.UtcNow,
                    Active = true,
                    Duration = model.Duration,
                    ProviderId = model.ProviderId,
                    LocationId = model.LocationId,
                    SpecializationId = model.SpecializationId,
                };
                var insertExecute = await this.unitOfWork.DoctorAvailabilityVisitType.InsertAsync(DoctorAvailabilityVisitType);


                return 1;
            }
            catch (Exception e)
            {
                e.Message.ToString();
                return -1;
            }


        }

        public async Task<int> UpdateAsync(InsertModel model)
        {

            using var transaction = this.unitOfWork.BeginTransaction();
            try
            {
                        var find = await this.unitOfWork.DoctorAvailabilityVisitType.FindAsync(d => d.DoctorAvailabilityVisitTypeId == model.DoctorAvailabilityVisitTypeId);
                        //var checkIf = await this.unitOfWork.ProviderAvailabilityVisitType.FindAsync(d => d.ProviderAvailabilityVisitTypeId == model.ProviderAvailabilityVisitTypeId);
                        var doctorAvailabilityVisitType = new DoctorAvailabilityVisitType
                        {
                            ModifiedBy = model.ModifiedBy,
                            ModifiedDate = DateTime.Now,
                            Active = true,
                            Duration = model.Duration,
                            ProviderId = find.ProviderId,
                            LocationId = find.LocationId,
                            SpecializationId = find.SpecializationId,
                            DoctorAvailabilityVisitTypeId = find.DoctorAvailabilityVisitTypeId
                        };
                        var data = await this.unitOfWork.DoctorAvailabilityVisitType.UpdateAsync(doctorAvailabilityVisitType, transaction);
                        if (data == 0)
                        {
                            transaction.Rollback();
                            return new int();
                        }

                transaction.Commit();
                return 1;
            }
            catch (Exception ex)
            {
                ex.Message.ToString();
                transaction.Rollback();
                return -1;
            }
        }

        public async Task<IEnumerable<ViewModel>> FetchDoctorChargeAsync(FilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.LocationId != null)
            {
                where += $@" AND PAS.""LocationId"" = {model.LocationId}";
            }
            if (model.ProviderId != null)
            {
                where += $@" AND PAS.""ProviderId"" = {model.ProviderId}";
            }
            if (model.SpecializationId != null)
            {
                where += $@" AND PAS.""SpecializationId"" = {model.SpecializationId}";
            }
            var query = $@"Select distinct COUNT(*) OVER () AS ""TotalItems"",PAS.""PartsOfDayId"",PAS.""StartDate""::date,PAS.""EndDate""::date,PAS.""ProviderAvailabilityChargeTypeId"", PAS.""SpecializationId"",PAS.""ProviderId"",PAS.""Charge"",PAS.""Charge"" as ""Value"",PAS.""ChargeTypesId"",PAS.""ChargeTypesId"" as ""Id"",
                            ct.""ChargeName"",ct.""ChargeName"" as ""Name"",L.""Name""as ""LocationName"",
							p.""FullName"" as ""ProviderName"",
							PAS.""CreatedBy"",ac.""FullName"" as ""CreatedByName"",PAS.""ModifiedBy"",cc.""FullName"" as ""ModifiedByName"",
				                    sp.""SpecializationName""
                                    from ""ProviderAvailabilityChargeType"" PAS
									left join ""Account"" ac on ac.""AccountId"" = PAS.""CreatedBy""
									left join ""Account"" cc on cc.""AccountId"" = PAS.""ModifiedBy""
                                    left join ""Provider"" p on p.""ProviderId"" = PAS.""ProviderId""
                                    left join ""ChargeTypes"" ct on ct.""ChargeTypesId""= PAS.""ChargeTypesId""
                                    join ""Specialization"" sp on sp.""SpecializationId""=PAS.""SpecializationId""
                                    join ""Location"" L on L.""LocationId"" = PAS.""LocationId""
                                    {where}
									group by PAS.""ProviderAvailabilityChargeTypeId"",PAS.""SpecializationId"",PAS.""ProviderId"",PAS.""Charge"",PAS.""ChargeTypesId"",ct.""ChargeName"",L.""Name"",p.""FullName"",
									sp.""SpecializationName"",PAS.""CreatedBy"",ac.""FullName"",PAS.""ModifiedBy"",cc.""FullName""";
            return await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
        }

        public async Task<IEnumerable<ViewModel>> FetchDoctorVisitsAsync(FilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.LocationId != null)
            {
                where += $@" AND PAS.""LocationId"" = {model.LocationId}";
            }
            if (model.ProviderId != null)
            {
                where += $@" AND PAS.""ProviderId"" = {model.ProviderId}";
            }
            if (model.SpecializationId != null)
            {
                where += $@" AND PAS.""SpecializationId"" = {model.SpecializationId}";
            }
            if (model.LocationId != null)
            {
                where += $@" AND PAS.""LocationId"" = {model.LocationId}";
            }
            if (model.ProviderId == null)
            {
                where += $@" and PAS.""ProviderId"" is null ";
            }
            if (model.SpecializationId == null)
            {
                where += $@" and PAS.""SpecializationId"" is null";
            }
            var query = $@"Select distinct COUNT(*) OVER () AS ""TotalItems"",PAS.""LocationId"",PAS.""ProviderAvailabilityVisitTypeId"",PAS.""Active"", PAS.""SpecializationId"",PAS.""ProviderId"",PAS.""Duration"",PAS.""Duration"" as ""Value"",PAS.""VisitTypeId"",PAS.""VisitTypeId"" as ""Id"",
                            ct.""VisitorName"" as ""VisitName"",ct.""VisitorName"" as ""Name"",L.""Name""as ""LocationName"",
							p.""FullName"" as ""ProviderName"",
							PAS.""CreatedBy"",ac.""FullName"" as ""CreatedByName"",PAS.""ModifiedBy"",cc.""FullName"" as ""ModifiedByName"",
				                    sp.""SpecializationName""
                                    from ""ProviderAvailabilityVisitType"" PAS
									left join ""Account"" ac on ac.""AccountId"" = PAS.""CreatedBy""
									left join ""Account"" cc on cc.""AccountId"" = PAS.""ModifiedBy""
                                    left join ""Provider"" p on p.""ProviderId"" = PAS.""ProviderId""
                                    left join ""VisitType"" ct on ct.""VisitTypeId""= PAS.""VisitTypeId""
                                    left join ""Specialization"" sp on sp.""SpecializationId""=PAS.""SpecializationId""
                                    join ""Location"" L on L.""LocationId"" = PAS.""LocationId""
                                    {where}
									group by PAS.""ProviderAvailabilityVisitTypeId"",PAS.""Active"",PAS.""SpecializationId"",PAS.""ProviderId"",PAS.""Duration"",PAS.""VisitTypeId"",ct.""VisitorName"",L.""Name"",p.""FullName"",
									sp.""SpecializationName"",PAS.""CreatedBy"",ac.""FullName"",PAS.""ModifiedBy"",cc.""FullName""";
            return await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
        }


        public async Task<int> ModifyStatusAsync(InsertModel model)
        {
            try
            {

                var query = $@"UPDATE ""DoctorAvailabilityVisitType"" SET ""Active"" = {model.Active}, ""ModifiedBy""  = {model.ModifiedBy} , ""ModifiedDate"" = '{DateTime.Now}' WHERE ""DoctorAvailabilityVisitTypeId"" in ({model.DoctorAvailabilityVisitTypeId})";

                var num = await this.unitOfWork.Current.QueryAsync<int>(query);

                return 1;
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }

            return -1;

        }
    }
}