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

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

        public ProgressReportDietService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        public async Task<IEnumerable<ViewModel>> FetchAsync(FilterModel model)
        {
            var query = $@"select PD.""ProgressReportDietId"",
                                    PD.""DietInstructions"",
                                    PD.""ProgressReportId"",
                                    PD.""MealTypeId"",
                                    PD.""StartDate"",
                                    PD.""EndDate"",
                                    PD.""CreatedBy"",
                                    PD.""StopReason"",
                                    PD.""ModifiedBy"",
                                    PD.""Active"",
                                    PD.""ModifiedDate"",
                                    PD.""CreatedDate"",
                                    c.""FullName"" ""CreatedByName"",
                                    m.""FullName"" ""ModifiedByName"",
                                    MT.""MealType"",
                                    MT.""MealInstruction""
                                   from ""ProgressReportDiet"" PD
                                JOIN ""ProgressReport"" r ON r.""ProgressReportId"" = PD.""ProgressReportId""
	                            JOIN ""Account"" c on c.""AccountId"" = PD.""CreatedBy""
	                            LEFT JOIN ""Account"" m on m.""AccountId"" = PD.""ModifiedBy""
                                join ""MealTypes"" MT on MT.""MealTypeId"" =  PD.""MealTypeId""   
                                WHERE r.""AdmissionId"" = {model.AdmissionId}";
            var response = await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
            return response;
        }

        public async Task<int> InsertAsync(InsertModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            try
            {
                var progressReport = await this.unitOfWork.ProgressReport.FindAsync(x => x.AdmissionId == model.AdmissionId, transaction);
                var progressReportId = progressReport?.ProgressReportId ?? await this.unitOfWork.ProgressReport.InsertAsync(new ProgressReport
                {
                    AdmissionId = model.AdmissionId,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now
                }, transaction);

                foreach (var record in model.Records)
                {
                    var diet = new ProgressReportDiet
                    {
                        Active = true,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        ProgressReportId = progressReportId,
                        Duration = record.Duration,
                        MedicationDurationTypeId = record.MedicationDurationTypeId,
                        StartDate = record.StartDate,
                        EndDate = record.EndDate,
                        MealTypeId = record.MealTypeId,
                        DietInstructions = record.DietInstructions,
                        IsMorning = record.IsMorning,
                        IsAfternoon = record.IsAfternoon,
                        IsNight = record.IsNight
                    };

                    var responseId = await this.unitOfWork.ProgressReportDiets.InsertAsync(diet, transaction);

                    if (responseId <= 0)
                    {
                        transaction.Rollback();
                        return -1;
                    }
                }

                transaction.Commit();
                return 1;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                return -1;
            }
        }

        public async Task<int> StopDietAsync(StopModel model)
        {
            var diet = await this.unitOfWork.ProgressReportDiets.FindAsync(x => x.ProgressReportDietId == model.Id);

            if (diet == null)
            {
                return -1;
            }
            diet.Active = false;
            diet.StopDate = DateTime.Now;
            diet.StopReason = model.StopReason;
            diet.ModifiedBy = model.By;
            diet.ModifiedDate = DateTime.Now;
            var response = await this.unitOfWork.ProgressReportDiets.UpdateAsync(diet);
            return response;

        }
    }
}