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

namespace OnlineAssessment.Data.EFCore
{
    public class EFCorePracticeAttemptRepository : EfCoreRepository<PracticeAttempts, OnlineAssessmentContext>
    {
        public readonly OnlineAssessmentContext _context;
        public readonly EfCoreCommonRepository _common;
        private readonly IMapper _mapper;
        public EFCorePracticeAttemptRepository(OnlineAssessmentContext context, IMapper mapper, IOptionsSnapshot<ResponseMessage> responseMessage) : base(context, responseMessage)
        {
            _context = context;
            _mapper = mapper;
            _common = new EfCoreCommonRepository(_context, mapper);
        }

        public int GetLanguageIdByCode(string language_code)
        {
            Language language = _common.GetLanguageByCode(language_code);

            if (language == null) return -1;
            int language_id = (int)language.Id;

            return language_id;
        }



        #region PracticeAttempts

        //Getting live practices of an institute
        public dynamic GetLivePracticesByModuleID(int institute_id, int user_id, int batch_id, string module, int module_id, string sortBy, string sortOrder)
        {
            List<Practices> practices;
            List<PracticeAttemptAllPracticeModel> practiceList = new List<PracticeAttemptAllPracticeModel>();

            try
            {
                int class_id = _common.getValidClassID(institute_id, batch_id, user_id);

                if (class_id < 0)
                    return (int)Message.NotAllowedToResource;

                if (module_id == -1)
                {
                    practices = (from ugp in _context.UserGroupPractices
                                 join p in _context.Practices on ugp.PracticeId equals p.Id

                                 where ugp.UserGroupId == batch_id && ugp.IsActive == true
                                        && p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString()
                                        && p.ClassId == class_id && p.Module == module && p.OpenDatetime <= _common.NowIndianTime() && p.IsActive == true

                                 select p
                         ).ToList();
                }
                else
                {
                    practices = (from ugp in _context.UserGroupPractices
                                 join p in _context.Practices on ugp.PracticeId equals p.Id

                                 where ugp.UserGroupId == batch_id && ugp.IsActive == true
                                        && p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString()
                                        && p.ClassId == class_id && p.Module == module && p.ModuleId == module_id && p.OpenDatetime <= _common.NowIndianTime() && p.IsActive == true

                                 select p
                         ).ToList();
                }


                if (practices == null || practices.Count == 0) return (int)Message.NoData;

                List<int> practiceIdList = new List<int>();
                foreach (Practices p in practices)
                {
                    practiceIdList.Add(p.Id);
                }

                practiceList = _common.PracticeAttempt_GetPracticeListByIds(institute_id, user_id, practiceIdList);

                if (practiceList == null) return (int)Message.Failure;

                if ((sortOrder != null && sortOrder.Length > 0) || (sortBy != null && sortBy.Length > 0))
                {
                    if (sortOrder != null && sortOrder.Equals("D"))
                    {
                        switch (sortBy.ToUpper())
                        {
                            case "ID": practiceList = practiceList.OrderByDescending(a => a.id).ToList(); break;
                            case "AUTHOR": practiceList = practiceList.OrderByDescending(a => a.author_name).ToList(); break;
                        }
                    }
                    else
                    {
                        switch (sortBy.ToUpper())
                        {
                            case "ID": practiceList = practiceList.OrderBy(a => a.id).ToList(); break;
                            case "AUTHOR": practiceList = practiceList.OrderBy(a => a.author_name).ToList(); break;
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                return (int)Message.Failure;
            }            

            return practiceList;
        }


        //Getting live practices of an author
        public dynamic GetLivePracticesByAuthor(int institute_id, int user_id, int batch_id, int author_id, string sortBy, string sortOrder)
        {
            try
            {
                List<Practices> practices;
                List<PracticeAttemptAllPracticeModel> practiceList = new List<PracticeAttemptAllPracticeModel>();

                int class_id = _common.getValidClassID(institute_id, batch_id, user_id);

                if (class_id < 0)
                    return (int)Message.NotAllowedToResource;

                practices = (from ugp in _context.UserGroupPractices
                             join p in _context.Practices on ugp.PracticeId equals p.Id

                             where ugp.UserGroupId == batch_id && ugp.IsActive == true
                             && p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString()
                             && p.ClassId == class_id && p.CreatedBy == author_id && p.OpenDatetime <= _common.NowIndianTime() && p.IsActive == true

                             select p
                             ).ToList();

                if (practices == null || practices.Count == 0) return (int)Message.NoData;

                List<int> practiceIdList = new List<int>();
                foreach (Practices p in practices)
                {
                    practiceIdList.Add(p.Id);
                }

                practiceList = _common.PracticeAttempt_GetPracticeListByIds(institute_id, user_id, practiceIdList);

                if (practiceIdList == null || practiceIdList.Count == 0) return (int)Message.NoData;

                if ((sortOrder != null && sortOrder.Length > 0) || (sortBy != null && sortBy.Length > 0))
                {
                    if (sortOrder != null && sortOrder.Equals("D"))
                    {
                        switch (sortBy.ToUpper())
                        {
                            case "ID": practiceList = practiceList.OrderByDescending(a => a.id).ToList(); break;
                            case "AUTHOR": practiceList = practiceList.OrderByDescending(a => a.author_name).ToList(); break;
                        }
                    }
                    else
                    {
                        switch (sortBy.ToUpper())
                        {
                            case "ID": practiceList = practiceList.OrderBy(a => a.id).ToList(); break;
                            case "AUTHOR": practiceList = practiceList.OrderBy(a => a.author_name).ToList(); break;
                        }
                    }
                }

                return practiceList;
            }
            catch (Exception ex)
            {
                return (int)Message.Failure;
            }            
        }

        //Getting recently attempted practices of an institute
        public List<PracticeAttemptsModel> GetRecentPracticeAttempts(int institute_id, int user_id, int batch_id, string sortBy, string sortOrder)
        {
            List<PracticeAttemptsModel> practiceList = new List<PracticeAttemptsModel>();

            int class_id = _common.getValidClassID(institute_id, batch_id, user_id);

            if (class_id < 0)
                return null;

            short myPracticePoints = 0;
            int subscription_id = 0;
            SubscriptionViewModel svm = _common.mySubscriptionDetails(user_id);
            if (svm != null)
            {
                myPracticePoints = svm.remaining_practice_credits;
                subscription_id = svm.id;
            }

            practiceList = (from pa in _context.PracticeAttempts
                                join p in _context.Practices on pa.PracticeId equals p.Id
                                join ugp in _context.UserGroupPractices on p.Id equals ugp.PracticeId

                                where p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString()
                                       && p.ClassId == class_id && p.OpenDatetime <= _common.NowIndianTime() && p.IsActive == true
                                       && pa.CreatedBy == user_id
                                       && ugp.UserGroupId == batch_id && ugp.IsActive == true
                                
                                select new PracticeAttemptsModel
                                {
                                    id = pa.Id,
                                    practice_id = p.Id,
                                    name = p.Name,
                                    topic_id = p.ModuleId,
                                    topic_name = _context.Categories.Where(t => t.Id == p.ModuleId && t.IsActive == true).FirstOrDefault().Name,
                                    image = p.Photo,
                                    language_code = _context.Languages.Where(l => l.Id == p.LanguageId && l.IsActive == true).FirstOrDefault().Code,
                                    practice_status = pa.Status,
                                    correct_count = pa.CorrectCount == null ? 0 : pa.CorrectCount,
                                    incorrect_count = pa.IncorrectCount == null ? 0 : pa.IncorrectCount,
                                    unattempted_count = pa.UnattemptedCount == null ? 0 : pa.UnattemptedCount,
                                    complexity = (short)p.Complexity,
                                    attempted_on = pa.CreatedOn,
                                    points_needed = (short)p.CreditsNeeded,
                                    points_available = myPracticePoints,
                                    isSubscribed = _context.SubscribedPractices.Where(sp => sp.SubscriptionId == subscription_id
                                                                        && sp.PracticeId == p.Id && sp.IsActive == true)
                                                                        .FirstOrDefault() == null ? true : false,
                                    isActive = (bool)pa.IsActive

                                }).ToList();

            
            if (practiceList == null || practiceList.Count == 0) return null;

            practiceList = practiceList.OrderByDescending(a => a.attempted_on).GroupBy(p => p.practice_id).Select(p => p.FirstOrDefault()).ToList();
            //practiceList = practiceList.OrderByDescending(a => a.attempted_on).ToList();


            if ((sortOrder != null && sortOrder.Length > 0) || (sortBy != null && sortBy.Length > 0))
            {
                if (sortOrder != null && sortOrder.Equals("D"))
                {
                    switch (sortBy.ToUpper())
                    {
                        case "ID": practiceList = practiceList.OrderByDescending(a => a.id).ToList(); break;
                        case "DATE": practiceList = practiceList.OrderByDescending(a => a.attempted_on).ToList(); break;
                    }
                }
                else
                {
                    switch (sortBy.ToUpper())
                    {
                        case "ID": practiceList = practiceList.OrderBy(a => a.id).ToList(); break;
                        case "DATE": practiceList = practiceList.OrderBy(a => a.attempted_on).ToList(); break;
                    }
                }
            }

            return practiceList;
        }

        public dynamic AddNewAttemptOfThePractice(int institute_id, int user_id, int language_id, int practice_id)
        {
            try
            {
                int newAttemptId = 0;
                PracticeAttemptAllQuestionsViewModel qns = new PracticeAttemptAllQuestionsViewModel();
                //Check practice validity            
                Practices practice = _context.Practices.Where(p => p.Id == practice_id && p.InstituteId == institute_id
                            && p.IsActive == true && p.Status == StatusCode.PUBLISHED.ToString()).FirstOrDefault();

                if (practice == null) return (int)Message.NotAllowedToResource;

                //Check subscription validity                
                SubscriptionViewModel svm;
                int subscription_id = 0;
                bool isSubscribed = false;
                if (practice.CreditsNeeded > 0)
                {
                    svm = _common.mySubscriptionDetails(user_id);
                    if (svm == null)
                        return (int)Message.NoValidSubscription;

                    subscription_id = svm.id;

                    SubscribedPractices subsPractice = _context.SubscribedPractices.Where(sp => sp.SubscriptionId == svm.id
                                        && sp.PracticeId == practice_id && sp.IsActive == true).FirstOrDefault();

                    if (subsPractice == null && svm.remaining_practice_credits < practice.CreditsNeeded)
                    {
                        return (int)Message.NoValidSubscription;
                    }
                    if (subsPractice != null)
                        isSubscribed = true;
                }
                
                newAttemptId = _common._pa_createNewAttempt(user_id, subscription_id, practice_id, (short)practice.CreditsNeeded, isSubscribed);
                if (newAttemptId <= 0) return (int)Message.NotAllowedToResource;

                qns = _common.GetPracticeAttemptPracticeQuestions(language_id, practice_id);
                qns.id = newAttemptId;

                return qns;
            }
            catch (Exception ex)
            {
                return (int)Message.Failure;
            }
        }

        /*
                public dynamic ReAttemptOfThePractice(int institute_id, int user_id, int practice_id)
                {
                    int newAttemptId = 0;
                    //Check practice validity            
                    Practices practice = _context.Practices.Where(p => p.Id == practice_id && p.InstituteId == institute_id
                                && p.IsActive == true && p.Status == StatusCode.PUBLISHED.ToString()).FirstOrDefault();

                    if (practice == null) return (int)Message.InvalidInput;


                    //total attempts taken
                    int attemptsTaken = 0;
                    List<PracticeAttempts> allLastAttempts = _context.PracticeAttempts.Where(a => a.PracticeId == practice_id && a.CreatedBy == user_id).ToList();

                    //1st attempt
                    if (allLastAttempts == null || allLastAttempts.Count == 0)
                    {
                        newAttemptId = _common._ea_createNewAttempt(user_id, exam_id, (int)exam.ExamDurationInSeconds);
                        if (newAttemptId <= 0) return null;
                        return _common.GetExamAttemptById(newAttemptId);
                    }

                    ExamAttempts lastAttempt = allLastAttempts.OrderByDescending(l => l.UpdatedOn).FirstOrDefault();
                    attemptsTaken = allLastAttempts.Count;
                    if (attemptsTaken < exam.AttemptsAllowed)
                    {
                        //last attempt is still not completed 
                        if (lastAttempt.Status == State.PAUSE) //Resume the paused attempt and start the same attempt
                        {
                            lastAttempt.Status = State.RESUME;
                            lastAttempt.UpdatedOn = _common.NowIndianTime();
                            _context.ExamAttempts.Update(lastAttempt);
                            _context.SaveChanges();

                            return _common.GetExamAttemptById(lastAttempt.Id);
                        }
                        //last attempt user left in between without pausing, so timer still running 
                        else if (lastAttempt.Status == State.START || lastAttempt.Status == State.RESUME) //check if time left, if so resume and start else complete it and start a new one
                        {
                            TimeSpan time_diff = (TimeSpan)(_common.NowIndianTime() - lastAttempt.UpdatedOn);
                            int time_diff_seconds = (int)time_diff.TotalSeconds;

                            lastAttempt.RemainingTimeSeconds -= time_diff_seconds;
                            if (lastAttempt.RemainingTimeSeconds < 0)
                            {
                                lastAttempt.RemainingTimeSeconds = 0;
                                lastAttempt.Status = State.COMPLETED;
                                lastAttempt.UpdatedOn = _common.NowIndianTime();
                                lastAttempt.UpdatedBy = user_id;
                                _context.ExamAttempts.Update(lastAttempt);
                                _context.SaveChanges();

                                newAttemptId = _common._ea_createNewAttempt(user_id, exam_id, (int)exam.ExamDurationInSeconds);
                                if (newAttemptId <= 0) return null;
                                return _common.GetExamAttemptById(newAttemptId);
                            }
                            else
                            {
                                lastAttempt.Status = State.RESUME;
                                lastAttempt.UpdatedOn = _common.NowIndianTime();
                                lastAttempt.UpdatedBy = user_id;
                                _context.ExamAttempts.Update(lastAttempt);
                                _context.SaveChanges();

                                return _common.GetExamAttemptById(lastAttempt.Id);
                            }
                        }
                        else
                        {
                            newAttemptId = _common._ea_createNewAttempt(user_id, exam_id, (int)exam.ExamDurationInSeconds);
                            if (newAttemptId <= 0) return null;
                            return _common.GetExamAttemptById(newAttemptId);
                        }
                    }

                    //if no more attempts allowed            
                    return (int)Message.InvalidOperation;
                }
        */

        public PracticeAttemptViewModel GetPracticeAttemptById(int institute_id, int attempt_id)
        {
            PracticeAttemptViewModel pav = new PracticeAttemptViewModel();

            pav = _common.GetPracticeAttemptById(institute_id, attempt_id);

            return pav;
        }

        public dynamic GetPracticeDetails(int institute_id, int user_id, int practice_id)
        {
            try
            {
                PracticeDetailViewModel details = new PracticeDetailViewModel();

                //Check practice validity            
                Practices practice = _context.Practices.Where(p => p.Id == practice_id && p.InstituteId == institute_id
                            && p.IsActive == true && p.Status == StatusCode.PUBLISHED.ToString() && (DateTime)p.OpenDatetime < _common.NowIndianTime()).FirstOrDefault();

                if (practice == null) return (int)Message.NotAllowedToResource;

                details.practice_id = practice.Id;
                details.practice_name = practice.Name;
                details.instruction = null;
                details.total_plays = _context.PracticeAttempts.Where(a => a.PracticeId == practice_id && a.IsActive == true).Select(l => l.CreatedBy).Distinct().Count();
                details.total_likes = _context.BookmarkedPractices.Where(b => b.PracticeId == practice_id && b.IsActive == true).ToList().Count;
                details.author_id = (int)practice.CreatedBy;
                details.total_questions = _context.PracticeQuestions.Where(q => q.PracticeId == practice_id && q.IsActive == true).Count();
                details.points_needed = (short)practice.CreditsNeeded;

                SubscriptionViewModel svm = _common.mySubscriptionDetails(user_id);
                if (svm == null)
                {
                    details.points_available = 0;
                    details.isSubscribed = false;
                }
                else
                {
                    details.points_available = svm.remaining_practice_credits;
                    SubscribedPractices subsPractice = _context.SubscribedPractices.Where(sp => sp.SubscriptionId == svm.id && sp.PracticeId == practice_id && sp.IsActive == true).FirstOrDefault();
                    details.isSubscribed = subsPractice != null ? true : false;
                }


                bool isBookmarked = false;
                BookmarkedPractices be = _context.BookmarkedPractices.Where(b => b.PracticeId == practice_id && b.UserId == user_id && b.IsActive == true).FirstOrDefault();
                if (be == null)
                {
                    isBookmarked = false;
                }
                else
                {
                    isBookmarked = (bool)be.IsActive;
                }
                details.isLiked = isBookmarked;

                Users author = _context.Users.Where(u => u.Id == practice.CreatedBy && u.IsActive == true).FirstOrDefault();
                if (author != null)
                {
                    details.author_name = author.FirstName;
                    details.author_image = author.Photo;
                }

                return details;
            }
            catch (Exception ex)
            {
                return (int)Message.Failure;
            }
        }


        public dynamic GetPracticeAttemptsCoverage(int institute_id, int batch_id, int user_id)
        {
            try
            {
                PracticeAttemptsCoverageViewModel coverage = new PracticeAttemptsCoverageViewModel();
                coverage.total_practices = 0;
                coverage.total_topics = 0;
                coverage.practices_covered = 0;
                coverage.total_topics = 0;

                Classes cls = (from m in _context.UserGroupMembers
                               join u in _context.UserGroups on m.UserGroupId equals u.Id
                               join c in _context.Classes on u.ClassId equals c.Id

                               where m.UserGroupId == batch_id && m.UserId == user_id && m.IsActive == true
                               && u.IsActive == true
                               && c.InstituteId == institute_id && c.IsActive == true

                               select c
                                    ).FirstOrDefault();

                if (cls == null) return (int)Message.NotAllowedToResource;

                List<int> topicIds = (from c in _context.Classes
                                      join s in _context.Subjects on c.Id equals s.ClassId
                                      join t in _context.Categories on s.Id equals t.SubjectId

                                      where c.Id == cls.Id
                                      && s.IsActive == true
                                      && t.IsActive == true

                                      select t.Id
                                   ).ToList();

                if (topicIds == null) return (int)Message.NoData;
                else coverage.total_topics = topicIds.Count();

                List<Practices> practices = (from a in _context.PracticeAttempts
                                             join p in _context.Practices on a.PracticeId equals p.Id

                                             where a.IsActive == true
                                             && topicIds.Contains(p.ModuleId)

                                             select p
                                                   ).ToList();

                if (practices == null || practices.Count == 0)
                    coverage.topics_covered = 0;
                else
                    coverage.topics_covered = practices.GroupBy(p => p.ModuleId).Select(p => p.FirstOrDefault()).ToList().Count();

                List<int> practiceIds = (from ugp in _context.UserGroupPractices
                                         join p in _context.Practices on ugp.PracticeId equals p.Id

                                         where ugp.UserGroupId == batch_id && ugp.IsActive == true
                                         && p.InstituteId == institute_id && p.Status == StatusCode.PUBLISHED.ToString()
                                         && p.ClassId == cls.Id && p.OpenDatetime <= _common.NowIndianTime() && p.IsActive == true

                                         select p.Id
                         ).ToList();

                if (practiceIds == null || practiceIds.Count == 0)
                    return (int)Message.NoData;

                coverage.total_practices = practiceIds.Count();

                List<PracticeAttempts> attempts = _context.PracticeAttempts.Where(a => a.IsActive == true && practiceIds.Contains(a.PracticeId)).ToList();

                if (attempts == null || attempts.Count == 0)
                    coverage.practices_covered = 0;
                else
                    coverage.practices_covered = attempts.GroupBy(a => a.PracticeId).Select(a => a.FirstOrDefault()).ToList().Count();

                return coverage;
            }
            catch
            {
                return (int)Message.Failure;
            }                        
        }

        public dynamic GetPracticeAttemptPracticeQuestions(int institute_id, int batch_id, int user_id, int language_id, int practice_id)
        {
            try
            {
                UserGroupPractices u = (from ugp in _context.UserGroupPractices
                          join p in _context.Practices on ugp.PracticeId equals p.Id
                          join ug in _context.UserGroups on ugp.UserGroupId equals ug.Id
                          join ugm in _context.UserGroupMembers on ug.Id equals ugm.UserGroupId

                          where ugp.UserGroupId == batch_id && ugp.PracticeId == practice_id && ugp.IsActive == true
                          && p.InstituteId == institute_id && p.Id == practice_id && p.IsActive == true
                          && ug.Id == batch_id && ug.IsActive == true
                          && ugm.UserId == user_id && ugm.UserGroupId == batch_id && ugm.IsActive == true
                          select ugp).FirstOrDefault();

                if (u == null)
                    return (int)Message.NotAllowedToResource;

                if (u.PracticeId != practice_id)
                {
                    return (int)Message.NotAllowedToResource;
                }

                Practices practices = _context.Practices.Where(p => p.Id == practice_id && p.IsActive == true).FirstOrDefault();
                if(practices == null)
                    return (int)Message.InvalidInput;

                if(practices.CreditsNeeded > 0)
                {
                    SubscriptionViewModel svm = _common.mySubscriptionDetails(user_id);
                    if (svm != null)
                        return (int)Message.NoValidSubscription;

                    SubscribedPractices subsPractice = _context.SubscribedPractices.Where(sp => sp.SubscriptionId == svm.id && sp.PracticeId == practice_id && sp.IsActive == true).FirstOrDefault();
                    bool isSubscribed = subsPractice != null ? true : false;

                    if (isSubscribed == false && svm.remaining_practice_credits < practices.CreditsNeeded)
                        return (int)Message.NotAllowedToResource;

                    if(isSubscribed == false)
                    {
                        _context.Database.BeginTransaction();

                        Subscriptions subscriptions = _context.Subscriptions.Where(s => s.Id == svm.id).FirstOrDefault();
                        subscriptions.RemainingExamCredits -= practices.CreditsNeeded;
                        _context.Subscriptions.Update(subscriptions);
                        _context.SaveChanges();

                        SubscribedPractices sp = new SubscribedPractices();
                        sp.SubscriptionId = svm.id;
                        sp.PracticeId = practice_id;
                        sp.CreatedBy = user_id;
                        sp.CreatedOn = _common.NowIndianTime();
                        sp.UpdatedBy = user_id;
                        sp.UpdatedOn = _common.NowIndianTime();
                        sp.IsActive = true;

                        _context.SubscribedPractices.Add(sp);
                        _context.SaveChanges();

                        _context.Database.CommitTransaction();
                    }
                }

                return _common.GetPracticeAttemptPracticeQuestions(language_id, practice_id);
            }
            catch (Exception ex)
            {
                _context.Database.RollbackTransaction();
                return (int)Message.Failure;
            }            
        }

        public dynamic EndPractice(int institute_id, int user_id, int attempt_id,  PracticeAttemptResultModel report)
        {
            CorrectnessCount cc = new CorrectnessCount();

            cc.nCorrect = -1;
            cc.nIncorrect = -1;

            //check if attempt is ongoing or not, check if attempt owner is user_id
            //update the result and return correct count
            try
            {
                _context.Database.BeginTransaction();

                PracticeAttempts attempts = (from a in _context.PracticeAttempts
                                             join p in _context.Practices on a.PracticeId equals p.Id

                                             where a.Id == attempt_id && a.Status != State.COMPLETED && a.CreatedBy == user_id && a.IsActive == true
                                             && p.IsActive == true && p.InstituteId == institute_id

                                             select a
                                    ).FirstOrDefault();

                if (attempts == null) return (int)Message.NotAllowedToResource;
                
                if (attempts.Status == State.START || attempts.Status == State.RESUME)
                {
                    attempts.CorrectCount = report.correct_count;
                    attempts.IncorrectCount = report.incorrect_count;
                    attempts.UnattemptedCount = report.unattempted_count;
                    attempts.ExpiredCount = report.expired_count;
                    attempts.UpdatedOn = _common.NowIndianTime();
                    attempts.UpdatedBy = user_id;
                    attempts.Status = State.COMPLETED;

                    _context.Entry(attempts).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
                    _context.SaveChanges();
                }

                _context.Database.CommitTransaction();
                cc.nCorrect = (int)attempts.CorrectCount;
                cc.nIncorrect = (int)attempts.IncorrectCount;
            }
            catch
            {
                _context.Database.RollbackTransaction();
                return (int)Message.Failure;
            }

            return cc;
        }

        public int AttachBookmarkToPractices(int institute_id, int batch_id, int user_id, int practice_id, out string return_message)
        {
            try
            {

                int id = (from ugp in _context.UserGroupPractices
                                 join p in _context.Practices on ugp.PracticeId equals p.Id
                                 join ug in _context.UserGroups on ugp.UserGroupId equals ug.Id
                                 join ugm in _context.UserGroupMembers on ug.Id equals ugm.UserGroupId

                                 where ugp.UserGroupId == batch_id && ugp.PracticeId == practice_id && ugp.IsActive == true
                                 && p.InstituteId == institute_id && p.Id == practice_id && p.IsActive == true
                                 && ug.Id == batch_id && ug.IsActive == true
                                 && ugm.UserId == user_id && ugm.UserGroupId == batch_id && ugm.IsActive == true
                                 select ugp).FirstOrDefault().PracticeId;

                if(id != practice_id)
                {
                    return_message = string.Format("Invalid details ");
                    return (int)Message.NotAllowedToResource;
                }

                List<BookmarkedPractices> listBP = _common.GetBookmarkedPractice(user_id, practice_id);
                
                if (listBP != null && listBP.Count > 0)
                {
                    return_message = string.Format("already bookmarked ");
                    return 1; //Its already there, so don't add this one again
                }
                else
                {
                    _context.Database.BeginTransaction();
                    BookmarkedPractices bp = new BookmarkedPractices()
                    {
                        PracticeId = practice_id,
                        UserId = user_id,
                        CreatedOn = _common.NowIndianTime(),
                        CreatedBy = user_id,
                        IsActive = true
                    };
                    
                    _context.BookmarkedPractices.Add(bp);
                    _context.SaveChanges();

                    _context.Database.CommitTransaction();
                }

                return_message = string.Format("the practice is bookmarked");
            }
            catch (Exception ex)
            {
                _context.Database.RollbackTransaction();
                return_message = ex.InnerException.ToString();
                return (int)Message.Failure;
            }

            return 1;
        }


        public int DetachBookmarkFromPractices(int institute_id, int batch_id, int user_id, int practice_id, out string return_message)
        {
            try
            {
                int id = (from ugp in _context.UserGroupPractices
                          join p in _context.Practices on ugp.PracticeId equals p.Id
                          join ug in _context.UserGroups on ugp.UserGroupId equals ug.Id
                          join ugm in _context.UserGroupMembers on ug.Id equals ugm.UserGroupId

                          where ugp.UserGroupId == batch_id && ugp.PracticeId == practice_id && ugp.IsActive == true
                          && p.InstituteId == institute_id && p.Id == practice_id && p.IsActive == true
                          && ug.Id == batch_id && ug.IsActive == true
                          && ugm.UserId == user_id && ugm.UserGroupId == batch_id && ugm.IsActive == true
                          select ugp).FirstOrDefault().PracticeId;

                if (id != practice_id)
                {
                    return_message = string.Format("Invalid details ");
                    return (int)Message.NotAllowedToResource;
                }

                List<BookmarkedPractices> listBP = _common.GetBookmarkedPractice(user_id, practice_id);

                if (listBP == null || listBP.Count == 0)
                {
                    return_message = string.Format("its not bookmarked ");
                    return 1; //Its already there, so don't add this one again
                }
                else
                {
                    //_context.Database.BeginTransaction();
                    //_context.BookmarkedPractices.Remove(bp);
                    _context.BulkDelete(listBP);

                    //_context.SaveChanges();
                    //_context.Database.CommitTransaction();
                }

                return_message = string.Format("the practice is removed");
            }
            catch (Exception ex)
            {
                _context.Database.RollbackTransaction();
                return_message = ex.InnerException.ToString();
                return (int)Message.Failure;
            }

            return 1;
        }

        public int RaiseQuestionBug(int institute_id, int user_id, int attempt_id, int question_id, string source, string title, string description, out string return_message)
        {
            try
            {
                int id = (from pa in _context.PracticeAttempts
                          join p in _context.Practices on pa.PracticeId equals p.Id
                          join pq in _context.PracticeQuestions on p.Id equals pq.PracticeId
                          
                          where pa.IsActive == true && pa.CreatedBy == user_id
                          && p.InstituteId == institute_id
                          && pq.QuestionId == question_id
                          select pq).FirstOrDefault().QuestionId;

                if (id != question_id)
                {
                    return_message = string.Format("Invalid details ");
                    return (int)Message.NotAllowedToResource;
                }

                _context.Database.BeginTransaction();
                QuestionBugs qb = new QuestionBugs()
                {
                    QuestionId = question_id,
                    Source = "App",
                    BugTitle = title,
                    BugDescription = description,
                    Status = "Initiated",
                    CreatedOn = _common.NowIndianTime(),
                    CreatedBy = user_id,
                    UpdatedOn = _common.NowIndianTime(),
                    UpdatedBy = user_id,
                    IsActive = true
                };
                
                _context.QuestionBugs.Add(qb);
                _context.SaveChanges();
                
                _context.Database.CommitTransaction();

                return_message = string.Format("the bug is raised");
            }
            catch (Exception ex)
            {
                _context.Database.RollbackTransaction();
                return_message = ex.InnerException.ToString();
                return (int)Message.Failure;
            }

            return 1;
        }

        #endregion

    }
}
