

namespace Hims.Infrastructure.Services
{
    using Dapper;
    using Domain.Services;
    using Hims.Domain.Configurations;
    using Hims.Domain.Entities;
    using Hims.Domain.Helpers;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Shared.UserModels;
    using System;
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Transactions;

    internal class DoctorUnitService : IDoctorUnitService
    {
        /// <summary>
        /// the unit of work
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

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

        public async Task<int> ActivateOrDeactivateTest(DoctorUnitMasterModel model)
        {
            var query = $@"UPDATE ""DoctorUnitMaster""
	                           SET ""ModifiedBy""={model.ModifiedBy}, ""ModifiedDate""=now(), ""Active""= {model.Active}
	                           WHERE ""DoctorUnitMasterId""= {model.DoctorUnitMasterId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<IEnumerable<DoctorUnitMasterModel>> FetchAllAsync(DoctorUnitMasterModel model)
        {
            var where = "where 1=1";
            if (model.Active != null)
            {
                where += (bool)model.Active ? $@" and DM.""Active"" is true " : $@" and DM.""Active"" is false ";
            }
            if (model.LocationId != null)
            {
                where += $@" and DM.""LocationId"" = {model.LocationId}";
            }
            if (!string.IsNullOrEmpty(model.UnitName))
            {
                where += $@" and DM.""UnitName"" ilike '%{model.UnitName}%' ";
            }
            if (!string.IsNullOrEmpty(model.Code))
            {
                where += $@" and DM.""Code"" ilike '%{model.Code}%' ";
            }
            if (!string.IsNullOrEmpty(model.Term))
            {
                where += $@" and DM.""UnitName"" ilike '%{model.Term}%' or DM.""Code"" ilike '%{model.Term}%'";
            }
            if (model.DoctorUnitMasterId != null)
            {
                where += $@" and DM.""DoctorUnitMasterId"" = {model.DoctorUnitMasterId} ";
            }
            var query = $@"select COUNT(*) OVER () AS ""TotalItems"", DM.""DoctorUnitMasterId"", DM.""UnitName"", DM.""Code"", DM.""CreatedDate"", DM.""ModifiedDate"", L.""Name"" as ""Location"",L.""LocationId"",
                         AC.""FullName"" as ""CreatedByName"", AN.""FullName"" as ""ModifiedByName"", DM.""Active""
                        from ""DoctorUnitMaster"" DM
                        left join ""Location"" L ON L.""LocationId""=DM.""LocationId""                        
                        left join ""Account"" AC ON AC.""AccountId""=DM.""CreatedBy""
                        left join ""Account"" AN ON AN.""AccountId""=DM.""ModifiedBy"" {where} order by DM.""CreatedDate"" DESC";
            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }
            var records=  await this.unitOfWork.Current.QueryAsync<DoctorUnitMasterModel>(query);
            foreach (var item in records)
            {
                var subQuery = $@"SELECT TD.""TagDoctorId"",TD.""ProviderId"",TD.""Designation"",TD.""DoctorUnitMasterId"", Pr.""FullName"" as ""ProviderName""
                                FROM ""TagDoctor"" TD
                                JOIN ""Provider"" Pr ON Pr.""ProviderId""=TD.""ProviderId""
                                where ""DoctorUnitMasterId"" = {item.DoctorUnitMasterId} order by 1 asc";
                item.TagDoctor = (await this.unitOfWork.Current.QueryAsync<TagDoctorModel>(subQuery)).ToList();

            }
            return records;
        }

        public async Task<int> InsertAsync(DoctorUnitMasterModel model)
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {
                var check = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"select count (""DoctorUnitMasterId"") from  ""DoctorUnitMaster"" where ""UnitName""='{model.UnitName}'");
                if (check > 0)
                {
                    return -1;
                }

                    var doctorUnitMaster = new DoctorUnitMaster
                    {
                        UnitName = model.UnitName,
                        Code = model.Code,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = model.LocationId,
                        Active = model.Active,
                    };
                    doctorUnitMaster.DoctorUnitMasterId = await this.unitOfWork.DoctorUnitMatser.InsertAsync(doctorUnitMaster, transaction);
                    if (doctorUnitMaster.DoctorUnitMasterId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                    var count = 0;
                    foreach (TagDoctorModel eachTagDoctor in model.TagDoctor)
                    {
                        var tagDotctor = new TagDoctor
                        {
                            ProviderId = eachTagDoctor.ProviderId,
                            Designation = eachTagDoctor.Designation,
                            DoctorUnitMasterId = doctorUnitMaster.DoctorUnitMasterId,
                        };
                        var response = await this.unitOfWork.TagDoctor.InsertAsync(tagDotctor, transaction);
                        if (response != 0)
                        {
                            count++;
                        }
                    }
                    if (count != model.TagDoctor.Count)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                    transaction.Commit();
                return doctorUnitMaster.DoctorUnitMasterId;
            }

               
        }

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

                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"select count(*) from ""DoctorUnitMaster"" where  lower (""UnitName"") = '{model.UnitName.ToLower()}' and ""DoctorUnitMasterId"" <> {model.DoctorUnitMasterId}");
                if (checkIf > 0)
                {
                    return -1;
                }
                var record = await this.unitOfWork.DoctorUnitMatser.FindAsync(m => m.DoctorUnitMasterId == model.DoctorUnitMasterId);
                if (record == null)
                {
                    return -2;
                }
                record.ModifiedBy = model.CreatedBy;
                record.ModifiedDate = DateTime.Now;
                record.UnitName = model.UnitName;
                record.Code = model.Code;
                //record.DepartmentId = model.DepartmentId;
                record.LocationId = model.LocationId;
                var num= await this.unitOfWork.DoctorUnitMatser.UpdateAsync(record);
                foreach (TagDoctorModel eachTagDoctor in model.TagDoctor)
                {
                    
                        var tagDotctor = new TagDoctor
                        {
                        ProviderId = eachTagDoctor.ProviderId,
                        Designation = eachTagDoctor.Designation,
                        DoctorUnitMasterId = record.DoctorUnitMasterId,
                        };
                        if (eachTagDoctor.TagDoctorId != 0)
                        {
                               var response = await this.unitOfWork.TagDoctor.UpdateAsync(tagDotctor);
                        }
                        else
                        {
                            var response = await this.unitOfWork.TagDoctor.InsertAsync(tagDotctor);

                        }
                }
            return num;
        }
    }
}
