using Hims.Domain.Repositories.UnitOfWork;
using Hims.Domain.Services;
using Hims.Shared.UserModels;
using Hims.Shared.UserModels.Filters;
using System;
using Hims.Domain.Entities;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using Hims.Shared.UserModels.BedManagement.Floor;
using Hims.Shared.Library;
using System.Collections;
using Hims.Shared.EntityModels;

namespace Hims.Infrastructure.Services
{

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

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


        /// <inheritdoc/>
        public async Task<int> AddTpa(TpaModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""TpaId"") FROM ""Tpa"" WHERE  Lower(""Name"") = '{model.Name.ToLower()}'");
            if (checkIf > 0)
            {
                return -2;
            }
            var tpa = new Tpa();
            tpa.Name = model.Name;
            tpa.CreatedBy = model.CreatedBy;
            tpa.CreatedDate = DateTime.Now;
            tpa.Active = true;

             var result = await this.unitOfWork.Tpa.InsertAsync(tpa);
            if (result >= 1)
            {
                return result;
            }
            else
            {
                return -1;
            }
        }

        /// <inheritdoc/>
        public async Task<int> ChangeStatus(TpaModel model)
        {
            var OldTpa = await this.unitOfWork.Tpa.FindAsync(l => l.TpaId == model.TpaId);
            OldTpa.Active = (bool)!model.Active;
            Tpa tpa = new Tpa();
            tpa.TpaId = (int)model.TpaId;
            tpa.Name = model.Name;
            tpa.Active = (bool) !model.Active;
            tpa.ModifiedBy = model.ModifiedBy;
            tpa.ModifiedDate = DateTime.Now;

            var result = await this.unitOfWork.Tpa.UpdateAsync(tpa);

            if (result >= 1)
            {
                return result;
            }
            else
            {
                return -1;
            }
        }

        /// <inheritdoc/>
        public Task<IEnumerable<TpaModel>> GetAllTpa(TpaModel model)
        {
            string where = "where 1=1 ";

            if (!string.IsNullOrEmpty(model.Name))
            {
                where += $@" and lower(t.""Name"") ilike '%{model.Name.ToLower()}%' ";
            }
            
            if (model.Active != null)
            {
                where += $@" and t.""Active"" = {model.Active}";
            }
            var Query = $@"	 select count(*) over () as ""TotalItems"", t.""TpaId"",t.""Name"",t.""Active"",A.""FullName"" as ""CreatedByName"",
			   t.""CreatedDate"", B.""FullName"" as ""ModifiedByName"",t.""CreatedBy"",t.""ModifiedBy"" , t.""ModifiedDate""
			   from  ""Tpa"" t
			   join ""Account"" A  on A.""AccountId"" = t.""CreatedBy""
			   left join ""Account"" B on B.""AccountId"" = t.""ModifiedBy"" {where}";

            if (model.PageSize != null && model.PageIndex != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                Query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }
            return this.unitOfWork.Current.QueryAsync<TpaModel>(Query);
        }

        /// <inheritdoc/>
        public async Task<int> UpdateTpa(TpaModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""TpaId"") FROM ""Tpa"" WHERE  Lower(""Name"") = '{model.Name.ToLower()}'");
            if (checkIf > 0)
            {
                return -2;
            }

            Tpa tpa = new Tpa();
            tpa.TpaId = (int)model.TpaId;
            tpa.Name = model.Name;
            tpa.Active = (bool)model.Active;
            tpa.ModifiedBy = model.ModifiedBy;
            tpa.ModifiedDate = DateTime.Now;

            var result = await this.unitOfWork.Tpa.UpdateAsync(tpa);

            if (result >= 1)
            {
                return result;
            }
            else
            {
                return -1;
            }

        }
    }
}
