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

namespace UnivateProperties_API.Repository.Timeshare
{
    public class WeekRepository : IRepository<TimeshareWeek>
    {
        private readonly DataContext _dbContext;

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

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

        public List<TimeshareWeek> GetAll()
        {
            return _dbContext.Weeks.ToList();
        }

        private TimeshareWeek GetWeekDetailed(TimeshareWeek week)
        {
            // Get Agent
            if(week.AgentId != 0 && week.Agent == null)
            {
                AgentRepository agentRepo = new AgentRepository(_dbContext);
                week.Agent = agentRepo.GetDetailed(x => x.Id == week.AgentId);
            }
            // Get Agency
            if(week.AgencyId != 0 && week.Agency == null)
            {
                AgencyRepository agencyRepo = new AgencyRepository(_dbContext);
                week.Agency = agencyRepo.GetDetailed(x => x.Id == week.AgencyId);
            }
            // Get Region
            if(week.RegionId != 0 && week.Region == null)
            {
                ProvinceRepository provinceRepo = new ProvinceRepository(_dbContext);
                week.Region = provinceRepo.GetDetailed(x => x.Id == week.RegionId);
            }
            // Get Status
            if(week.StatusId != 0 && week.Status == null)
            {
                StatusRepository statusRepo = new StatusRepository(_dbContext);
                week.Status = statusRepo.GetDetailed(x => x.Id == week.StatusId);
            }

            return week;
        }

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

        public List<TimeshareWeek> GetDetailedAll()
        {
            var list = GetAll();
            List<TimeshareWeek> weeklist = new List<TimeshareWeek>();
            foreach(var item in list)
            {
                weeklist.Add(GetWeekDetailed(item));
            }
            return weeklist;
        }

        public void Insert(TimeshareWeek item)
        {
            item = GetWeekDetailed(item);
            // Set starting Status of A1
            StatusRepository repo = new StatusRepository(_dbContext);
            item.Status = repo.GetDetailed(s => s.Code == "A1");
            if(item.Status != null)
            {
                //Create initial
                item.Status = new Status()
                {
                    Code = "A1",
                    Description = "Pending verification",
                    StatusType = StatusType.Timeshare,
                    ModifiedBy = "KobusB"
                };
            }            
            _dbContext.Add(item);
            Save();
        }

        public void Insert(IEnumerable<TimeshareWeek> items)
        {
            foreach (var item in items)
            {
                _dbContext.Add(item);
            }
            Save();
        }

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

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

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

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

        public void Update(TimeshareWeek item)
        {
            _dbContext.Entry(item).State = EntityState.Modified;
            Save();
        }

        public List<TimeshareWeek> GetBy(WeekFilterDto week)
        {
            List<TimeshareWeek> item = GetDetailedAll();
            if (!string.IsNullOrEmpty(week.RegionCode))
            {
                item = item.Where(x => x.Region != null && x.Region.Code?.ToLower() == week.RegionCode.ToLower()).ToList();
            }
            if (!string.IsNullOrEmpty(week.ResortCode))
            {
                item = item.Where(x => x.ResortCode?.ToLower() == week.ResortCode).ToList();
            }
            if (week.Date != null)
            {
                item = item.Where(x =>
                                        x.ArrivalDate >= week.Date.Value.AddDays(-7)
                                        && x.DepartureDate <= week.Date.Value.AddDays(7)).ToList();
            }
            if (week.MinAmount != null && week.MinAmount != 0)
            {
                item = item.Where(x => x.SellPrice >= week.MinAmount).ToList();
            }
            if (week.MaxAmount != null && week.MaxAmount != 0)
            {
                item.Where(x => x.SellPrice <= week.MaxAmount).ToList();
            }
            return item;
        }
    }
}