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

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

        /// <summary>
        /// The amazon s 3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration amazonS3Configuration;

        /// <inheritdoc cref="IProviderDocumentService" />
        public ProviderDocumentServices(IUnitOfWork unitOfWork, IAmazonS3Configuration amazonS3Configuration)
        {
            this.unitOfWork = unitOfWork;
            this.amazonS3Configuration = amazonS3Configuration;
        }

        /// <inheritdoc />
        public Task<IEnumerable<ProviderDocumentModel>> FetchAsync(ProviderDocumentFilterModel model)
        {
            var where = string.Empty;

            if (model.ProviderId != 0)
            {
                 where = $@" WHERE prd.""Active"" IS TRUE AND prd.""ProviderId"" = {model.ProviderId}";
            }

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"",prd.*,prv.""FullName"" as ""ProviderName"",prd.""IsRead"", prd.""ProviderDocumentId"",
                                (CASE WHEN prd.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', prv.""Guid"", '/', prd.""ThumbnailUrl"") ELSE NULL END) AS ""ThumbnailUrl"",
                                (CASE WHEN prd.""DocumentUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', prv.""Guid"", '/', prd.""DocumentUrl"") ELSE NULL END) AS ""DocumentUrl""
                                FROM ""ProviderDocument"" prd
                                JOIN ""Provider"" prv ON prv.""ProviderId"" = prd.""ProviderId"" AND prv.""Active"" IS TRUE
                                {where} ORDER BY prd.""ProviderDocumentId"" DESC";

            if (model.PageIndex <= 0)
            {
                return this.unitOfWork.Current.QueryAsync<ProviderDocumentModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);

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

        /// <inheritdoc />
        public Task<int> AddAsync(ProviderDocumentModel model)
        {
            var providerDocument = new ProviderDocument
            {
                Active = true,
                ProviderId = model.ProviderId,
                DocumentName = model.DocumentName,
                DocumentType = model.DocumentType,
                Description = model.Description,
                DocumentUrl = model.DocumentUrl,
                ThumbnailUrl = model.ThumbnailUrl,
                UploadedDate = DateTime.UtcNow
            };

            return this.unitOfWork.ProviderDocuments.InsertAsync(providerDocument);
        }

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

        /// <inheritdoc />
        public Task<int> ModifyStatusAsync(ModifyProviderDocumentModel model)
        {
            var query = $@"UPDATE ""ProviderDocument"" SET ""Active"" = {model.Status}, ""ModifiedBy"" = {model.ModifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""ProviderDocumentId""= {model.ProviderDocumentId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(ProviderDocumentModel model)
        {
            var providerDocument = await this.unitOfWork.ProviderDocuments.FindAsync(m => m.ProviderDocumentId == model.ProviderDocumentId);
            providerDocument.DocumentName = model.DocumentName;
            providerDocument.DocumentType = model.DocumentType;
            providerDocument.Description = model.Description;
            providerDocument.ModifiedBy = model.ModifiedBy;
            providerDocument.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.ProviderDocuments.UpdateAsync(providerDocument);
        }

        /// <inheritdoc />
        public Task<int> ModifyReadAsync(ModifyProviderDocumentModel model)
        {
            var query = $@"UPDATE ""ProviderDocument"" SET ""IsRead"" = true, ""ModifiedBy"" = {model.ModifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""ProviderDocumentId""= {model.ProviderDocumentId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }
    }
}