namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Dapper;
    using Hims.Domain.Entities.EncounterTemplates;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Domain.Services;
    using Hims.Shared.UserModels.EncounterTemplates;

    /// <summary> 
    /// The enocunter template service.
    /// </summary>
    public class EncounterTemplateServices : IEncounterTemplateService
    {

        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IEncounterTemplateService"/>
        public EncounterTemplateServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc/>
        public async Task<int> InsertOrEditTemplateAsync(EncounterTemplateModel model)
        {
            var checkIfQuery = $@"select count(*) from ""TemplateHeader"" where lower(""TemplateName"") = lower('{model.TemplateName}') and ""ModulesMasterId"" = {model.ModulesMasterId} ";
            var templateHeader = new TemplateHeader
            {
                Active = true,
                CreatedBy = (int)model.CreatedBy,
                CreatedDate = DateTime.Now,
                ModulesMasterId = (int)model.ModulesMasterId,
                TemplateName = model.TemplateName,

            };

            if (model.TemplateHeaderId != null && model.TemplateHeaderId > 0)
            {
                checkIfQuery += $@" and ""TemplateHeaderId"" <> {model.TemplateHeaderId}";
                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkIfQuery);
                if (checkIf > 0)
                {
                    return -1;
                }
                var getOldOne = await this.unitOfWork.TemplateHeaders.FindAsync(t => t.TemplateHeaderId == model.TemplateHeaderId);
                getOldOne.TemplateName = model.TemplateName;
                getOldOne.ModifiedBy = templateHeader.CreatedBy;
                getOldOne.ModifiedDate = DateTime.Now;

                var updateRes = await this.unitOfWork.TemplateHeaders.UpdateAsync(getOldOne);
                if (updateRes < 0)
                {
                    return -2;
                }

                var findDet = await this.unitOfWork.TemplateDetails.FindAsync(x => x.TemplateHeaderId == model.TemplateHeaderId);
                findDet.JSONValue = model.JSONValue;
                return await this.unitOfWork.TemplateDetails.UpdateAsync(findDet);
            }
            else
            {
                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkIfQuery);
                if (checkIf > 0)
                {
                    return -1;
                }
                templateHeader.TemplateHeaderId = await this.unitOfWork.TemplateHeaders.InsertAsync(templateHeader);
                var detail = new TemplateDetail
                {
                    TemplateHeaderId = templateHeader.TemplateHeaderId,
                    JSONValue = model.JSONValue
                };

                return await this.unitOfWork.TemplateDetails.InsertAsync(detail);
            }
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<EncounterTemplateModel>> FetchTemplatesAsync(EncounterTemplateModel model)
        {
            var where = "where 1=1";
            if(model.Active != null)
            {
                where += $@" and th.""Active"" is {model.Active}";
            }

            if(model.ModulesMasterId != null)
            {
                where += $@" and th.""ModulesMasterId"" = {model.ModulesMasterId}";
            }
            if (!string.IsNullOrEmpty(model.ModuleName))
            {
                where += $@" and lower(mm.""ModuleName"") ilike '%{model.ModuleName.ToLower()}%'";
            }
                if (model.TemplateHeaderId!=null)
            {
                where += $@" and th.""TemplateHeaderId"" = {model.TemplateHeaderId}";
            }

            var query = $@"SELECT count(th.*) over() as ""TotalItems"", th.""TemplateHeaderId"", th.""ModulesMasterId"", th.""TemplateName"", th.""CreatedBy"", th.""CreatedDate"", th.""ModifiedBy"", th.""ModifiedDate"", th.""Active"" ,
	                            td.""TemplateDetailId"" ,td.""JSONValue"" , c.""FullName""  as ""CreatedByName"", m.""FullName"" as ""ModifiedByName"", mm.""ModuleName"" ,mm.""ModuleIcon"" 
	                            FROM ""TemplateHeader"" th
	                            join ""TemplateDetail"" td on td.""TemplateHeaderId"" = th.""TemplateHeaderId"" 
	                            join ""ModulesMaster"" mm ON mm.""ModulesMasterId"" = th.""ModulesMasterId"" 
	                            join ""Account"" c on c.""AccountId"" = th.""CreatedBy"" 
	                            left join ""Account"" m on m.""AccountId"" = th.""ModifiedBy"" 
                                {where}
                                order by th.""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.PageSize * model.PageIndex}";
            }

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