using Dapper;
using Hims.Domain.Configurations;
using Hims.Domain.Entities;
using Hims.Domain.Repositories.UnitOfWork;
using Hims.Domain.Services;
using Hims.Shared.EntityModels;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Hims.Infrastructure.Services
{



    /// <inheritdoc />

    public class ReferralDoctorService : IReferralDoctorService
    {
        /// <summary>
        /// the unit of work.
        /// </summary>

        private readonly IUnitOfWork unitOfWork;


        /// <inheritdoc cref="IReferralDoctorService" />


        public ReferralDoctorService(IUnitOfWork unitOfWork)
        {
            this.unitOfWork = unitOfWork;
        }

        /// <inheritdoc />
        public async Task<int> AddAsync(ReferralDoctorModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var fullName = model.FirstName + " " + model.LastName;
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ReferralDoctorId"") FROM ""ReferralDoctor"" WHERE TRIM(UPPER(""FullName"")) = '{fullName.ToUpper().Trim()}'");
            if (checkIf > 0)
            {
                return -1;
            }
            var checkMobile = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ReferralDoctorId"") FROM ""ReferralDoctor"" WHERE ""Mobile"" = '{model.Mobile}'");
            if (checkMobile > 0)
            {
                return -2;
            }

            var referralDoctor = new ReferralDoctor
            {
                ReferralDoctorId = model.ReferralDoctorId,
                Salutation = model.Salutation,
                FirstName = model.FirstName,
                LastName = model.LastName,
                FullName= fullName,
                Mobile = model.Mobile,
                Email = model.Email,
                Active = true,
                LocationId = model.LocationId,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,

            };

            var referralDoctorId = await this.unitOfWork.ReferralDoctor.InsertAsync(referralDoctor, transaction);
            if (referralDoctorId <= 0)
            {
                transaction.Rollback();
                return 0;
            }
            transaction.Commit();
            return referralDoctorId;
        }

        /// <inheritdoc />
        public Task<IEnumerable<ReferralDoctorModel>> FetchAsync(ReferralDoctorModel model)
        {
            var where = $@" 1=1 ";
            if(model.LocationId!=null)
            {
                where += $@" and L.""LocationId""={model.LocationId} ";
            }
            //var query = $@"Select * from ""ReferralDoctor"" where  {where} order by ""CreatedDate"" desc";
            var query = $@"select RD.* , L.""Name"" as ""LocationName"",A.""FullName"" as ""CreatedByName"",B.""FullName"" as ""ModifiedByName""  from ""ReferralDoctor"" RD 
join ""Account"" A on A.""AccountId""=RD.""CreatedBy"" 
left join ""Account"" B on B.""AccountId""=RD.""ModifiedBy""
join ""Location"" L on L.""LocationId""=RD.""LocationId"" where {where} order by ""CreatedDate"" desc";

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

        /// <inheritdoc />
        public async Task<int> UpdateAsync(ReferralDoctorModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();

            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ReferralDoctorId"") FROM ""ReferralDoctor"" WHERE TRIM(UPPER(""FirstName"")) = '{model.FirstName.ToUpper().Trim()}' and TRIM(UPPER(""LastName"")) = '{model.LastName.ToUpper().Trim()}' AND ""ReferralDoctorId"" <> {model.ReferralDoctorId}");
            if (checkIf > 0)
            {
                return -1;
            }
            var checkMobile = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ReferralDoctorId"") FROM ""ReferralDoctor"" WHERE ""Mobile"" = '{model.Mobile}' AND ""ReferralDoctorId"" <> {model.ReferralDoctorId}");
            if (checkMobile > 0)
            {
                return -2;
            }
            var referralDoctor = await this.unitOfWork.ReferralDoctor.FindAsync(m => m.ReferralDoctorId == model.ReferralDoctorId);
            referralDoctor.Salutation = model.Salutation;
            referralDoctor.FirstName = model.FirstName;
            referralDoctor.LastName = model.LastName;
            referralDoctor.FullName = model.FirstName +" "+ model.LastName;
            referralDoctor.Mobile = model.Mobile;
            referralDoctor.Email = model.Email;
            referralDoctor.ModifiedBy = model.ModifiedBy;
            referralDoctor.ModifiedDate = DateTime.Now;
            var updateResponse = await this.unitOfWork.ReferralDoctor.UpdateAsync(referralDoctor, transaction);

            if (updateResponse <= 0)
            {
                transaction.Rollback();
                return 0;
            }
            transaction.Commit();
            return updateResponse;
        }

        /// <inheritdoc />
        public Task<int> ModifyStatusAsync(int referralDoctorId, int modifiedBy, bool status)
        {
            var query = $@"UPDATE ""ReferralDoctor"" SET ""Active"" = {!status}, ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""ReferralDoctorId""= {referralDoctorId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<string> FindNameByReferralDoctorId(int referralDoctorId)
        {
            var query = $@"SELECT ""FullName"" FROM ""ReferralDoctor""  WHERE ""ReferralDoctorId"" = {referralDoctorId} ";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
            return response;
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int referralDoctorId)
        {
            var query = $@"DELETE FROM ""ReferralDoctor"" WHERE ""ReferralDoctorId""= {referralDoctorId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }
    }
}
