using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using UnivateProperties_API.Containers.Communication;
using UnivateProperties_API.Context;
using UnivateProperties_API.Model;
using UnivateProperties_API.Model.Communication;
using UnivateProperties_API.Model.Timeshare;
using UnivateProperties_API.Model.Users;

namespace UnivateProperties_API.Repository.Communication
{
    public class TemplateRepository : IRepository<Template>
    {
        private readonly DataContext _dbContext;

        public TemplateRepository(DataContext dbContext)
        {
            _dbContext = dbContext;
        }

        public List<Template> Get(Func<Template, bool> where)
        {
            return _dbContext.Templates.Where(where).ToList();
        }

        public List<Template> GetAll()
        {
            return _dbContext.Templates.ToList();
        }

        public Template GetDetailed(Func<Template, bool> first)
        {
            var item = _dbContext.Templates.FirstOrDefault(first);
            return item;
        }

        public List<Template> GetDetailedAll()
        {
            var list = GetAll();
            return list;
        }

        public void Insert(Template item)
        {
            item.Id = NewId();
            _dbContext.Add(item);
            Save();
        }

        public void Insert(IEnumerable<Template> items)
        {
            int id = NewId();
            foreach (var item in items)
            {
                item.Id = id;
                _dbContext.Add(item);
                id += 1;
            }
            Save();
        }

        public void Remove(Template item)
        {
            var i = _dbContext.Templates.Find(item);
            _dbContext.Templates.Remove(i);
            Save();
        }

        public void Remove(IEnumerable<Template> items)
        {
            foreach (var item in items)
            {
                Template i = _dbContext.Templates.Find(item);
                _dbContext.Templates.Remove(i);
            }
            Save();
        }

        public void RemoveAtId(int item)
        {
            var i = _dbContext.Templates.Find(item);
            _dbContext.Templates.Remove(i);
            Save();
        }

        public void Update(Template item)
        {
            var itemList = _dbContext.PlaceHolders.Where(x => x.TemplateId == item.Id).ToList();
            CheckListChange(itemList, item.PlaceHolders.ToList());
            _dbContext.Entry(item).State = EntityState.Modified;
            Save();
        }

        private void CheckListChange(List<PlaceHolder> holderOld, List<PlaceHolder> holderNew)
        {
            foreach (var item in holderOld)
            {
                if (!holderNew.Any(x => x.Id == item.Id))
                {
                    var i = _dbContext.PlaceHolders.FirstOrDefault(x => x.Id == item.Id);
                    if (item != null)
                    {
                        _dbContext.PlaceHolders.Remove(i);
                    }
                }
            }
            foreach (var item in holderNew.Where(x => x.Id == 0))
            {
                _dbContext.Add(item);
            }
        }

        public void Save()
        {
            _dbContext.SaveChanges();
        }

        public int NewId()
        {
            int id = 0;
            if (_dbContext.Templates.Count() > 0)
            {
                id = _dbContext.Templates.Max(x => x.Id);
            }
            id += 1;
            return id;
        }

        public List<TemplateDto> GetSimpleAll()
        {
            List<TemplateDto> list = new List<TemplateDto>();
            foreach (var item in GetAll())
            {
                list.Add(new TemplateDto()
                {
                    Id = item.Id,
                    Name = item.Name,
                    Subject = item.Subject,
                    Body = item.Body,
                    PlaceHolders = GetPlaceHolders(item.Id)
                });
            }
            return list;
        }

        private List<PlaceHolderDto> GetPlaceHolders(int id)
        {
            List<PlaceHolderDto> list = new List<PlaceHolderDto>();
            foreach (var item in _dbContext.PlaceHolders.Where(x => x.TemplateId == id).ToList())
            {
                list.Add(new PlaceHolderDto()
                {
                    Id = item.Id,
                    Name = item.Name,
                    BoundTo = item.BoundTo,
                    BoundToClass = item.BoundToClass,
                    BoundToClassDisplay = item.BoundToClassDisplay
                });
            }
            return list;
        }

        public void SendEmailTemplate(Template template, Person sendTo, List<BaseEntity> args)
        {
            if (template != null)
            {
                if (template.SenderId == null)
                {
                    var acc = _dbContext.Accounts.FirstOrDefault(x => x.Default);
                    if (acc != null)
                    {
                        template.SenderId = acc.Id;
                        template.Sender = acc;
                    }
                }
                else template.Sender = _dbContext.Accounts.FirstOrDefault(x => x.Id == template.SenderId);
                template.PlaceHolders = _dbContext.PlaceHolders.Where(x => x.TemplateId == template.Id).ToList();
                if (sendTo != null)
                {
                    try
                    {
                        Email email = new Email(template, sendTo, args);
                        EmailRepository emailRepo = new EmailRepository(_dbContext);
                        emailRepo.Insert(email);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
        }
    }
}