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

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

        /// <inheritdoc cref="IDemandBookService" />
        public DemandBookService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <summary>
        /// The add async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task<int> AddAsync(InsertModel model)
        {
            var demandBook = new DemandBook
            {
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                PatientId = model.PatientId,
                ProductName = model.ProductName,
                RequiredQty = model.RequiredQty,
                PharmacyProductId = model.PharmacyProductId,
                LocationId = (int)model.LocationId
            };
            return await this.unitOfWork.DemandBooks.InsertAsync(demandBook);
        }

        /// <summary>
        /// The add async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task<IEnumerable<ViewModel>> FetchAsync(ViewModel model)
        {
            var where = "where 1=1";
            if (model.FromDate != null)
            {
                where += $@" and d.""CreatedDate""::date >= '{model.FromDate?.ToString("yyyy-MM-dd")}' ";
            }

            if (model.ToDate != null)
            {
                where += $@" and d.""CreatedDate""::date <= '{model.ToDate?.ToString("yyyy-MM-dd")}' ";
            }
            if (model.AccountId != null)
            {
                where += $@" and d.""CreatedBy"" = '{model.AccountId}'";
            }
            if (model.ProductName != null)
            {
                where += $@" and d.""ProductName"" = '{model.ProductName}'";
            }
            if (model.LocationId != null)
            {
                where += $@" and d.""LocationId"" = {model.LocationId} ";
            }

            var query = $@"select count(d.*) over() as ""TotalItems"", d.""DemandBookId"",d.""PharmacyProductId"",d.""ProductName"",pp.""GenericName"",d.""RequiredQty"",d.""ModifiedDate"",d.""CreatedDate"",CA.""FullName"" as ""CreatedByName"",M.""FullName"" as ""ModifiedByName"",P.""FullName"",P.""UMRNo"",P.""Mobile"" from ""DemandBook"" d
                         left Join ""Account"" CA ON CA.""AccountId"" = d.""CreatedBy""
                            left join ""Account"" M on M.""AccountId"" = d.""ModifiedBy"" 
							left join ""PharmacyProduct"" pp on pp.""PharmacyProductId"" = d.""PharmacyProductId""
                         left join ""Patient"" p on p.""PatientId"" = d.""PatientId"" {where}  order by d.""CreatedDate"" desc";

            if (model.PageIndex != 0 && model.PageSize != 0)
            {
                model.PageIndex -= 1;
                query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            }
            return await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
        }

        /// <summary>
        /// The update async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task<int> UpdateDemandRecord(ViewModel model)
        {
            var demand =
                await this.unitOfWork.DemandBooks.FindAsync(m => m.DemandBookId == model.DemandBookId);
            demand.ProductName = model.ProductName;
            demand.RequiredQty = model.RequiredQty;
            demand.ModifiedBy = model.ModifiedBy;
            demand.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.DemandBooks.UpdateAsync(demand);
        }
    }
}