using System.Linq;

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.Domain.Configurations;
    using Shared.EntityModels;
    using Shared.UserModels.Filters;

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

        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;

        /// <inheritdoc cref="ISettingService" />
        public SettingServices(IUnitOfWork unitOfWork, IRunningEnvironment runningEnvironment) // => this.unitOfWork = unitOfWork;
        {
            this.unitOfWork = unitOfWork;
            this.runningEnvironment = runningEnvironment;
        }     
        public async Task<bool> CheckSmsEnabled()
        {
            var query = $@"SELECT * FROM ""Settings"" where ""Name"" =  'Appointment Booked SMS'";
            var response = unitOfWork.Current.Query<SettingModel>(query).ToList();
            if (response[0].Active == false)
            {
                return false;
            }


            return true;
        }
        public async Task<bool> CheckEmailEnabled()
        {
            var query = $@"SELECT * FROM ""Settings"" where ""Name"" =  'Email'";
            var response = unitOfWork.Current.Query<SettingModel>(query).ToList();
            if (response[0].Active == false)
            {
                return false;
            }


            return true;
        }
        /// <inheritdoc />
        public async Task<int> AppointmentSettingAsync(PrintSettingModel model)
        {

            var isAppointment = "";

            if (model.IsAppointment == false || model.IsAppointment == null)
            {
                isAppointment = $@"Update ""CommonSetting"" set ""IsAppointment"" = true where ""IsAppointment"" = {model.IsAppointment}";
            }
            else
            {
                isAppointment = $@"Update ""CommonSetting"" set ""IsAppointment"" = false where ""IsAppointment"" = {model.IsAppointment}";
            }
            return await this.unitOfWork.Current.ExecuteAsync(isAppointment);
        }

        ///<inheritdoc/>
        public async Task<int> InsertAsync(SettingModel model)
        {
            var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"SELECT COUNT(""SettingsId"") FROM ""Settings"" WHERE TRIM(UPPER(""Name"")) = '{model.Name.ToUpper().Trim()}'");
            if (checkIf > 0)
            {
                return -1;
            }
            var set = new Settings
            {
                Type = model.Type,
                Name = model.Name,
                Value = model.Value,
                Active = false,
                Description = model.Description,
                ImageUrl = model.ImageUrl
            };
            return await this.unitOfWork.Settings.InsertAsync(set);

        }

        ///<inheritdoc/>
        public async Task<int> UpdateAsync(SettingModel model)
        {
            if (model.Type == "Logo")
            {
                var findActiveLogo = await this.unitOfWork.Settings.FindAsync(m => m.Active == true && m.Type == "Logo");
                if (findActiveLogo != null)
                {
                    findActiveLogo.Active = false;
                    await this.unitOfWork.Settings.UpdateAsync(findActiveLogo);
                }
            }
            if (model.Type == "Icon")
            {
                var findActiveIcon = await this.unitOfWork.Settings.FindAsync(m => m.Active == true && m.Type == "Icon");
                if (findActiveIcon != null)
                {
                    findActiveIcon.Active = false;
                    await this.unitOfWork.Settings.UpdateAsync(findActiveIcon);
                }
            }
            if (model.Type == "Banner")
            {
                var findActiveBanner = await this.unitOfWork.Settings.FindAsync(m => m.Active == true && m.Type == "Banner");
                if (findActiveBanner != null)
                {
                    findActiveBanner.Active = false;
                    await this.unitOfWork.Settings.UpdateAsync(findActiveBanner);
                }
            }

            var set = await this.unitOfWork.Settings.FindAsync(m => m.SettingsId == model.SettingsId);
            if (set == null)
            {
                return 0;
            }
            set.Value = model.Value;
            set.Active = (bool)model.Active;
            set.Description = model.Description;
            set.Name = model.Name;
            return await this.unitOfWork.Settings.UpdateAsync(set);

        }

        ///<inheritdoc/>
        public async Task<IEnumerable<SettingModel>> FetchAsync(string name,string type, bool? active)
        {
            var where = $@" WHERE 1 = 1 ";
            if (!string.IsNullOrEmpty(name))
            {
                if (name.Contains(","))
                {
                    where += $@" AND s.""Name"" in ({name})";
                }
                else
                {
                    where += $@" AND s.""Name""='{name}'";
                }
                
            }
            if (!string.IsNullOrEmpty(type))
            {
                where += $@" AND s.""Type"" = '{type}'";
            }
            if (active != null)
            {
                where += $@" AND s.""Active"" IS {((bool)active ? "TRUE" : "FALSE")}";
            }
            var query = $@"Select s.""SettingsId"" ,s.""Type"" , s.""Name"" , s.""Value"" , s.""ImageUrl"" , s.""Description"", s.""Active"" ,
                                
                CASE WHEN ""ImageUrl"" is null THEN null ELSE CONCAT('{this.runningEnvironment.CurrentEnvironment}','/', ""ImageUrl"") END as ""ImageUrl""     
                from ""Settings"" s {where} order by ""Type"" ASC";

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

        }       
    }
}