using AutoMapper;
using DamageAssesment.Api.Surveys.Db;
using DamageAssesment.Api.Surveys.Interfaces;
using DamageAssesment.Api.Surveys.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace DamageAssesment.Api.Surveys.Providers
{
    public class SurveysProvider : ISurveyProvider
    {
        private readonly SurveysDbContext surveyDbContext;
        private readonly ILogger<SurveysProvider> logger;
        private readonly IMapper mapper;

        public SurveysProvider(SurveysDbContext surveysDbContext, ILogger<SurveysProvider> logger, IMapper mapper)
        {
            this.surveyDbContext = surveysDbContext;
            this.logger = logger;
            this.mapper = mapper;
            //seedData();
        }

        // Method to seed initial data into the database
        public void seedData()
        {
            if (!surveyDbContext.Surveys.Any())
            {
                var survey1 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now };
                var survey2 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now.AddDays(-10) };
                var survey3 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-100), EndDate = DateTime.Now.AddDays(-10), CreatedDate = DateTime.Now.AddDays(-100) };

                surveyDbContext.Surveys.Add(survey1);
                surveyDbContext.Surveys.Add(survey2);
                surveyDbContext.Surveys.Add(survey3);
                surveyDbContext.SaveChanges();

                if (!surveyDbContext.SurveysTranslation.Any())
                {
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey1.Id, Language = "en", Title = "Impact of Tropical Storm Emily on Florida's Economy" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey1.Id, Language = "es", Title = "Impacto de la tormenta tropical Emily en la economía de Florida" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey1.Id, Language = "fr", Title = "Impact de la tempête tropicale Emily sur l'économie de la Floride" });

                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey2.Id, Language = "en", Title = "Hurricane Andrew Aftermath Survey" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey2.Id, Language = "es", Title = "Encuesta sobre las secuelas del huracán Andrew" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey2.Id, Language = "fr", Title = "Enquête sur les conséquences de l'ouragan Andrew" });
                  
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey3.Id, Language = "en", Title = "Hurricane Irma" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey3.Id, Language = "es", Title = "Huracán Irma" });
                    surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = survey3.Id, Language = "fr", Title = "Ouragan Irma" });

                    surveyDbContext.SaveChanges();
                }
            }
        }

        // Method to get survey translations for a given survey ID and language
        public IEnumerable<Models.SurveyTranslation> GetSurveyTranslations(int id, IEnumerable<Models.SurveyTranslation> SurveyTranslation, string? language)
        {
            if (SurveyTranslation == null)
            {
                if (string.IsNullOrEmpty(language))
                {
                    SurveyTranslation = mapper.Map<IEnumerable<Db.SurveyTranslation>, IEnumerable<Models.SurveyTranslation>>(
                        surveyDbContext.SurveysTranslation.Where(a => a.SurveyId == id).ToList());
                }
                else
                {
                    SurveyTranslation = mapper.Map<IEnumerable<Db.SurveyTranslation>, IEnumerable<Models.SurveyTranslation>>(
                    surveyDbContext.SurveysTranslation.Where(a => a.SurveyId == id && a.Language == language).ToList());
                }
            }
            return SurveyTranslation;
        }

        // Method to create a multi-language object from survey translations
        public object CreateMultiLanguageObject(IEnumerable<Models.SurveyTranslation> surveyTranslations)
        {
            object MultiLanguage = new object();
            Dictionary<string, string> dict = new Dictionary<string, string>();
            foreach (Models.SurveyTranslation item in surveyTranslations)
            {
                dict.Add(item.Language, item.Title);
            }
            MultiLanguage = dict;
            return MultiLanguage;
        }
        public string GetStatus(DateTime? StartDate,DateTime? EndDate)
        {
            try
            {
                if (StartDate > DateTime.Now)
                    return SurveyStatus.PENDING.ToString();
                else if (StartDate <= DateTime.Now && EndDate > DateTime.Now)
                    return SurveyStatus.ACTIVE.ToString();
                else
                    return SurveyStatus.INACTIVE.ToString();
            }
            catch
            {
                return SurveyStatus.INACTIVE.ToString();
            }
        }
        // Method to get surveys asynchronously with multi-language support
        public async Task<(bool IsSuccess, IEnumerable<Models.MultiLanSurvey> Surveys, string ErrorMessage)> GetSurveysAsync(string language)
        {
            IEnumerable<Models.MultiLanSurvey> surveysList = null;
            try
            {
                logger?.LogInformation("Get all Surveys from DB");
                //checking is enabled in survey response 
                var surveys = await surveyDbContext.Surveys.ToListAsync();//Where(s => s.IsEnabled == true)
                if (surveys != null)
                {
                    surveysList = from s in surveys
                                  select new Models.MultiLanSurvey
                                  {
                                      Id = s.Id,
                                      StartDate = s.StartDate,
                                      EndDate = s.EndDate,
                                      IsEnabled = s.IsEnabled,
                                      CreatedDate = s.CreatedDate,
                                      Status= GetStatus(s.StartDate,s.EndDate),
                                      Titles = CreateMultiLanguageObject(GetSurveyTranslations(s.Id, null, language))
                                  };

                    logger?.LogInformation($"{surveys.Count} Items(s) found");
                    return (true, surveysList, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Method to get a specific survey by ID asynchronously with multi-language support
        public async Task<(bool IsSuccess, Models.MultiLanSurvey Surveys, string ErrorMessage)> GetSurveysAsync(int id, string language)
        {
            try
            {
                logger?.LogInformation("Query Survey");
                // removed is enabled becuase we are using it in responses to get response
                var survey = await surveyDbContext.Surveys.SingleOrDefaultAsync(s => s.Id == id);

                if (survey != null)
                {
                    Models.MultiLanSurvey result = null;
                    var surveyTranslations = await surveyDbContext.SurveysTranslation.Where(s => s.SurveyId == survey.Id).ToListAsync();
                    result = new Models.MultiLanSurvey
                    {
                        Id = survey.Id,
                        StartDate = survey.StartDate,
                        EndDate = survey.EndDate,
                        IsEnabled = survey.IsEnabled,
                        CreatedDate = survey.CreatedDate,
                        Status = GetStatus(survey.StartDate, survey.EndDate),
                        Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, language))
                    };
                    logger?.LogInformation($"Survey Id: {id} found");
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Method to create a new survey asynchronously with multi-language support
        public async Task<(bool IsSuccess, Models.MultiLanSurvey Survey, string ErrorMessage)> PostSurveyAsync(Models.Survey survey)
        {
            try
            {
                if (survey != null)
                {
                    if (survey.StartDate != null && survey.EndDate != null)
                    {
                        if(survey.StartDate.Value>survey.EndDate.Value)
                            return (false, null, $"Survey start date should be less than enddate");
                    }
                    survey.CreatedDate = DateTime.Now;
                    Db.Survey _survey = mapper.Map<Models.Survey, Db.Survey>(survey);

                    surveyDbContext.Surveys.Add(_survey);
                    await surveyDbContext.SaveChangesAsync();

                    foreach (var title in survey.Titles)
                    {
                        surveyDbContext.SurveysTranslation.Add(new Db.SurveyTranslation { SurveyId = _survey.Id, Language = title.Language, Title = title.Title });
                    }
                    await surveyDbContext.SaveChangesAsync();
                    var result = mapper.Map<Db.Survey, Models.MultiLanSurvey>(_survey);
                    result.Status = GetStatus(_survey.StartDate, _survey.EndDate);
                    result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, ""));
                    return (true, result, "Successful");
                }
                else
                {
                    logger?.LogInformation($"Survey Id: {survey.Id} cannot be added");
                    return (false, null, $"Survey Id:  {survey.Id} cannot be added");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Method to update an existing survey asynchronously with multi-language support
        public async Task<(bool IsSuccess, Models.MultiLanSurvey Survey, string ErrorMessage)> PutSurveyAsync(int Id, Models.Survey survey)
        {
            try
            {
                if (survey != null)
                {
                    if (survey.StartDate != null && survey.EndDate != null)
                    {
                        if (survey.StartDate.Value > survey.EndDate.Value)
                            return (false, null, $"Survey start date should be less than enddate");
                    }
                    var _survey = await surveyDbContext.Surveys.AsNoTracking().Where(s => s.Id == Id).SingleOrDefaultAsync();

                    if (_survey != null)
                    {
                        var surveysTranslation = await surveyDbContext.SurveysTranslation.Where(s => s.SurveyId == Id).ToListAsync();
                        surveyDbContext.SurveysTranslation.RemoveRange(surveysTranslation);
                        await surveyDbContext.SaveChangesAsync();
                        _survey = mapper.Map<Models.Survey, Db.Survey>(survey);
                        surveyDbContext.Surveys.Update(_survey);
                        await surveyDbContext.SaveChangesAsync();
                        List<Db.SurveyTranslation> listSurveyTranslation = new List<Db.SurveyTranslation>();
                        foreach (var title in survey.Titles)
                        {
                            listSurveyTranslation.Add(new Db.SurveyTranslation { SurveyId = _survey.Id, Language = title.Language, Title = title.Title });
                        }
                        surveyDbContext.SurveysTranslation.AddRange(listSurveyTranslation);
                        await surveyDbContext.SaveChangesAsync();

                        var result = mapper.Map<Db.Survey, Models.MultiLanSurvey>(_survey);
                        result.Status = GetStatus(_survey.StartDate, _survey.EndDate);
                        result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, ""));
                        return (true, result, "Successful");
                    }
                    else
                    {
                        logger?.LogInformation($"Survey Id : {Id} Not found");
                        return (false, null, "Not Found");
                    }
                }
                else
                {
                    logger?.LogInformation($"Survey Id: {Id} Bad Request");
                    return (false, null, "Bad request");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        // Method to delete a survey by ID asynchronously with multi-language support
        public async Task<(bool IsSuccess, Models.MultiLanSurvey Survey, string ErrorMessage)> DeleteSurveyAsync(int Id)
        {
            try
            {
                var survey = await surveyDbContext.Surveys.Where(x => x.Id == Id).SingleOrDefaultAsync();

                if (survey != null)
                {
                    var result = mapper.Map<Db.Survey, Models.MultiLanSurvey>(survey);
                    result.Status = GetStatus(survey.StartDate, survey.EndDate);
                    result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, ""));
                    surveyDbContext.Surveys.Remove(survey);
                    await surveyDbContext.SaveChangesAsync();
                    return (true, result, $"Survey Id: {Id} deleted Successfully");
                }
                else
                {
                    logger?.LogInformation($"Survey Id : {Id} Not found");
                    return (false, null, "Not Found");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }
    }
}