using DbConnectionLibrairie;
using Entities;
using ManagerInterfaces;
using Microsoft.EntityFrameworkCore;
using OrderCriterias;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EntityManagers
{
    public class AnswerEntityManager : IAnswerManager<AnswerEntity>
    {
        private MyDbContext dbContext;

        public AnswerEntityManager(MyDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public async Task<AnswerEntity> addAnswer(AnswerEntity answer)
        {
            var tmp = await dbContext.Answers.Where(a => a.Content == answer.Content.ToLower() && a.IdQuestion == answer.IdQuestion).FirstOrDefaultAsync();
            if (tmp != null) // <=> he already exist
            {
                return tmp!;
            }
            await dbContext.Answers.AddAsync(new AnswerEntity { Content = answer.Content.ToLower(), IdQuestion = answer.IdQuestion });
            await dbContext.SaveChangesAsync();
            return await dbContext.Answers.Where(a => a.Content == answer.Content && a.IdQuestion == answer.IdQuestion).FirstAsync();
        }

        public async Task<AnswerEntity?> getAnswer(uint id)
        {
            return await dbContext.Answers.Where(a => a.Id == id).FirstOrDefaultAsync();
        }

        public async Task<(int nbPages, IEnumerable<AnswerEntity>? answers)> getAnswers(int page, int count, AnswerOrderCriteria orderCriteria = AnswerOrderCriteria.ById)
        {
            int nbEl = getNbElements();
            if (page < 0 || count < 0 || page > nbEl / count)
            {
                return await Task.FromResult<(
                    int nbPages,
                    IEnumerable<AnswerEntity>? answers
                )> ((
                    count == 0 ? -1 : nbEl / count,
                    null
                ));
            }
            var tmp = dbContext.Answers;
            switch (orderCriteria)
            {
                case AnswerOrderCriteria.ById:
                    tmp.OrderBy(a => a.Id);
                    break;
                case AnswerOrderCriteria.ByContent:
                    tmp.OrderBy(a => a.Content);
                    break;
                case AnswerOrderCriteria.ByIdQuestion:
                    tmp.OrderBy(a => a.IdQuestion);
                    break;
            }
            return await Task.FromResult<(
                int nbPages,
                IEnumerable<AnswerEntity>? answers
            )> ((
                nbEl / count,
                tmp.Skip((page - 1) * count).Take(count)
            ));
        }

        public async Task<IEnumerable<AnswerEntity>?> getAnswersByIdQuestion(uint id)
        {
            if(dbContext.Questions.Where(q => q.Id == id).Any())
            {
                return await Task.FromResult<IEnumerable<AnswerEntity>?>(dbContext.Answers.Where(a => a.IdQuestion == id));
            }
            return await Task.FromResult<IEnumerable<AnswerEntity>?>(null);
        }

        public int getNbElements()
        {
            return dbContext.Answers.CountAsync().Result;
        }

        public async Task<AnswerEntity?> removeAnswer(uint id)
        {
            var tmp = getAnswer(id).Result;
            if (tmp == null) return await Task.FromResult<AnswerEntity?>(tmp);
            dbContext.Answers.Remove(tmp);
            await dbContext.SaveChangesAsync();
            return await Task.FromResult<AnswerEntity?>(tmp);
        }

        public async Task<AnswerEntity?> removeAnswer(AnswerEntity answer)
        {
            var tmp = dbContext.Answers.Where(a => a.Equals(answer)).FirstOrDefaultAsync().Result;
            if (tmp == null) return await Task.FromResult<AnswerEntity?>(tmp);
            dbContext.Answers.Remove(tmp);
            await dbContext.SaveChangesAsync();
            return await Task.FromResult<AnswerEntity?>(tmp);
        }

        public async Task<AnswerEntity?> updateAnswer(uint id, AnswerEntity answer)
        {
            var tmp = await dbContext.Answers.Where(a => a.Id == id).FirstOrDefaultAsync();
            if(tmp == null)
            {
                return null;
            }
            tmp.Content = answer.Content;
            tmp.Question = answer.Question;
            tmp.IdQuestion = answer.IdQuestion;
            await dbContext.SaveChangesAsync();
            return tmp;
        }
    }
}
