using AutoMapper;
using DamageAssesment.Api.Attachments.Db;
using DamageAssesment.Api.Attachments.Interfaces;
using DamageAssesment.Api.Attachments.Models;
using Microsoft.EntityFrameworkCore;
using System.Drawing;

namespace DamageAssesment.Api.Attachments.Providers
{
    public class AttachmentsProvider : IAttachmentsProvider
    {

        private AttachmentsDbContext AttachmentDbContext;
        private ILogger<AttachmentsProvider> logger;
        private IUploadService uploadservice;
        private IMapper mapper; 
        private readonly IHttpContextAccessor httpContextAccessor;
        private string baseUrl;
        public AttachmentsProvider(AttachmentsDbContext AttachmentDbContext, ILogger<AttachmentsProvider> logger, IMapper mapper,IUploadService uploadservice, IHttpContextAccessor httpContextAccessor)
        {
            this.AttachmentDbContext = AttachmentDbContext;
            this.logger = logger;
            this.mapper = mapper;
            this.uploadservice = uploadservice;
            this.httpContextAccessor = httpContextAccessor;
            baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}";
            baseUrl = baseUrl + "/attachments/download";
           // SeedData();
        }
        public async Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> GetAttachmentsAsync()
        {
            
            try
            {
                logger?.LogInformation("Query Question");
                var Attachment = await AttachmentDbContext.Attachments.AsNoTracking().Where(a => !a.IsDeleted).ToListAsync();
                if (Attachment != null)
                {
                    foreach (var attachment in Attachment)
                    {
                        attachment.URI = $"{baseUrl}/{attachment.Id}";
                    }
                    logger?.LogInformation($"{Attachment.Count} Attachments(s) found");
                    var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(Attachment);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }

        }
        public async Task<(bool IsSuccess, Models.Attachment Attachment, string ErrorMessage)> GetAttachmentByIdAsync(int Id)
        {
            try
            {
                logger?.LogInformation("Query Attachment");
                var Attachment = await AttachmentDbContext.Attachments.AsNoTracking().FirstOrDefaultAsync(q => q.Id == Id & !q.IsDeleted);
                if (Attachment != null)
                {
                    logger?.LogInformation($"{Attachment} customer(s) found");
                    Attachment.URI = $"{baseUrl}/{Attachment.Id}";
                    var result = mapper.Map<Db.Attachment, Models.Attachment>(Attachment);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }
        public async Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> PostAttachmentAsync(List<Models.Attachment> Attachments)
        {
            try
            {
                logger?.LogInformation("Query Attachment");
                List<Db.Attachment> attachments = mapper.Map<List<Models.Attachment>, List<Db.Attachment>>(Attachments);
                AttachmentDbContext.Attachments.AddRange(attachments);
                await AttachmentDbContext.SaveChangesAsync();
                foreach (var attachment in attachments)
                {
                    attachment.URI = $"{baseUrl}/{attachment.Id}";
                }
                var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(attachments);
                return (true, result, null);
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        public async Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> PutAttachmentAsync(List<Models.Attachment> Attachments)
        {
            try
            {
                logger?.LogInformation("Query Attachment");
                List<Db.Attachment> attachments = mapper.Map<List<Models.Attachment>, List<Db.Attachment>>(Attachments);
                AttachmentDbContext.Attachments.UpdateRange(attachments);
                await AttachmentDbContext.SaveChangesAsync();
                foreach (var attachment in attachments)
                {
                    attachment.URI = $"{baseUrl}/{attachment.Id}";
                }
                var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(attachments);
                return (true, result, null);
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }
        public async Task<(bool IsSuccess, int counter, string Path)> DeleteBulkAttachmentsAsync(int responseId, List<int> answerIds)
        {
            int AttachmentId = 0;
            try
            {
                AttachmentId = AttachmentDbContext.Attachments.Max(a => a.Id);
                List<Db.Attachment> Attachments = AttachmentDbContext.Attachments.Where(a => a.ResponseId == responseId && answerIds.Contains(a.AnswerId ?? 0)).AsNoTracking().ToList();
                if (Attachments.Count > 0)
                {
                    AttachmentDbContext.Attachments.RemoveRange(Attachments);
                    await AttachmentDbContext.SaveChangesAsync();
                }
                return (true, AttachmentId, "");
            }
            catch (Exception ex)
            {

                logger?.LogError(ex.ToString());
                return (false, AttachmentId, "");
            }
        }
        public async Task<(bool IsSuccess,int counter,string message)> GetAttachmentCounter()
        {
            try
            {
                int AttachmentId = AttachmentDbContext.Attachments.Max(a => a.Id);
                return  (true, AttachmentId, "");
            }
            catch(Exception ex)
            {
                return (false, 0, ex.Message);
            }
        }
        public async Task<(bool IsSuccess, int counter, string Path)> DeleteAttachmentsAsync(int responseId, int answerId)
        {
            int AttachmentId = 0;
            try
            {
                 AttachmentId = AttachmentDbContext.Attachments.Max(a => a.Id);
                List<Db.Attachment> Attachments = AttachmentDbContext.Attachments.Where(a => a.ResponseId == responseId && a.AnswerId == answerId).AsNoTracking().ToList();
                if (Attachments.Count > 0)
                {
                    AttachmentDbContext.Attachments.RemoveRange(Attachments);
                    await AttachmentDbContext.SaveChangesAsync();
                }
                return (true, AttachmentId, "");
            }
            catch (Exception ex)
            {

                logger?.LogError(ex.ToString());
                return (false, AttachmentId, "");
            }
        }
        public async Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> GetAttachmentInfo(List<AnswerInfo> answers)
        {
            try
            {
                List<int> attchmentIds = new List<int>();
                foreach (AnswerInfo item in answers)
                {
                    attchmentIds.AddRange(item.postedFiles.Select(a => a.AttachmentId ?? 0).ToList());
                }
                var attachments= AttachmentDbContext.Attachments.AsNoTracking().Where(a=>attchmentIds.Contains(a.Id)).ToList();
                var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(attachments);
                return (true, result, null);
            }
            catch (Exception ex) 
            {
                return (false, null, ex.Message);
            }
        }
        public async Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> DeleteAttachmentAsync(int Id)
        {
            try
            {
                Db.Attachment Attachment = AttachmentDbContext.Attachments.Where(a => a.Id == Id).AsNoTracking().FirstOrDefault();
                if (Attachment == null)
                {
                    return (false, null, "Not Found");
                }
                Attachment.IsDeleted = true;
                AttachmentDbContext.Attachments.Update(Attachment);
                await AttachmentDbContext.SaveChangesAsync();
                return (true, mapper.Map<Db.Attachment, Models.Attachment>(Attachment), $"Attachment {Id} is deleted");
            }
            catch (Exception ex)
            {

                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }
        private bool AttachmentExists(int id)
        {
            return AttachmentDbContext.Attachments.AsNoTracking().Count(e => e.Id == id && !e.IsDeleted) > 0;
        }
        public async Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> GetDownloadAttachmentAsync(int Id)
        {
            try
            {
                Db.Attachment Attachment = AttachmentDbContext.Attachments.Where(a => a.Id == Id).AsNoTracking().FirstOrDefault();
                if (Attachment == null)
                {
                    return (false, null, "Not Found");
                }
                return (true, mapper.Map<Db.Attachment, Models.Attachment>(Attachment), $"Attachment {Id}");
            }
            catch (Exception ex)
            {

                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        private void SeedData()
        {
            if (!AttachmentDbContext.Attachments.Any())
            {
                // adding sample text file in respective folder based responseid and answer id
                FileModel fileModel= new FileModel(){AttachmentId=0,FileName="Sample",FileContent= "c2FtcGxl",FileExtension=".txt"};
                List<AnswerInfo> answerInfos=new List<AnswerInfo>();
                answerInfos.Add(new AnswerInfo(){ AnswerId = 1,postedFiles=new List<FileModel> { fileModel }});
                List<Models.Attachment> attachments = uploadservice.UploadAttachment(1, 0, answerInfos);
                if (attachments.Count > 0)
                {
                    List<Db.Attachment> Attachments = mapper.Map<List<Models.Attachment>, List<Db.Attachment>>(attachments);
                    AttachmentDbContext.Attachments.AddRange(Attachments);
                    AttachmentDbContext.SaveChanges();
                }
            }

        }
    }
}