using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using EFCore.BulkExtensions;
using Microsoft.Extensions.Options;
using OnlineAssessment.Common;
using OnlineAssessment.Domain.Models;
using OnlineAssessment.Domain.ViewModels;

namespace OnlineAssessment.Data.EFCore
{
    public class EFCorePlanRepository : EfCoreRepository<Subscriptions, OnlineAssessmentContext>
    {
        public readonly OnlineAssessmentContext _context;
        public readonly EfCoreCommonRepository _common;
        private readonly IMapper _mapper;
        public EFCorePlanRepository(OnlineAssessmentContext context, IMapper mapper, IOptionsSnapshot<ResponseMessage> responseMessage) : base(context, responseMessage)
        {
            _context = context;
            _mapper = mapper;
            _common = new EfCoreCommonRepository(_context, mapper);
        }
        #region Plans
   
        public dynamic AddPlans(int institute_id, int user_id, PlanAddModel newPlan)
        {
            try
            {
                string slug = _common.CreateSlug(newPlan.code);
                Plans oldPlan = _context.Plans.Where(p => p.InstituteId == institute_id && p.IsActive == true &&
                    p.Status == StatusCode.PUBLISHED.ToString() && p.Code == slug).FirstOrDefault();
                if (oldPlan != null)
                    return (int)Message.InvalidInput;

                _context.Database.BeginTransaction();
                int newId = 0;
                Plans plans = new Plans();
                plans.Name = newPlan.name;
                plans.Code = slug;
                plans.Description = newPlan.description;
                plans.InstituteId = institute_id;
                plans.CreatedOn = _common.NowIndianTime();
                plans.UpdatedOn = _common.NowIndianTime();
                plans.CreatedBy = user_id;
                plans.UpdatedBy = user_id;
                plans.IsActive = true;
                plans.PaidExams = newPlan.paid_exams;
                plans.PaidPractices = newPlan.paid_practices;
                plans.InitialPrice = newPlan.initial_price;
                plans.FinalPrice = newPlan.final_price;
                plans.Status = StatusCode.DRAFT.ToString();

                _context.Plans.Add(plans);
                _context.SaveChanges();
                newId = plans.Id;

                _context.Database.CommitTransaction();

                return slug;
            }
            catch
            {
                _context.Database.RollbackTransaction();
                return -1;
            }
        }

        public dynamic PublishPlans(int institute_id, int user_id, string plan_code)
        {
            try
            {
                Plans plans = _context.Plans.Where(p => p.InstituteId == institute_id && p.IsActive == true &&
                    p.Status != StatusCode.PUBLISHED.ToString() && p.Code == plan_code).FirstOrDefault();
                if (plans == null)
                    return (int)Message.NotAllowedToResource;

                _context.Database.BeginTransaction();
                plans.UpdatedOn = _common.NowIndianTime();
                plans.UpdatedBy = user_id;
                plans.Status = StatusCode.PUBLISHED.ToString();

                _context.Plans.Update(plans);
                _context.SaveChanges();
                
                _context.Database.CommitTransaction();

                return plans.Code;
            }
            catch
            {
                _context.Database.RollbackTransaction();
                return -1;
            }
        }

        public dynamic DeletePlans(int institute_id, int user_id, string plan_code)
        {
            try
            {
                Plans plans = _context.Plans.Where(p => p.InstituteId == institute_id && p.IsActive == true &&
                    p.Code == plan_code).FirstOrDefault();
                if (plans == null)
                    return (int)Message.NotAllowedToResource;

                _context.Database.BeginTransaction();
                plans.UpdatedOn = _common.NowIndianTime();
                plans.UpdatedBy = user_id;
                plans.IsActive = false;

                _context.Plans.Update(plans);
                _context.SaveChanges();

                _context.Database.CommitTransaction();

                return plans.Code;
            }
            catch
            {
                _context.Database.RollbackTransaction();
                return -1;
            }
        }


        public List<PlanViewModel> GetPlans(int institute_id, string sortBy, string sortOrder)
        {
            List<PlanViewModel> planList = (from p in _context.Plans
                                          where p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString() &&  p.IsActive == true 
                                          select new PlanViewModel
                                          {
                                              code = p.Code,
                                              name = p.Name,
                                              description = p.Description,
                                              paid_exams = (int) p.PaidExams,
                                              paid_practices = (int) p.PaidPractices,
                                              duration_days = (int) p.DurationDays,
                                              initial_price = (int) p.InitialPrice,
                                              final_price = (int) p.FinalPrice,
                                              last_updated = (DateTime) p.UpdatedOn
                                          }
                         ).ToList();

            if ((sortOrder != null && sortOrder.Length > 0) || (sortBy != null && sortBy.Length > 0))
            {
                if (sortOrder != null && sortOrder.Equals("D"))
                {
                    switch (sortBy.ToUpper())
                    {
                        case "NAME": planList = planList.OrderByDescending(a => a.name).ToList(); break;
                        case "UPDATED_ON": planList = planList.OrderByDescending(a => a.last_updated).ToList(); break;
                    }

                }
                else
                {
                    switch (sortBy.ToUpper())
                    {
                        case "NAME": planList = planList.OrderBy(a => a.name).ToList(); break;
                        case "UPDATED_ON": planList = planList.OrderBy(a => a.last_updated).ToList(); break;
                    }
                }
            }

            return planList;
        }

        public TagViewModel UpdateTagOfTheInstitute(int institute_id, int user_id, TagEditModel existingTag)
        {
            try
            {

                _context.Database.BeginTransaction();

                int count = 0;

                Tags tags = _context.Tags.Where(t => t.InstituteId == institute_id && t.Id == existingTag.Id && t.IsActive == true).FirstOrDefault();
                if (existingTag.name != null && existingTag.name != tags.Name) { tags.Name = existingTag.name; count++; }

                if(count > 0)
                {
                    tags.UpdatedOn = _common.NowIndianTime();
                    tags.UpdatedBy = user_id;
                }

                _context.Tags.Update(tags);
                _context.SaveChanges();
                
                _context.Database.CommitTransaction();

                TagViewModel tvm = _common.GetTagById(institute_id, existingTag.Id);

                return tvm;
            }
            catch
            {
                _context.Database.RollbackTransaction();
                return null;
            }
        }
        public int DeleteTagOfTheInstitute(int institute_id, int user_id, int tag_id)
        {
            try
            {
                Tags tags = _context.Tags.Where(t => t.Id == tag_id && t.InstituteId == institute_id && t.IsActive == true).FirstOrDefault();

                tags.IsActive = false;
                tags.UpdatedOn = _common.NowIndianTime();
                tags.UpdatedBy = user_id;

                _context.Tags.Update(tags);
                _context.SaveChanges();

                return tag_id;

            }
            catch
            {
                return 0;
            }
        }

        #endregion

    }
}
