using AutoMapper;
using DamageAssesment.Api.Answers.Db;
using DamageAssesment.Api.Answers.Interfaces;
using DamageAssesment.Api.Answers.Models;
using Microsoft.EntityFrameworkCore;

namespace DamageAssesment.Api.Answers.Providers
{
    public class AnswersProvider : IAnswersProvider
    {
        private AnswerDbContext answerDbContext;
        private ILogger<AnswersProvider> logger;
        private IMapper mapper;

        // Constructor with dependency injection and data seeding
        public AnswersProvider(AnswerDbContext answerDbContext, ILogger<AnswersProvider> logger, IMapper mapper)
        {
            this.answerDbContext = answerDbContext;
            this.logger = logger;
            this.mapper = mapper;
            SeedData(); // Seed initial data if the table is empty
        }

        // Get all answers
        public async Task<(bool IsSuccess, IEnumerable<Models.Answer> Answers, string ErrorMessage)> GetAnswersAsync()
        {
            try
            {
                logger?.LogInformation("Query Question");
                var answer = await answerDbContext.Answers.AsNoTracking().ToListAsync();
                if (answer != null)
                {
                    logger?.LogInformation($"{answer.Count} Answers(s) found");
                    var result = mapper.Map<IEnumerable<Db.Answer>, IEnumerable<Models.Answer>>(answer);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Get an answer by its ID
        public async Task<(bool IsSuccess, Models.Answer Answer, string ErrorMessage)> GetAnswerByIdAsync(int Id)
        {
            try
            {
                logger?.LogInformation("Query Answer");
                var answer = await answerDbContext.Answers.AsNoTracking().FirstOrDefaultAsync(q => q.Id == Id);
                if (answer != null)
                {
                    logger?.LogInformation($"{answer} customer(s) found");
                    var result = mapper.Map<Db.Answer, Models.Answer>(answer);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Get answers by survey response ID
        public async Task<(bool IsSuccess, IEnumerable<Models.Answer> Answers, string ErrorMessage)> GetAnswersAsync(int surveyResponseId)
        {
            try
            {
                var respAnswers = await answerDbContext.Answers.AsNoTracking()
                    .Where(a => a.SurveyResponseId == surveyResponseId).AsNoTracking()
                    .ToListAsync();
                if (respAnswers != null)
                {
                    var result = mapper.Map<IEnumerable<Db.Answer>, IEnumerable<Models.Answer>>(respAnswers);
                    return (true, result, null);
                }
                return (false, null, "Not Found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Get answers by question ID
        public async Task<(bool IsSuccess, IEnumerable<Models.Answer> Answers, string ErrorMessage)> GetAnswersByQuestionAsync(int questionId)
        {
            try
            {
                var respAnswers = await answerDbContext.Answers.AsNoTracking()
                    .Where(a => a.QuestionId == questionId).AsNoTracking()
                    .ToListAsync();
                if (respAnswers != null)
                {
                    var result = mapper.Map<IEnumerable<Db.Answer>, IEnumerable<Models.Answer>>(respAnswers);
                    return (true, result, null);
                }
                return (false, null, "Not Found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Create a new answer
        public async Task<(bool IsSuccess, Models.Answer Answer, string ErrorMessage)> PostAnswerAsync(Models.Answer Answer)
        {
            try
            {
                logger?.LogInformation("Query Answer");
                if (!AnswerExists(Answer.Id))
                {
                    Db.Answer answer = mapper.Map<Models.Answer, Db.Answer>(Answer);
                    answerDbContext.Answers.Add(answer);
                    await answerDbContext.SaveChangesAsync();
                    var result = mapper.Map<Db.Answer, Models.Answer>(answer);
                    return (true, result, null);
                }
                return (false, null, "Answer is already exists");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Update an existing answer
        public async Task<(bool IsSuccess, Models.Answer Answer, string ErrorMessage)> UpdateAnswerAsync(Models.Answer Answer)
        {
            try
            {
                if (Answer != null)
                {
                    var existing = answerDbContext.Answers.AsNoTracking().FirstOrDefault(x => x.Id == Answer.Id);
                    if (existing != null)
                    {
                        Db.Answer answer = mapper.Map<Models.Answer, Db.Answer>(Answer);
                        answerDbContext.Answers.Update(answer);
                        await answerDbContext.SaveChangesAsync();
                        return (true, mapper.Map<Db.Answer, Models.Answer>(answer), "Successful");
                    }
                    else
                    {
                        logger?.LogInformation($"{Answer} Not found");
                        return (false, null, "Not Found");
                    }
                }
                else
                {
                    logger?.LogInformation($"{Answer} Bad Request");
                    return (false, null, "Bad request");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Delete an answer by its ID
        public async Task<(bool IsSuccess, Models.Answer Answer, string ErrorMessage)> DeleteAnswerAsync(int Id)
        {
            try
            {
                Db.Answer answer = answerDbContext.Answers.AsNoTracking().Where(a => a.Id == Id).FirstOrDefault();
                if (answer == null)
                {
                    return (false, null, "Not Found");
                }
                answerDbContext.Answers.Remove(answer);
                answerDbContext.SaveChanges();
                return (true, mapper.Map<Db.Answer, Models.Answer>(answer), $"AnswerId {Id} deleted successfully");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Check if an answer with a specific ID exists
        private bool AnswerExists(int id)
        {
            return answerDbContext.Answers.AsNoTracking().Count(e => e.Id == id) > 0;
        }

        // Seed initial data if the table is empty
        public void SeedData()
        {
            if (!answerDbContext.Answers.Any())
            {
                answerDbContext.Answers.Add(new Db.Answer() { Id = 1, AnswerText = "Yes", Comment = "Comment test 4", QuestionId = 1, SurveyResponseId = 1 });
                answerDbContext.Answers.Add(new Db.Answer() { Id = 2, AnswerText = "No", Comment = "Comment test 5", QuestionId = 2, SurveyResponseId = 1 });
                // Uncomment the lines below to add more initial data if needed
                //answerDbContext.Answers.Add(new Db.Answer() { Id = 3, AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 1 });
                //answerDbContext.Answers.Add(new Db.Answer() { Id = 4, AnswerText = "Yes", Comment = "No Comment", QuestionId = 1, SurveyResponseId = 2 });
                //answerDbContext.Answers.Add(new Db.Answer() { Id = 5, AnswerText = "No", Comment = "No Comment", QuestionId = 2, SurveyResponseId = 2 });
                //answerDbContext.Answers.Add(new Db.Answer() { Id = 6, AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 2 });
                answerDbContext.SaveChanges();
            }
        }
    }
}