using AutoMapper;
using Microsoft.EntityFrameworkCore;
using OnlineAssessment.Common;
using OnlineAssessment.Domain.Models;
using OnlineAssessment.Domain.ViewModels;
using Razorpay.Api;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace OnlineAssessment.Data.EFCore
{
    public class EfCoreCommonRepository : EfCoreRepository<Users, OnlineAssessmentContext>
    {
        //public static OnlineAssessmentContext _context;
        private readonly IMapper _mapper;
        public readonly OnlineAssessmentContext _context;
        public EfCoreCommonRepository(OnlineAssessmentContext context) : base(context)
        {
            _context = context;
        }

        public EfCoreCommonRepository(OnlineAssessmentContext context, IMapper mapper) : base(context)
        {
            _context = context;
            _mapper = mapper;
        }

        public DateTime NowIndianTime()
        {
            TimeZoneInfo INDIAN_ZONE = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
            DateTime indianTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, INDIAN_ZONE);

            return indianTime;
        }

        // Method to remove accents (diacritics)
        public static string RemoveAccents(string value)
        {
            string normalizedString = value.Normalize(NormalizationForm.FormD);
            StringBuilder stringBuilder = new StringBuilder();

            foreach (char c in normalizedString)
            {
                if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(c);
                }
            }

            return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
        }

        public string convertToSlug(string value)
        {

            //First to lower case 
            value = value.ToLowerInvariant();

            // Step 2: Remove accents (diacritics)
            value = RemoveAccents(value);

            //Replace spaces 
            value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);

            //Remove invalid chars 
            value = Regex.Replace(value, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled);

            //Trim dashes from end 
            value = value.Trim('-', '_');

            //Replace double occurences of - or \_ 
            value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);

            return value;
        }

        public bool CheckIfUserExist(int user_id, int institute_id)
        {
            UserViewModel user = GetUserById(institute_id, user_id);
            if (user == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }


        internal bool isUser(int institute_id, int user_id)
        {
            bool isExist = false;
            Users users = _context.Users.Where(u => u.Id == user_id && u.InstituteId == institute_id).FirstOrDefault();

            if (users != null) isExist = true;

            return isExist;            
        }


        /// <summary>
        /// Get user details
        /// </summary>
        /// <param name="id">Id of the user for whom the information need to be sent</param>
        /// <returns>Details of the user</returns>
        internal UserViewModel GetUserById(int institute_id, int user_id)
        {
            UserViewModel returnUser = null;
            try
            {
                //Users user = _context.Users.FirstOrDefault(u => u.Id == id);
                returnUser = (from u in _context.Users 
                                     
                                      where u.Id == user_id && u.InstituteId == institute_id

                                      select new UserViewModel
                                      {
                                          id = u.Id,
                                          institute_id = u.InstituteId,
                                          role = _context.Roles.Where(r => r.Id == u.RoleId).FirstOrDefault().Code,
                                          language_code = _context.Languages.Where(l => l.Id == u.LanguageId).FirstOrDefault().Code,
                                          registration_id = u.RegistrationId,
                                          registration_from = u.RegistrationDatetime,
                                          first_name = u.FirstName,
                                          last_name = u.LastName,
                                          gender = u.Gender,
                                          email_id = u.EmailId,
                                          mobile_no = u.MobileNo,
                                          dob = u.DateOfBirth,
                                          photo = u.Photo,

                                          isActive = u.IsActive

                                      }).FirstOrDefault();
                                     
            }
            catch (Exception ex)
            {
                returnUser = null;
                throw new Exception(ex.Message);

            }

            return returnUser;
        }

        internal bool isValidBatch(int institute_id, int batch_id, int user_id)
        {
            UserGroups userGroup = _context.UserGroups.Where(ug => ug.Id == batch_id && ug.IsActive == true).FirstOrDefault();
            if (userGroup == null) return false;
            UserGroupMembers userGroupMembers = _context.UserGroupMembers.Where(ugm => ugm.UserGroupId == userGroup.Id && ugm.UserId == user_id).FirstOrDefault();
            if (userGroupMembers == null) return false;

            return true;

        }


        internal bool isValidExam(int institute_id, int exam_id, int user_id)
        {
            List<int> uge = _context.UserGroupExams.Where(e => e.ExamId == exam_id && e.IsActive == true).Select(e => e.UserGroupId).ToList();
            List<int> ugm = _context.UserGroupMembers.Where(m => m.UserId == user_id && uge.Contains(m.UserGroupId)).Select(m => m.UserGroupId).ToList();

            if (ugm == null || ugm.Count == 0) return false;

            return true;
        }


        internal int getValidClassID(int institute_id, int batch_id, int user_id)
        {
            int class_id = -1;

            try
            {
                class_id = (from ugm in _context.UserGroupMembers
                            join ug in _context.UserGroups on ugm.UserGroupId equals ug.Id
                            join c in _context.Classes on ug.ClassId equals c.Id

                            where ugm.UserGroupId == batch_id && ugm.UserId == user_id && ugm.IsActive == true
                            && ug.IsActive == true
                            && c.InstituteId == institute_id && c.IsActive == true

                            select c.Id

                              ).FirstOrDefault();

            }
            catch (Exception ex)
            {
                class_id = -1;
                throw new Exception(ex.Message);

            }

            return class_id;

        }


        /// <summary>
        /// Get user details
        /// </summary>
        /// <param name="id">Id of the user for whom the information need to be sent</param>
        /// <returns>Details of the user</returns>
        internal UserViewModel GetUserById(int user_id)
        {
            UserViewModel returnUser = null;
            try
            {
                //Users user = _context.Users.FirstOrDefault(u => u.Id == id);
                returnUser = (from u in _context.Users

                              where u.Id == user_id

                              select new UserViewModel
                              {
                                  id = u.Id,
                                  institute_id = u.InstituteId,
                                  role = _context.Roles.Where(r => r.Id == u.RoleId).FirstOrDefault().Code,
                                  language_code = _context.Languages.Where(l => l.Id == u.LanguageId).FirstOrDefault().Code,
                                  registration_id = u.RegistrationId,
                                  registration_from = u.RegistrationDatetime,
                                  first_name = u.FirstName,
                                  last_name = u.LastName,
                                  gender = u.Gender,
                                  email_id = u.EmailId,
                                  mobile_no = u.MobileNo,
                                  dob = u.DateOfBirth,
                                  photo = u.Photo,

                                  isActive = u.IsActive

                              }).FirstOrDefault();

            }
            catch (Exception ex)
            {
                returnUser = null;
                throw new Exception(ex.Message);

            }

            return returnUser;
        }



        /// <summary>
        /// Get user details
        /// </summary>
        /// <param name="id">Id of the user for whom the information need to be sent</param>
        /// <returns>Details of the user</returns>
        internal LoginViewModel GetLoginDetails(int id)
        {
            LoginViewModel returnUser = null;
            try
            {
                Users user = _context.Users.FirstOrDefault(u => u.Id == id);
                if(user == null)
                {
                    return null;
                }

                //Roles role = _context.Roles.FirstOrDefault(r => r.Id == user.RoleId);
                Institutes institute = _context.Institutes.FirstOrDefault(i => i.Id == user.InstituteId);
                
                string languageCode = null;
                Languages language = _context.Languages.FirstOrDefault(l => l.Id == user.LanguageId);
                if (language != null) languageCode = language.Code;

                /*SUBSDELETE
                string plan_code = null;
                string plan_name = null;
                SubscriptionViewModel svm = mySubscriptionDetails(user.Id);
                if (svm != null)
                {
                    plan_code = svm.plan_code;
                    plan_name = svm.plan_name;
                }
                */


                returnUser = new LoginViewModel
                {
                    id = user.Id,
                    email_id = user.EmailId,
                    mobile_num = user.MobileNo,
                    role_id = user.RoleId,
                    role_name = Security.GetRoleNameById(user.RoleId),
                    institute_id = user.InstituteId,
                    institute_name = institute.Name,
                    institute_logo = institute.ImageUrlSmall,
                    language_code = languageCode,
                    first_name = user.FirstName,
                    last_name = user.LastName,
                    gender = user.Gender,
                    state = user.StateCode,
                    city = user.City,
                    batch_id = user.BatchId,
                    batch_name = user.BatchId == null ? null : _context.UserGroups.FirstOrDefault(g => g.Id == user.BatchId).Name,
                    //current_plan_code = plan_code,
                    //current_plan_name = plan_name,
                    IsActive = user.IsActive
                };

            }
            catch (Exception ex)
            {
                returnUser = null;
                throw new Exception(ex.Message);

            }

            return returnUser;
        }




        internal UserGroupViewModel GetUserGroupById(int institute_id, int id)
        {

            UserGroupViewModel userGroup = (from ug in _context.UserGroups
                                            join c in _context.Classes on ug.ClassId equals c.Id
                                            //join cl in _context.ClassLanguages on c.Id equals cl.ClassId
                                             
                                            where ug.Id == id && ug.IsActive == true
                                                
                                                && c.InstituteId == institute_id && c.IsActive == true
                                                //&& cl.IsActive == true
                                            select new UserGroupViewModel
                                            {
                                                id = ug.Id,
                                                class_id = ug.ClassId,
                                                class_name = c.Name,
                                                name = ug.Name,
                                                description = ug.Description,
                                                photo = ug.Photo,
                                                created_on = ug.CreatedOn,
                                                updated_on = ug.UpdatedOn,
                                                isActive = ug.IsActive                                               
                                            }).FirstOrDefault();

            if (userGroup == null) return null;

            userGroup.user_count = (from ugm in _context.UserGroupMembers
                                      join u in _context.Users on ugm.UserId equals u.Id

                                      where ugm.UserGroupId == userGroup.id && ugm.IsActive == true
                                              && u.IsActive == true

                                      select u).ToList().Count;

            userGroup.exam_count = (from uge in _context.UserGroupExams
                                    join e in _context.Exams on uge.ExamId equals e.Id

                                    where uge.UserGroupId == userGroup.id && uge.IsActive == true
                                            && e.IsActive == true && e.ExamStatus.ToUpper() == StatusCode.PUBLISHED.ToString() 
                                            && e.ExamCloseDatetime > NowIndianTime()

                                    select e).ToList().Count;


            return userGroup;
        }


        internal UserGroupMembers GetUserGroupMembers(int user_group_id, int user_id)
        {
            UserGroupMembers userGroupMembers = _context.UserGroupMembers.Where(a => a.UserId == user_id && a.UserGroupId == user_group_id).FirstOrDefault();
            return userGroupMembers;
        }

        internal List<UserGroups> GetClassUserGroups(int class_id)
        {
            List<UserGroups> userGroups = _context.UserGroups.Where(u => u.ClassId == class_id && u.IsActive == true).ToList();
            return userGroups;
        }

        /*
        internal SubCategories GetSubCategorById(int id)
        {
            SubCategories subcategories = _context.SubCategories.Where(s => s.Id == id).FirstOrDefault();
            return subcategories;
        }
        */

        internal Language GetLanguageById(int? languageId)
        {
            Language userLanguage = null;
            Languages userLanguages = _context.Languages.AsNoTracking().Where(c => c.Id == languageId).FirstOrDefault();
            if (userLanguages != null)
            {
                userLanguage = new Language();
                userLanguage.Id = languageId;
                userLanguage.Name = userLanguages.Name;
                userLanguage.Code = userLanguages.Code;
                userLanguage.IsActive = userLanguages.IsActive;
            }

            return userLanguage;
        }

        internal Language GetLanguageByCode(string code)
        {
            Language userLanguage = null;
            
            Languages userLanguages = _context.Languages.AsNoTracking().Where(c => c.Code == code).
                                                                        Where(c => c.IsActive == true).FirstOrDefault();
            if (userLanguages != null)
            {
                userLanguage = new Language();
                userLanguage.Id = userLanguages.Id;
                userLanguage.Name = userLanguages.Name;
                userLanguage.Code = userLanguages.Code;
                userLanguage.IsActive = userLanguages.IsActive;
            }

            return userLanguage;
        }

        internal Plans GetPlanByCode(int institute_id, string code)
        {
            Plans plans = _context.Plans.Where(p => p.Code == code && 
                            p.InstituteId == institute_id && 
                            p.IsActive == true).FirstOrDefault();
            return plans;
        }


        internal QuestionType GetQuestionTypeById(int? questiontypeId)
        {
            QuestionType questionType = null;
            var questionTypes = _context.QuestionTypes.AsNoTracking().Where(q => q.Id == questiontypeId).ToList();
            if (questionTypes != null && questionTypes.Count > 0)
            {
                questionType = new QuestionType();
                questionType.Id = questiontypeId;
                questionType.Code = questionTypes[0].Code;
                questionType.Name = questionTypes[0].Name;
                questionType.IsActive = questionTypes[0].IsActive;
            }

            return questionType;
        }

        internal QuestionType GetQuestionTypeByCode(string code)
        {
            QuestionType qtype = null;
            QuestionTypes qtypes = _context.QuestionTypes.AsNoTracking().Where(q => q.Code == code).
                                                                        Where(q => q.IsActive == true).FirstOrDefault();
            if (qtypes != null)
            {
                qtype = new QuestionType();
                qtype.Id = qtypes.Id;
                qtype.Name = qtypes.Name;
                qtype.Code = qtypes.Code;
                qtype.IsActive = qtypes.IsActive;
            }

            return qtype;
        }

        internal string GetCountryByStateId(int? stateId)
        {
            return "INDIA";
        }

        internal ExamType GetExamTypeById(int? examtypeId)
        {
            ExamType examType = null;
            ExamTypes examTypes = _context.ExamTypes.AsNoTracking().Where(q => q.Id == examtypeId).FirstOrDefault();
            if (examTypes != null)
            {
                examType = new ExamType();
                examType.Id = examtypeId;
                examType.Code = examTypes.Code;
                examType.Name = examTypes.Name;
                examType.Description = examTypes.Description;
                examType.IsActive = examTypes.IsActive;
            }

            return examType;
        }
        

        //internal UserClass GetClassDetailsByClassId(int classId, int userId)
        //{
        //    UserClass userClass = null;
        //    var classes = _context.Classes.AsNoTracking().Where(c => c.Id == classId).ToList();
        //    if (classes != null && classes.Count > 0)
        //    {
        //        userClass = new UserClass();

        //        userClass.UserId = userId;
        //        userClass.ClassId = classId;
        //        userClass.Name = classes[0].Name;
        //        userClass.Description = classes[0].Description;
        //    }

        //    return userClass;
        //}

        //internal UserSubject GetUserSubjectDetailsBySubjectId(int subjectId, int userId)
        //{
        //    UserSubject userSubject = null;
        //    //var userSubjects = _context.UserSubjects.AsNoTracking().Where(user_subject => user_subject.Id == subjectId).ToList();
        //    //if (!(userSubjects == null || userSubjects.Count.Equals(0)))
        //    //{
        //    //Get the subject details
        //    var subjects = _context.Subjects.AsNoTracking().Where(s => s.Id == subjectId).ToList();
        //    if (subjects != null && subjects.Count > 0)
        //    {

        //        //Get the class of the subject
        //        var classes = _context.Classes.AsNoTracking().Where(c => c.Id == subjects[0].ClassId).ToList();
        //        if (classes != null && classes.Count > 0)
        //        {
        //            userSubject = new UserSubject
        //            {
        //                Id = subjects[0].Id,
        //                UserId = userId,

        //                ClassId = classes[0].Id,
        //                ClassName = classes[0].Name,
        //                ClassDescription = classes[0].Description,

        //                SubjectId = subjects[0].Id,
        //                //SubjectName = subjects[0].Name,
        //                //SubjectDescription = subjects[0].Description
        //            };
        //        }
        //        int languageId = 0;
        //        var subjectLanguages = _context.SubjectLanguages.AsNoTracking().Where(c => c.SubjectId == userSubject.SubjectId).ToList();
        //        if (classes != null && classes.Count > 0)
        //        {
        //            languageId = subjectLanguages[0].LanguageId;
        //            userSubject.SubjectName = subjectLanguages[0].Name;
        //            userSubject.SubjectDescription = subjectLanguages[0].Description;

        //        }

        //        var languages = _context.Languages.AsNoTracking().Where(c => c.Id == languageId).ToList();
        //        if (languages != null && languages.Count > 0)
        //        {
        //            userSubject.LanguageId = languageId;
        //            userSubject.LanguageName = languages[0].Name;
        //        }
        //    }
        //    //}

        //    return userSubject;
        //}



        internal UserBookmarks GetUserBookmarksByUserId(int userId)
        {
            UserBookmarks userBookmarks = null;


            return userBookmarks;
        }

        internal Logs GetUserLogsUserId(int id)
        {
            Logs logs = new Logs();
            List<UserLog> userLogs = new List<UserLog>();
            List<ActivityLog> activityLogs = new List<ActivityLog>();

            logs.UserLogs = userLogs;
            logs.ActivityLogs = activityLogs;

            return logs;
        }

        //internal List<UserSubject> GetUserSubjectsByUserId(int id)
        //{
        //    List<UserSubject> userSubjects = new List<UserSubject>();
        //    var subjects = _context.UserSubjects.AsNoTracking().Where(u => u.UserId == id).ToList();
        //    if (!(subjects == null || subjects.Count.Equals(0)))
        //    {
        //        for (int x = 0; x < subjects.Count; x++)
        //        {
        //            UserSubject userSubject = GetUserSubjectDetailsBySubjectId(subjects[x].SubjectId, id);
        //            userSubjects.Add(userSubject);
        //        }
        //    }
        //    return userSubjects;
        //}

        //internal List<UserClass> GetUserClassesByUserId(int id)
        //{
        //    List<UserClass> userClasses = new List<UserClass>();
        //    var classes = _context.ClassesUsers.AsNoTracking().Where(c => c.UserId == id).ToList();
        //    if (!(classes == null || classes.Count.Equals(0)))
        //    {
        //        for (int x = 0; x < classes.Count; x++)
        //        {
        //            UserClass userClass = new UserClass();
        //            userClass = GetClassDetailsByClassId(classes[0].ClassId, id);
        //            userClasses.Add(userClass);
        //        }
        //    }
        //    return userClasses;
        //}

        internal Role GetRoleDetailByRoleId(int roleId)
        {
            Role userRole = new Role();
            var roles = _context.Roles.AsNoTracking().Where(r => r.Id == roleId).ToList();
            if (!(roles == null || roles.Count.Equals(0)))
            {
                Roles role = roles[0];
                userRole.Id = role.Id;
                userRole.AccessLevel = role.AccessLevel;
                userRole.Name = role.Name;
                userRole.Description = role.Description;

                return userRole;

            }
            else
            {
                return null;

            }
        }

        internal InstituteViewModel GetInstituteDetailById(int instituteId)
        {
            Institutes institutes = _context.Institutes.Where(i => i.Id == instituteId).FirstOrDefault();
            InstituteViewModel institute = _mapper.Map<Institutes, InstituteViewModel>(institutes);
            if (institute != null)
            {
                institute.State = GetStateById(institute.StateId);
                institute.Country = GetCountryByStateId(institute.StateId);
            }
            return institute;
        }

        private string GetStateById(int stateId)
        {
            string stateName = string.Empty;
            States states = _context.States.Where(s => s.Id == stateId).FirstOrDefault();
            if (states != null)
            {
                stateName = states.Name;
            }
            return stateName;
        }


        //Calculate complexity
        internal int _calculateComplexity(int? input)
        {
            int output = -1;

            if (input == null)
            {
                output = (int)COMPLEXITY.EASY;
            }
            else if (input > (int)COMPLEXITY.DIFFICULT)
            {
                output = (int)COMPLEXITY.DIFFICULT;
            }
            else if (input < (int)COMPLEXITY.EASY)
            {
                output = (int)COMPLEXITY.EASY;
            }
            else
            {
                output = (int)input;
            }

            return output;
        }

        internal SubjectViewModel GetSubjectByName(int institute_id, int class_id, string subject_name)
        {

            SubjectViewModel result = (from s in _context.Subjects
                                       join c in _context.Classes on s.ClassId equals c.Id

                                       where c.InstituteId == institute_id && c.Id == class_id && c.IsActive == true
                                       && s.Name == subject_name && s.IsActive == true

                                       select new SubjectViewModel
                                       {
                                           id = s.Id,
                                           name = s.Name,
                                           isActive = s.IsActive,
                                           last_updated = s.UpdatedOn
                                       }).FirstOrDefault();

            return result;
        }

        internal SubjectViewModel GetSubjectById(int institute_id, int subject_id)
        {
            SubjectViewModel result = (from s in _context.Subjects
                                       join c in _context.Classes on s.ClassId equals c.Id
                                       
                                       where c.InstituteId == institute_id && s.Id == subject_id
                                       select new SubjectViewModel
                                       {
                                           id = s.Id,
                                           name = s.Name,
                                           isActive = s.IsActive,
                                           last_updated = s.UpdatedOn
                                       }).FirstOrDefault();

            return result;

        }

        internal CategoryViewModel GetCategoryById(int institute_id, int categoryId)
        {
            CategoryViewModel category = (from c in _context.Categories
                                 join s in _context.Subjects on c.SubjectId equals s.Id
                                 join cls in _context.Classes on s.ClassId equals cls.Id
                                 where c.Id == categoryId && c.IsActive == true
                                       && cls.InstituteId == institute_id && cls.IsActive == true
                                       
                                 select new CategoryViewModel
                                 {
                                     id = c.Id,
                                     name = c.Name,
                                     isActive = c.IsActive,
                                     last_updated = c.UpdatedOn
                                 }
                          ).FirstOrDefault();

            return category;
        }
/*
        internal SubCategoryViewModel GetSubCategoryById(int institute_id, int language_id, int subCategoryId)
        {
            SubCategoryViewModel subCategoryViewModel = (from sc in _context.SubCategories
                                                         join scl in _context.SubCategoryLanguages on sc.Id equals scl.SubcategoryId
                                                         join c in _context.Categories on sc.CategoryId equals c.Id
                                                         join s in _context.Subjects on c.SubjectId equals s.Id
                                                         join cls in _context.Classes on s.ClassId equals cls.Id
                                                         where sc.Id == subCategoryId && sc.IsActive == true
                                                                && cls.InstituteId == institute_id && cls.IsActive == true
                                                                && scl.LanguageId == language_id && scl.IsActive == true
                                                         select new SubCategoryViewModel
                                                         {
                                                             Id = sc.Id,
                                                             Name = scl.Name,
                                                             Description = scl.Description,

                                                             IsActive = c.IsActive
                                                         }
                          ).FirstOrDefault();

            return subCategoryViewModel;
        }
*/
        internal ClassViewModel GetClassByName(int institute_id, string class_name)
        {
            ClassViewModel cvm = (from c in _context.Classes
                                  where c.Name == class_name && c.InstituteId == institute_id && c.IsActive == true

                                  select new ClassViewModel
                                  {
                                      id = c.Id,
                                      name = c.Name,
                                      isActive = c.IsActive
                                  }).FirstOrDefault();

            return cvm;
        }


        internal ClassViewModel GetClassById(int institute_id, int class_id)
        {
            ClassViewModel cvm = (from c in _context.Classes
                                  where c.Id == class_id && c.InstituteId == institute_id && c.IsActive == true

                                  select new ClassViewModel
                                  {
                                      id = c.Id,
                                      name = c.Name,
                                      isActive = c.IsActive
                                  }).FirstOrDefault();

            return cvm;
        }


        internal ClassViewModel GetAnyClassById(int institute_id, int class_id)
        {
            ClassViewModel cvm = (from c in _context.Classes
                                     where c.Id == class_id && c.InstituteId == institute_id
                                            && c.IsActive == true

                                     select new ClassViewModel
                                     {
                                         id = c.Id,
                                         name = c.Name,
                                         isActive = c.IsActive 
                                     }).FirstOrDefault();

            return cvm;
        }

        internal TagViewModel GetTagById(int institute_id, int tag_id)
        {
            TagViewModel tag = (from t in _context.Tags
                                where t.InstituteId == institute_id && t.Id == tag_id
                                select new TagViewModel
                                {
                                    id = t.Id,
                                    name = t.Name,                                    
                                    last_updated = t.UpdatedOn
                                }
                        ).FirstOrDefault();

            return tag;

        }

        internal QuestionViewModel GetQuestionById(int institute_id, int language_id, int question_Id)
        {
           

            QuestionViewModel qvm = (from q in _context.Questions
                                     join ql in _context.QuestionLanguges on q.Id equals ql.QuestionId
                                     join u in _context.Users on q.AuthorId equals u.Id
                                     join t in _context.QuestionTypes on q.TypeId equals t.Id
                                     join qc in _context.QuestionCategories on q.Id equals qc.QuestionId
                                     join c in _context.Categories on qc.CategoryId equals c.Id
                                     join sub in _context.Subjects on c.SubjectId equals sub.Id

                                     where q.InstituteId == institute_id && q.Id == question_Id && q.IsActive == true
                                     && ql.LanguageId == language_id && ql.IsActive == true 
                                     && t.IsActive == true
                                     && c.IsActive == true
                                     && sub.IsActive == true
                                     
                                     select new QuestionViewModel
                                     {
                                         id = q.Id,
                                         title = ql.Question,
                                         status = q.StatusCode,
                                         complexity_code = q.ComplexityCode,

                                         source = q.Source,
                                         type = t.Code,
                                         type_name = t.Name,
                                         author_id = q.AuthorId,
                                         author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                         //TODO: after db change effect -> Hint = ql.Hint,
                                         //TODO: after db change effect -> AnswerOptionId = q.AnswerOptionId,
                                         answer_explanation = ql.AnswerExplanation,
                                         isActive = q.IsActive,
                                         subject_id = sub.Id,
                                         subject_name = sub.Name,
                                         topic_id = c.Id,
                                         topic_name = c.Name,
                                         last_updated = ql.UpdatedOn,
                                         languages_available = _context.QuestionLanguges.
                                                            Where(l => l.QuestionId == q.Id && l.IsActive == true).Select(l => l.LanguageId).ToList()
                                     }
                                     ).FirstOrDefault();



            List<QuestionOptionViewModel> qovm = (from qo in _context.QuestionOptions
                                                  join qol in _context.QuestionOptionLanguages on qo.Id equals qol.QuestionOptionId
                                                  
                                                  where qo.QuestionId == question_Id && qo.IsActive == true
                                                  && qol.IsActive == true && qol.LanguageId == language_id

                                                  select new QuestionOptionViewModel
                                                  {
                                                      id = qo.Id,
                                                      //LanguageId = qol.LanguageId,
                                                      text = qol.OptionText,
                                                      isCorrect = qo.IsCorrect
                                                  }
                                                  ).ToList();



            if (qvm != null && qovm != null)
            {
                qvm.options = qovm;
            }


            List<TagViewModel> tvm = (from qt in _context.QuestionTags
                                                  join t in _context.Tags on qt.Id equals t.Id

                                                  where qt.IsActive == true && qt.QuestionId == question_Id
                                                  && t.IsActive == true

                                                  select new TagViewModel
                                                  {
                                                      id = t.Id,
                                                      name = "TBD"
                                                  }
                                                  ).ToList();



            if (tvm != null && tvm.Count > 0)
            {
                qvm.tags = tvm;
            }

            return qvm;

        }


        internal QuestionCategories GetQuestionCategory(int category_id, int question_id)
        {
            QuestionCategories questionCategories = _context.QuestionCategories.Where(a => a.QuestionId == question_id && a.CategoryId == category_id).FirstOrDefault();
            return questionCategories;
        }

        internal ExamSections GetExamSection(int exam_id, int section_id)
        {
            ExamSections examSections = _context.ExamSections.Where(a => a.ExamId == exam_id && a.SubjectId == section_id && a.IsActive == true).FirstOrDefault();
            return examSections;
        }

        internal QuestionTags GetQuestionTag(int tag_id, int question_id)
        {
            QuestionTags questionTags = _context.QuestionTags.Where(a => a.QuestionId == question_id && a.TagId == tag_id).FirstOrDefault();
            return questionTags;
        }

        internal Questions GetQuestionOfAnInstitute(int institute_id, int language_id, int question_id)
        {
            //Questions questions = _context.Questions.Where(a => a.Id == question_id && a.InstituteId == institute_id).FirstOrDefault();
            Questions questions = (from q in _context.Questions
                                  join ql in _context.QuestionLanguges on q.Id equals ql.QuestionId
                                  where q.Id == question_id && q.InstituteId == institute_id && q.IsActive == true
                                        && ql.LanguageId == language_id && ql.IsActive == true

                                  select q).FirstOrDefault();

            return questions;
        }

        internal BookmarkedQuestions GetBookmarkedQuestion(int user_id, int question_id)
        {
            BookmarkedQuestions questions = _context.BookmarkedQuestions.Where(a => a.UserId == user_id && a.QuestionId == question_id).FirstOrDefault();
            return questions;
        }

        internal List<BookmarkedPractices> GetBookmarkedPractice(int user_id, int practice_id)
        {
            List<BookmarkedPractices> practices = _context.BookmarkedPractices.Where(a => a.UserId == user_id && a.PracticeId == practice_id && a.IsActive == true).ToList();
            return practices;
        }
        internal List<BookmarkedExams> GetBookmarkedExam(int user_id, int exam_id)
        {
            List<BookmarkedExams> exams = _context.BookmarkedExams.Where(a => a.UserId == user_id && a.ExamId == exam_id && a.IsActive == true).ToList();
            return exams;
        }
        /*
                internal StudyNoteViewModel GetStudyNoteById(int studyNoteId)
                {
                    StudyNoteViewModel studyNoteViewModel = (from sn in _context.StudyNotes
                                                             where sn.Id == studyNoteId
                                                             select new StudyNoteViewModel
                                                             {
                                                                 Id = sn.Id,
                                                                 UserId = sn.UserId,
                                                                 SubjectId = sn.SubjectId,
                                                                 CategoryId = sn.CategoryId,
                                                                 SubCategoryId = sn.SubCategoryId,
                                                                 Name = sn.Name,
                                                                 Description = sn.Description,
                                                                 PdfUrl = sn.PdfUrl,
                                                                 VideoUrl = sn.VideoUrl,
                                                                 Status = sn.Status,
                                                                 CreatedOn = sn.CreatedOn,
                                                                 UpdatedOn = sn.UpdatedOn,
                                                                 IsActive = sn.IsActive
                                                             }
                                  ).FirstOrDefault();

                    return studyNoteViewModel;
                }
        */

        internal ExamQuestionsMarkWeight GetExamSectionQuestion(int institute_id, int exam_section_id, int question_id)
        {
            ExamQuestionsMarkWeight eqmw = (from m in _context.ExamQuestionsMarkWeight
                                            join q in _context.Questions on m.QuestionId equals q.Id

                                            where m.ExamSectionId == exam_section_id && m.QuestionId == question_id && m.IsActive == true
                                            && q.InstituteId == institute_id && q.StatusCode == StatusCode.PUBLISHED.ToString() && q.IsActive == true

                                            select m).FirstOrDefault();

            return eqmw;
        }

        internal ExamViewModel GetExamById(int institute_id, int exam_id)
        {
            ExamViewModel exam = (from e in _context.Exams
                                  where e.InstituteId == institute_id && e.Id == exam_id && e.IsActive == true 
                                  
                                  select new ExamViewModel
                                  {
                                      id = e.Id,
                                      institute_id = (int)e.InstituteId,
                                      author_id = e.CreatedBy,
                                      examtype_id = (int)e.ExamTypeId,
                                      language_id = e.LanguageId,
                                      name = e.Name,
                                      instruction = e.Instruction,
                                      exam_status = e.ExamStatus,
                                      start_date = e.ExamOpenDatetime,
                                      end_date = e.ExamCloseDatetime,
                                      //duration_seconds = (double)e.ExamDurationInMinutes,
                                      attempts_allowed = e.AttemptsAllowed,
                                      created_on = (DateTime)e.CreatedOn,
                                      updated_on = (DateTime)e.UpdatedOn,
                                      isActive = e.IsActive
                                  }
                           ).FirstOrDefault();

            List<ExamSections> examSections;
            List<ExamSectionViewModel> lesbvm = new List<ExamSectionViewModel>(); ;
            examSections = _context.ExamSections.Where(e => e.ExamId == exam_id && e.IsActive == true).ToList();

            foreach (ExamSections s in examSections)
            {
                ExamSectionViewModel esvm = GetExamSectionById(s.Id);
                
                lesbvm.Add(esvm);
            }

            exam.sections = lesbvm;
            return exam;
        }


        internal PracticeViewModel GetPracticeById(int institute_id, int practice_id)
        {
            PracticeViewModel practice = (from p in _context.Practices
                                  where p.InstituteId == institute_id && p.Id == practice_id && p.IsActive == true

                                  select new PracticeViewModel
                                  {
                                      id = p.Id,
                                      institute_id = (int)p.InstituteId,
                                      author_id = p.CreatedBy,
                                      module = p.Module,
                                      module_id = p.ModuleId,
                                      module_name = (p.Module == Constant.Subject) ?
                                      _context.Subjects.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name :
                                      _context.Categories.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name,
                                      module_status = p.ModuleStatus,
                                      language_id = p.LanguageId,
                                      name = p.Name,
                                      instruction = p.Instruction,
                                      status = p.Status,
                                      start_date = p.OpenDatetime,
                                      created_on = (DateTime)p.CreatedOn,
                                      updated_on = (DateTime)p.UpdatedOn,
                                      isActive = p.IsActive
                                  }
                           ).FirstOrDefault();

            return practice;
        }


        internal ExamViewAllModel GetExamBasicById(int institute_id, int exam_id)
        {
            ExamViewAllModel exam = (from e in _context.Exams
                                     join u in _context.Users on e.CreatedBy equals u.Id
                                     where e.InstituteId == institute_id && e.Id == exam_id && e.IsActive == true

                                     select new ExamViewAllModel
                                     {
                                         id = e.Id,
                                         institute_id = (int)e.InstituteId,
                                         //TODO: change for this AuthorId = e.CreatedBy,
                                         author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                         name = e.Name,
                                         examtype_id = (int)e.ExamTypeId,
                                         language_code = _context.Languages.Where(l => l.Id == e.LanguageId).FirstOrDefault().Code.ToString(),
                                         exam_status = e.ExamStatus,
                                         complexity = (short)e.Complexity,
                                         start_date = e.ExamOpenDatetime,
                                         end_date = e.ExamCloseDatetime,
                                         attempts_allowed = e.AttemptsAllowed,
                                         exam_duration = e.ExamDurationInSeconds,
                                         created_on = e.CreatedOn,
                                         updated_on = e.UpdatedOn,
                                         isActive = e.IsActive                                         
                                     }
                           ).FirstOrDefault();

            List<ExamSections> examSections;
            List<ExamQuestionsMarkWeight> examQuestions;
            exam.total_questions = 0;
            exam.total_marks = 0;

            examSections = _context.ExamSections.Where(s => s.ExamId == exam_id && s.IsActive == true).ToList();

            foreach (ExamSections s in examSections)
            {
                examQuestions = _context.ExamQuestionsMarkWeight.Where(q => q.ExamSectionId == s.Id).ToList();
                if(examQuestions.Count() > 0)
                {
                    exam.total_questions += examQuestions.Count();
                }
                
                foreach (ExamQuestionsMarkWeight q in examQuestions)
                {
                    if (q.MarkForCorrectAnswer != null)
                        exam.total_marks += q.MarkForCorrectAnswer;
                }
            }

            return exam;
        }

        internal List<ExamViewDraftModel> GetExamDraftListByIds(int institute_id, List<int> examIDList)
        {
            List<ExamViewDraftModel> exam = (from e in _context.Exams
                                             join u in _context.Users on e.CreatedBy equals u.Id
                                             where e.InstituteId == institute_id && examIDList.Contains(e.Id) && e.IsActive == true

                                             select new ExamViewDraftModel
                                             {
                                                 id = e.Id,
                                                 institute_id = (int)e.InstituteId,
                                                 author_id = e.CreatedBy,
                                                 author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                                 name = e.Name,
                                                 sections_count = 0,//_context.ExamSections.Where(es => es.IsActive == true && es.ExamId == e.Id).ToList().Count,
                                                 sections_status = StatusCode.DRAFT.ToString(),
                                                 examtype_id = (int)e.ExamTypeId, //Comment
                                                 language_id = e.LanguageId, //Comment
                                                 exam_status = e.ExamStatus,
                                                 //complexity = (short)e.Complexity,
                                                 created_on = e.CreatedOn,
                                                 updated_on = e.UpdatedOn,
                                                 isActive = true//e.IsActive
                                             }
                           ).ToList();

            return exam;
        }

        internal int GetTotalQuestionOfTheExam(int exam_id)
        {
            List<ExamQuestionsMarkWeight> leqmw = (from e in _context.ExamSections
                     join q in _context.ExamQuestionsMarkWeight on e.Id equals q.ExamSectionId

                     where e.ExamId == exam_id && e.IsActive == true
                                    && q.IsActive == true


                    select new ExamQuestionsMarkWeight
                    {
                        Id = q.Id
                    }

             ).ToList();

            if (leqmw == null) return 0;

            return leqmw.Count;
        }


        internal List<ExamAttemptAllExamModel> GetExamDetailsByIds(int institute_id, int batch_id, int user_id, List<Exams> examList)
        {
            List<int> idList = new List<int>();
            
            List<ExamAttemptAllExamModel> detailedExamList = new List<ExamAttemptAllExamModel>();

            /* SUBSDELETE
            short myExamPoints = 0;
            SubscriptionViewModel svm = mySubscriptionDetails(user_id);
            if (svm != null)
            {
                myExamPoints = svm.remaining_exam_credits;
            } 
            */

            var exams = (from ex in examList
                         join es in _context.ExamSections on ex.Id equals es.ExamId into sections
                         join su in _context.Subjects on sections.FirstOrDefault().SubjectId equals su.Id
                         join la in _context.Languages on ex.LanguageId equals la.Id
                         join uge in _context.UserGroupExams on ex.Id equals uge.ExamId
                         join us in _context.Users on ex.CreatedBy equals us.Id
                         join qs in _context.ExamQuestionsMarkWeight on us.IsActive equals qs.IsActive into qns


                         where ex.InstituteId == institute_id
                            && uge.UserGroupId == batch_id && uge.IsActive == true 
                            && sections.All(a => a.IsActive == true)

                         select new
                         {
                             e = ex,
                             s = sections,
                             sub = su,
                             u = us,
                             l = la,
                             q = qns
                         });

            foreach (var item in exams)
            {
                ExamAttemptAllExamModel examDetail = new ExamAttemptAllExamModel();
                examDetail.id = item.e.Id;
                examDetail.institute_id = item.e.InstituteId;
                examDetail.author_id = item.e.CreatedBy;
                examDetail.author_name = item.u.FirstName + (item.u.LastName == null ? "" : " " + item.u.LastName);
                examDetail.name = item.e.Name;
                examDetail.examtype_id = item.e.ExamTypeId;
                examDetail.language_code = item.l.Code.ToString();
                examDetail.complexity = item.e.Complexity;
                examDetail.attempts_allowed = item.e.AttemptsAllowed;
                //examDetail.points_needed = (short)item.e.CreditsNeeded;
                //examDetail.points_available = myExamPoints;
                var latestAttempt = _context.ExamAttempts
                                            .Where(a => a.ExamId == item.e.Id && a.CreatedBy == user_id)
                                            .OrderByDescending(a => a.CreatedOn)
                                            .FirstOrDefault();

                if (latestAttempt != null) 
                    examDetail.attempt_status = latestAttempt.Status;

                examDetail.start_date = item.e.ExamOpenDatetime;
                examDetail.end_date = item.e.ExamCloseDatetime;
                examDetail.exam_duration = item.e.ExamDurationInSeconds;
                examDetail.subject_count = item.s.Count();
                examDetail.total_questions = item.q.Where(x => item.s.Select(i => i.Id).Contains(x.ExamSectionId) && x.IsActive == true).Count();
                examDetail.subject_name = item.s.Count() > 1 ? "FULL" : item.sub.Name;
                examDetail.subject_id = item.s.Count() > 1 ? 0 : item.sub.Id;
                examDetail.total_marks = item.q.Where(x => item.s.Select(i => i.Id).Contains(x.ExamSectionId) && x.IsActive == true).Select(i => i.MarkForCorrectAnswer).Sum();
                examDetail.isActive = item.e.IsActive;
               detailedExamList.Add(examDetail);
            }

            detailedExamList = detailedExamList.OrderByDescending(a => a.created_on).ToList();

            return detailedExamList;
        }

        internal List<ExamViewAllModel> GetExamListByIds(int institute_id, List<int> examIDList)
        {
            List<ExamViewAllModel> exam = (from e in _context.Exams
                                             join u in _context.Users on e.CreatedBy equals u.Id
                                             where e.InstituteId == institute_id && examIDList.Contains(e.Id) 
                                                            && e.ExamStatus == StatusCode.PUBLISHED.ToString() && e.IsActive == true

                                             select new ExamViewAllModel
                                             {
                                                 id = e.Id,
                                                 institute_id = (int)e.InstituteId,
                                                 author_id = e.CreatedBy,
                                                 author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                                 name = e.Name,
                                                 examtype_id = (int)e.ExamTypeId,
                                                 language_code = _context.Languages.Where(l => l.Id == e.LanguageId).FirstOrDefault().Code.ToString(),
                                                 exam_status = e.ExamStatus,
                                                 complexity = (short)e.Complexity,
                                                 attempts_allowed = e.AttemptsAllowed,
                                                 start_date = e.ExamOpenDatetime,
                                                 end_date = e.ExamCloseDatetime,
                                                 exam_duration = e.ExamDurationInSeconds,
                                                 sections_count = _context.ExamSections.Where(es => es.IsActive == true && es.ExamId == e.Id).ToList().Count,
                                                 created_on = e.CreatedOn,
                                                 updated_on = e.UpdatedOn,
                                                 //total_questions = GetTotalQuestionOfTheExam(e.Id),
                                                 //total_marks = GetTotalQuestionOfTheExam(e.Id),
                                                 isActive = e.IsActive                                           
                                             }
                           ).ToList();

            foreach(ExamViewAllModel ev in exam)
            {
                List<ExamQuestionsMarkWeight> leqmw = (from e in _context.ExamSections
                                                       join q in _context.ExamQuestionsMarkWeight on e.Id equals q.ExamSectionId

                                                       where e.ExamId == ev.id && e.IsActive == true
                                                                      && q.IsActive == true


                                                       select new ExamQuestionsMarkWeight
                                                       {
                                                           MarkForCorrectAnswer = q.MarkForCorrectAnswer
                                                       }

                ).ToList();

                if (leqmw == null)
                {
                    ev.total_questions = 0;
                    ev.total_marks = 0;
                }
                else
                {
                    ev.total_questions = leqmw.Count;
                    ev.total_marks = leqmw.Sum(item => item.MarkForCorrectAnswer);
                }
            }

            return exam;
        }


        internal List<PracticeViewAllModel> GetPracticeListByIds(int institute_id, List<int> practiceIDList)
        {
            List<PracticeViewAllModel> practice = (from p in _context.Practices
                                           join u in _context.Users on p.CreatedBy equals u.Id
                                           where p.InstituteId == institute_id && practiceIDList.Contains(p.Id)
                                                         && p.IsActive == true

                                           select new PracticeViewAllModel
                                           {
                                               id = p.Id,
                                               author_id = p.CreatedBy,
                                               author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                               name = p.Name,
                                               module = p.Module,
                                               module_id = p.ModuleId,
                                               language_code = _context.Languages.Where(l => l.Id == p.LanguageId).FirstOrDefault().Code.ToString(),
                                               status = p.Status,
                                               //complexity = (short)p.Complexity,
                                               start_date = p.OpenDatetime,
                                               created_on = p.CreatedOn,
                                               updated_on = p.UpdatedOn,
                                               //total_questions = _context.Q
                                               isActive = p.IsActive
                                           }
                           ).ToList();

            
           return practice;
        }


        internal List<PracticeAttemptAllPracticeModel> PracticeAttempt_GetPracticeListByIds(int institute_id, int user_id, List<int> practiceIDList)
        {
            short myPracticePoints = 0;
            int subscription_id = 0;
            SubscriptionViewModel svm = mySubscriptionDetails(user_id);
            if (svm != null)
            {
                myPracticePoints = svm.remaining_practice_credits;
                subscription_id = 0;
            }

            List<PracticeAttemptAllPracticeModel> practice = (from p in _context.Practices
                                                   join u in _context.Users on p.CreatedBy equals u.Id
                                                   where p.InstituteId == institute_id && practiceIDList.Contains(p.Id)
                                                                 && p.IsActive == true

                                                   select new PracticeAttemptAllPracticeModel
                                                   {
                                                       id = p.Id,
                                                       institute_id = p.InstituteId,
                                                       author_id = (int)p.CreatedBy,
                                                       author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                                       name = p.Name,
                                                       module = p.Module,
                                                       module_id = p.ModuleId,
                                                       module_name = p.Module == Constant.Subject ? _context.Subjects.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name : _context.Categories.Where(c => c.Id == p.ModuleId).FirstOrDefault().Name,
                                                       language_code = _context.Languages.Where(l => l.Id == p.LanguageId).FirstOrDefault().Code.ToString(),
                                                       practice_status = p.Status,
                                                       attempt_count = _context.PracticeAttempts.Where(a => a.PracticeId == p.Id && a.IsActive == true).Select(l => l.CreatedBy).Distinct().Count(),
                                                       bookmark_count = _context.BookmarkedPractices.Where(b => b.PracticeId == p.Id && b.IsActive == true).Select(l => l.CreatedBy).Distinct().Count(),
                                                       points_available = myPracticePoints,
                                                       points_needed = (short)p.CreditsNeeded,
                                                       isSubscribed = _context.SubscribedPractices.Where(sp => sp.SubscriptionId == subscription_id
                                                                        && sp.PracticeId == p.Id && sp.IsActive == true)
                                                                        .FirstOrDefault() == null ? true: false,
                                                       complexity = (short)p.Complexity,
                                                       start_date = (DateTime)p.OpenDatetime,
                                                       created_on = (DateTime)p.CreatedOn,
                                                       updated_on = (DateTime)p.UpdatedOn,
                                                       total_questions = _context.PracticeQuestions.Where(pq => pq.PracticeId == p.Id && pq.IsActive == true).Count(),
                                                       isActive = (bool)p.IsActive
                                                   }
                           ).ToList();


            return practice;
        }

        internal List<ExamAttemptAllExamModel> GetExamListWithAttemptByIds(int institute_id, List<int> examIDList)
        {
            List<ExamAttemptAllExamModel> exam = (from e in _context.Exams
                                           join u in _context.Users on e.CreatedBy equals u.Id
                                           where e.InstituteId == institute_id && examIDList.Contains(e.Id)
                                                          && e.ExamStatus == StatusCode.PUBLISHED.ToString() && e.IsActive == true

                                           select new ExamAttemptAllExamModel
                                           {
                                               id = e.Id,
                                               institute_id = (int)e.InstituteId,
                                               author_id = e.CreatedBy,
                                               author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                               name = e.Name,
                                               examtype_id = (int)e.ExamTypeId,
                                               language_code = _context.Languages.Where(l => l.Id == e.LanguageId).FirstOrDefault().Code.ToString(),
                                               complexity = (short)e.Complexity,
                                               attempts_allowed = (short)e.AttemptsAllowed,
                                               start_date = (DateTime)e.ExamOpenDatetime,
                                               end_date = (DateTime)e.ExamCloseDatetime,
                                               exam_duration = (int)e.ExamDurationInSeconds,
                                               subject_count = _context.ExamSections.Where(es => es.IsActive == true && es.ExamId == e.Id).ToList().Count,
                                               points_needed = (short)e.CreditsNeeded,
                                               created_on = (DateTime)e.CreatedOn,
                                               updated_on = (DateTime)e.UpdatedOn,
                                               isActive = (bool)e.IsActive
                                           }
                           ).ToList();

            foreach (ExamAttemptAllExamModel ev in exam)
            {
                List<ExamQuestionsMarkWeight> leqmw = (from e in _context.ExamSections
                                                       join q in _context.ExamQuestionsMarkWeight on e.Id equals q.ExamSectionId

                                                       where e.ExamId == ev.id && e.IsActive == true
                                                                      && q.IsActive == true


                                                       select new ExamQuestionsMarkWeight
                                                       {
                                                           MarkForCorrectAnswer = q.MarkForCorrectAnswer
                                                       }

                ).ToList();

                if (leqmw == null)
                {
                    ev.total_questions = 0;
                    ev.total_marks = 0;
                }
                else
                {
                    ev.total_questions = leqmw.Count;
                    ev.total_marks = (double)leqmw.Sum(item => item.MarkForCorrectAnswer);
                }


                //Add attempt info
                List<ExamAttempts> attempts = (from a in _context.ExamAttempts
                                               where a.ExamId == ev.id && a.IsActive == true
                                               select a).ToList();
                ExamAttempts lastAttempt = new ExamAttempts();

                if (attempts == null || attempts.Count == 0)
                {
                    ev.attempts_taken = 0;
                    ev.attempt_status = null;
                }
                else
                {
                    ev.attempts_taken = (short)attempts.Count;
                    lastAttempt = attempts.OrderByDescending(l => l.UpdatedOn).FirstOrDefault();

                    if (lastAttempt.Status == State.START || lastAttempt.Status == State.RESUME)
                    {
                        //Check if user still has time to update the answers
                        TimeSpan time_diff = (TimeSpan)(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 = NowIndianTime();
                            _context.ExamAttempts.Update(lastAttempt);
                            _context.SaveChanges();

                            ev.attempt_status = State.COMPLETED;
                        } else
                        {
                            ev.attempt_status = lastAttempt.Status;
                        }
                    }    
                    else if (lastAttempt.Status == State.PAUSE || lastAttempt.Status == State.COMPLETED)
                    {
                        ev.attempt_status = lastAttempt.Status;
                    }
                }
            }

            return exam;
        }


        internal List<ExamAttemptAllExamModel> GetLiveExamListOfTheSubject(int institute_id, int batch_id, int subject_id)
        {
            List<ExamAttemptAllExamModel> exam = (from e in _context.Exams
                                                  join uge in _context.UserGroupExams on e.Id equals uge.ExamId 
                                                  join u in _context.Users on e.CreatedBy equals u.Id
                                                  where e.InstituteId == institute_id && e.ExamStatus == StatusCode.PUBLISHED.ToString() && e.ExamOpenDatetime < NowIndianTime() && e.ExamCloseDatetime > NowIndianTime() && e.IsActive == true
                                                  && uge.UserGroupId == batch_id && uge.IsActive == true

                                                  select new ExamAttemptAllExamModel
                                                  {
                                                      id = e.Id,
                                                      institute_id = (int)e.InstituteId,
                                                      author_id = e.CreatedBy,
                                                      author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                                      name = e.Name,
                                                      examtype_id = (int)e.ExamTypeId,
                                                      language_code = _context.Languages.Where(l => l.Id == e.LanguageId).FirstOrDefault().Code.ToString(),
                                                      complexity = (short)e.Complexity,
                                                      attempts_allowed = (short)e.AttemptsAllowed,
                                                      start_date = (DateTime)e.ExamOpenDatetime,
                                                      end_date = (DateTime)e.ExamCloseDatetime,
                                                      exam_duration = (int)e.ExamDurationInSeconds,
                                                      subject_count = _context.ExamSections.Where(es => es.IsActive == true && es.ExamId == e.Id).ToList().Count,
                                                      points_needed = (short)e.CreditsNeeded,
                                                      created_on = (DateTime)e.CreatedOn,
                                                      updated_on = (DateTime)e.UpdatedOn,
                                                      isActive = (bool)e.IsActive
                                                  }
                           ).ToList();

            if(subject_id > 0)
            {
                exam = (from e in exam
                        join sec in _context.ExamSections on e.id equals sec.ExamId
                        join sub in _context.Subjects on sec.SubjectId equals sub.Id

                        where e.subject_count == 1 
                        && sec.IsActive == true && sub.IsActive == true && sub.Id == subject_id
                        select e).ToList();
            } 
            
            else if(subject_id == 0)
            {
                exam = exam.Where(e => e.subject_count > 1).ToList();
            }
           
            foreach (ExamAttemptAllExamModel ev in exam)
            {
                List<ExamQuestionsMarkWeight> leqmw = (from e in _context.ExamSections
                                                       join q in _context.ExamQuestionsMarkWeight on e.Id equals q.ExamSectionId

                                                       where e.ExamId == ev.id && e.IsActive == true
                                                                      && q.IsActive == true


                                                       select new ExamQuestionsMarkWeight
                                                       {
                                                           MarkForCorrectAnswer = q.MarkForCorrectAnswer
                                                       }

                ).ToList();

                if (leqmw == null)
                {
                    ev.total_questions = 0;
                    ev.total_marks = 0;
                }
                else
                {
                    ev.total_questions = leqmw.Count;
                    ev.total_marks = (double)leqmw.Sum(item => item.MarkForCorrectAnswer);
                }


                //Add attempt info
                List<ExamAttempts> attempts = (from a in _context.ExamAttempts
                                               where a.ExamId == ev.id && a.IsActive == true
                                               select a).ToList();
                ExamAttempts lastAttempt = new ExamAttempts();

                if (attempts == null || attempts.Count == 0)
                {
                    ev.attempts_taken = 0;
                    ev.attempt_status = null;
                }
                else
                {
                    ev.attempts_taken = (short)attempts.Count;
                    lastAttempt = attempts.OrderByDescending(l => l.UpdatedOn).FirstOrDefault();

                    if (lastAttempt.Status == State.START || lastAttempt.Status == State.RESUME)
                    {
                        //Check if user still has time to update the answers
                        TimeSpan time_diff = (TimeSpan)(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 = NowIndianTime();
                            _context.ExamAttempts.Update(lastAttempt);
                            _context.SaveChanges();

                            ev.attempt_status = State.COMPLETED;
                        }
                        else
                        {
                            ev.attempt_status = lastAttempt.Status;
                        }
                    }
                    else if (lastAttempt.Status == State.PAUSE || lastAttempt.Status == State.COMPLETED)
                    {
                        ev.attempt_status = lastAttempt.Status;
                    }
                }
            }

            return exam;
        }

        internal List<ExamAttemptAttemptedExamModel> GetAttemptedExamList(int institute_id, int batch_id, int user_id)
        {
            List<int> idList = new List<int>();
            List<ExamAttempts> attemptList = new List<ExamAttempts>();

            attemptList = _context.ExamAttempts.Where(ea => ea.Status == State.COMPLETED.ToString() && ea.IsActive == true && ea.CreatedBy == user_id).ToList();

            List<ExamAttemptAttemptedExamModel> attemptsHistory = new List<ExamAttemptAttemptedExamModel>();

            var exams = (from ea in attemptList
                         join es in _context.ExamSections on ea.ExamId equals es.ExamId into sections
                         join su in _context.Subjects on sections.FirstOrDefault().SubjectId equals su.Id
                         join ex in _context.Exams on ea.ExamId equals ex.Id
                         join la in _context.Languages on ex.LanguageId equals la.Id
                         join uge in _context.UserGroupExams on ex.Id equals uge.ExamId
                         join us in _context.Users on ex.CreatedBy equals us.Id
                         join qs in _context.ExamQuestionsMarkWeight on us.IsActive equals qs.IsActive into qns

                         where ex.InstituteId == institute_id 
                            && uge.UserGroupId == batch_id && uge.IsActive == true
                            && sections.All(a => a.IsActive == true)
                            
                         select new
                         {
                             e = ex,
                             s = sections,
                             sub = su,
                             a = ea,
                             u = us,
                             l = la,
                             q = qns
                         });

            foreach (var item in exams)
            {
                ExamAttemptAttemptedExamModel lastAttempt = new ExamAttemptAttemptedExamModel();
                lastAttempt.id = item.a.Id;
                lastAttempt.institute_id = item.e.InstituteId;
                lastAttempt.exam_id = item.e.Id;
                lastAttempt.author_id = item.e.CreatedBy;
                lastAttempt.author_name = item.u.FirstName + (item.u.LastName == null ? "" : " " + item.u.LastName);
                lastAttempt.name = item.e.Name;
                lastAttempt.examtype_id = item.e.ExamTypeId;
                lastAttempt.language_code = item.l.Code.ToString();
                lastAttempt.complexity = item.e.Complexity;
                lastAttempt.attempts_allowed = item.e.AttemptsAllowed;
                lastAttempt.start_date = item.e.ExamOpenDatetime;
                lastAttempt.end_date = item.e.ExamCloseDatetime;
                lastAttempt.exam_duration = item.e.ExamDurationInSeconds;
                lastAttempt.attempted_on = item.a.CreatedOn;
                lastAttempt.total_score = item.a.Score;
                lastAttempt.attempt_status = item.a.Status;
                lastAttempt.sections_count = item.s.Count();
                lastAttempt.total_questions = item.q.Where(x => item.s.Select(i => i.Id).Contains(x.ExamSectionId) && x.IsActive == true).Count();
                lastAttempt.sections_name = item.s.Count() > 1 ? "FULL" : item.sub.Name;
                lastAttempt.total_marks = item.q.Where(x => item.s.Select(i => i.Id).Contains(x.ExamSectionId) && x.IsActive == true).Select(i => i.MarkForCorrectAnswer).Sum();
                lastAttempt.attempts_taken = attemptList.Where(n => n.ExamId == item.e.Id).Count();
                lastAttempt.isActive = item.a.IsActive;
                attemptsHistory.Add(lastAttempt);
            }

            attemptsHistory = attemptsHistory.OrderByDescending(a => a.attempted_on).ToList();

            return attemptsHistory;
        }


            /*
                    internal List<ExamAttemptAttemptedExamModel> GetAttemptedExamList(int institute_id, int batch_id, int user_id)
                    {
                        List<int> idList = new List<int>();
                        List<int> attemptList = new List<int>();

                        attemptList = _context.ExamAttempts.Where(ea => ea.Status == State.COMPLETED.ToString() && ea.IsActive == true && ea.CreatedBy == user_id).Select(ea => ea.Id).ToList();

                        ExamAttemptAttemptedExamModel exam = null;

                        var exams = (from ea in _context.ExamAttempts
                                    join et in _context.ExamSections on ea.ExamId equals et.ExamId into sections

                                    where ea.Status == State.COMPLETED.ToString() && ea.IsActive == true && ea.CreatedBy == user_id

                                    select new
                                    {
                                        s = sections,
                                        a = ea
                                    });




                        var exam = (from ea in _context.ExamAttempts
                                                                    join es in _context.ExamSections on ea.ExamId equals es.ExamId into sections

                                                                    join e in _context.Exams on ea.ExamId equals e.Id
                                                                    //join eaa in _context.ExamAttemptsAnswer on ea.Id equals eaa.ExamAttemptId
                                                                    join uge in _context.UserGroupExams on e.Id equals uge.ExamId
                                                                    join u in _context.Users on e.CreatedBy equals u.Id


                                                                    where e.InstituteId == institute_id && e.ExamStatus == StatusCode.PUBLISHED.ToString() && e.ExamOpenDatetime < NowIndianTime()
                                                                    && ea.Status == State.COMPLETED.ToString() && ea.IsActive == true && ea.CreatedBy == user_id
                                                                    && uge.UserGroupId == batch_id && uge.IsActive == true
                                                                    //&& sections.All(a => a.IsActive == true)


                                                                    select 
                                                                    new ExamAttemptAttemptedExamModel
                                                                    {
                                                                      id = ea.Id,
                                                                      exam_id = e.Id,
                                                                      institute_id = (int)e.InstituteId,
                                                                      author_id = e.CreatedBy,
                                                                      author_name = u.FirstName + (u.LastName == null ? "" : " " + u.LastName),
                                                                      name = e.Name,
                                                                      examtype_id = (int)e.ExamTypeId,
                                                                      language_code = _context.Languages.Where(l => l.Id == e.LanguageId).FirstOrDefault().Code.ToString(),
                                                                      complexity = (short)e.Complexity,
                                                                      attempts_allowed = (short)e.AttemptsAllowed,
                                                                      start_date = (DateTime)e.ExamOpenDatetime,
                                                                      end_date = (DateTime)e.ExamCloseDatetime,
                                                                      exam_duration = (int)e.ExamDurationInSeconds,
                                                                      attempted_on = (DateTime)ea.CreatedOn,
                                                                      total_score = (int)ea.Score,
                                                                      attempt_status = ea.Status,
                                                                      sections_count = idList.Count(),
                                                                      //total_questions = _context.ExamQuestionsMarkWeight.Where(q => q.IsActive == true && sections.Select(a => a.Id).Contains(q.ExamSectionId)).Count(),
                                                                        //sections_name = idList.Count() > 1 ? "FULL" : sub_name,
                                                                        //total_questions = _context.ExamQuestionsMarkWeight.Where(q => q.IsActive == true && idList.Contains(q.ExamSectionId)).Count(),
                                                                        //total_marks = (double)_context.ExamQuestionsMarkWeight.AsEnumerable().Where(q => q.IsActive == true && idList.Contains(q.ExamSectionId)).Select(q => q.MarkForCorrectAnswer).Sum(),
                                                                        attempts_taken = (short)_context.ExamAttempts.Where(ea => ea.IsActive == true && ea.ExamId == e.Id && ea.CreatedBy == user_id).Count(),
                                                                      isActive = (bool)e.IsActive
                                                                    } 

                                        ).ToList();

                        //exam = exam.GroupBy(a => a.exam_id).Select(a => a.FirstOrDefault()).OrderByDescending(a => a.attempted_on).ToList();
                        //exam = exam.OrderByDescending(a => a.attempted_on).ToList();


                        int i = 0;
                        foreach (ExamAttemptAttemptedExamModel e in exam)
                        {
                            i = i + 1;



                            idList = _context.ExamSections.Where(es => es.IsActive == true && es.ExamId == e.exam_id).Select(es => es.Id).ToList();

                            e.sections_count = idList.Count();
                            e.sections_name = e.sections_count > 1 ? "FULL" : null;
                            if(e.sections_name == null)
                            {
                                int sub_id = _context.ExamSections.Where(es => idList.Contains(es.Id)).Select(es => es.SubjectId).FirstOrDefault();
                                e.sections_name = _context.Subjects.Where(s => s.Id == sub_id).Select(s => s.Name).FirstOrDefault();
                            }
                            e.total_questions = _context.ExamQuestionsMarkWeight.Where(q => q.IsActive == true && idList.Contains(q.ExamSectionId)).Count();

                            e.total_marks = (double)_context.ExamQuestionsMarkWeight.Where(q => q.IsActive == true && idList.Contains(q.ExamSectionId)).Select(q => q.MarkForCorrectAnswer).Sum();
                            e.attempts_taken = (short)_context.ExamAttempts.Where(ea => ea.IsActive == true && ea.ExamId == e.exam_id && ea.CreatedBy == user_id).Count();

                        }

                        return exam;
                    }
            */


            internal ExamSectionViewModel GetExamSectionById(int newExamSectionId)
        {
            ExamSectionViewModel examSection = (from s in _context.ExamSections
                                                join sub in _context.Subjects on s.SubjectId equals sub.Id
                                                
                                                where s.Id == newExamSectionId && s.IsActive == true
                                                    && sub.IsActive == true
                                                    
                                                select new ExamSectionViewModel
                                                {
                                                    id = s.Id,
                                                    subject_id = s.SubjectId,
                                                    section_state = s.Status,
                                                    subject_name = sub.Name,
                                                    section_sequence = s.SubjectSequence,
                                                    section_duration = s.SubjectDuration
                                                    
                                                }
                           ).FirstOrDefault();



            List <ExamQuestionsMarkWeight> leq = _context.ExamQuestionsMarkWeight.Where(q => q.ExamSectionId == newExamSectionId 
                                                                                && q.IsActive == true).ToList();

            if(examSection != null)
            {
                examSection.total_questions = leq.Count;
                examSection.total_marks = 0;
                foreach (ExamQuestionsMarkWeight m in leq)
                {
                    if (m.MarkForCorrectAnswer != null) examSection.total_marks += (double)m.MarkForCorrectAnswer;
                }
            }
            
            return examSection;
        }



        internal List<ExamViewAllModel> GetExams(int institute_id, int language_id, int class_id, int? user_id, string sortBy, string sortOrder)
        {
            List<Exams> exams;
            List<ExamViewAllModel> examList = new List<ExamViewAllModel>();

            exams = (from e in _context.Exams

                          where e.InstituteId == institute_id && e.IsActive == true
                          
                          select e
                     ).ToList();



            if (user_id != null)
            {
                exams = exams.Where(e => e.CreatedBy == user_id).ToList();
            }

            foreach (Exams e in exams)
            {
                ExamViewAllModel evm = GetExamBasicById(institute_id, e.Id);
                examList.Add(evm);
            }

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


            return examList;
        }


        internal UserGroupExams GetUserGroupExams(int institute_id, int exam_id, int user_group_id)
        {
            UserGroupExams uge = (from ue in _context.UserGroupExams
                                  join e in _context.Exams on ue.ExamId equals e.Id
                                  join ug in _context.UserGroups on ue.UserGroupId equals ug.Id
                                  join c in _context.Classes on ug.ClassId equals c.Id

                                  where ue.ExamId == exam_id && ue.UserGroupId == user_group_id && ue.IsActive == true
                                  && e.InstituteId == institute_id && e.IsActive == true
                                  && ug.IsActive == true
                                  && c.InstituteId == institute_id && c.IsActive == true
                                  select ue).FirstOrDefault(); 
            return uge;
        }

        internal UserGroupPractices GetUserGroupPractices(int institute_id, int practice_id, int user_group_id)
        {
            UserGroupPractices ugp = (from up in _context.UserGroupPractices
                                  join p in _context.Practices on up.PracticeId equals p.Id
                                  join ug in _context.UserGroups on up.UserGroupId equals ug.Id
                                  join c in _context.Classes on ug.ClassId equals c.Id

                                  where up.PracticeId == practice_id && up.UserGroupId == user_group_id && up.IsActive == true
                                  && p.InstituteId == institute_id && p.IsActive == true
                                  && ug.IsActive == true
                                  && c.InstituteId == institute_id && c.IsActive == true
                                  select up).FirstOrDefault();
            return ugp;
        }


        public int _ea_createNewAttempt(int user_id, int exam_id, int duration)
        {
            ExamAttempts examAttempts = new ExamAttempts();

            try
            {
                _context.Database.BeginTransaction();

                /* SUBSDELETE 
                //if paid and not subscribed : add item into subscribedexam and deduct points from remaining point
                if (points_needed > 0 && isSubscribed == false)
                {
                    Subscriptions subscriptions = _context.Subscriptions.Where(s => s.Id == subscription_id).FirstOrDefault();

                    if (points_needed > subscriptions.RemainingExamCredits)
                        return (int)Message.NotAllowedToResource;

                    subscriptions.RemainingExamCredits -= points_needed;
                    _context.Subscriptions.Update(subscriptions);
                    _context.SaveChanges();

                    SubscribedExams se = new SubscribedExams();
                    se.SubscriptionId = subscription_id;
                    se.ExamId = exam_id;
                    se.CreatedBy = user_id;
                    se.CreatedOn = NowIndianTime();
                    se.UpdatedBy = user_id;
                    se.UpdatedOn = NowIndianTime();
                    se.IsActive = true;

                    _context.SubscribedExams.Add(se);
                    _context.SaveChanges();                    
                }
                */


                examAttempts.ExamId = exam_id;
                examAttempts.CreatedBy = user_id;
                examAttempts.CreatedOn = NowIndianTime();
                examAttempts.UpdatedBy = user_id;
                examAttempts.UpdatedOn = NowIndianTime();
                examAttempts.PuasedPeriod = 0.ToString();
                examAttempts.Status = State.START;
                examAttempts.IsActive = true;
                examAttempts.RemainingTimeSeconds = duration;

                _context.ExamAttempts.Add(examAttempts);
                _context.SaveChanges();


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

            return examAttempts.Id;
        }

        public int _pa_createNewAttempt(int user_id, int subscription_id, int practice_id, short points_needed, bool isSubscribed)
        {
            PracticeAttempts practiceAttempts = new PracticeAttempts();

            try
            {
                _context.Database.BeginTransaction();

                //if paid and not subscribed : add item into subscribedpractice and deduct points from remaining point
                if (points_needed > 0 && isSubscribed == false)
                {
                    SubscribedPractices sp = new SubscribedPractices();
                    sp.SubscriptionId = subscription_id;
                    sp.PracticeId = practice_id;
                    sp.CreatedBy = user_id;
                    sp.CreatedOn = NowIndianTime();
                    sp.UpdatedBy = user_id;
                    sp.UpdatedOn = NowIndianTime();
                    sp.IsActive = true;

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

                    Subscriptions subscriptions = _context.Subscriptions.Where(s => s.Id == subscription_id).FirstOrDefault();
                    subscriptions.RemainingExamCredits -= points_needed;
                    _context.Subscriptions.Update(subscriptions);
                    _context.SaveChanges();
                }

                practiceAttempts.PracticeId = practice_id;
                practiceAttempts.CreatedBy = user_id;
                practiceAttempts.CreatedOn = NowIndianTime();
                practiceAttempts.UpdatedBy = user_id;
                practiceAttempts.UpdatedOn = NowIndianTime();
                practiceAttempts.Status = State.START;
                practiceAttempts.IsActive = true;

                _context.PracticeAttempts.Add(practiceAttempts);
                _context.SaveChanges();

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

            return practiceAttempts.Id;
        }

        internal PracticeAttemptViewModel GetPracticeAttemptById(int institute_id, int newPracticeAttemptId)
        {
            PracticeAttemptViewModel practiceAttempt = new PracticeAttemptViewModel();
            practiceAttempt = (from pa in _context.PracticeAttempts
                               join p in _context.Practices on pa.PracticeId equals p.Id
                           join u in _context.Users on pa.CreatedBy equals u.Id
                           where pa.Id == newPracticeAttemptId
                           select new PracticeAttemptViewModel
                           {
                               practice_id = pa.PracticeId,
                               attempt_id = pa.Id,
                               attempt_status = pa.Status,
                               attempt_started_on = (DateTime)pa.CreatedOn,
                               topic_name = (p.Module == Constant.Subject) ?
                                      _context.Subjects.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name :
                                      _context.Categories.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name,
                               total_questions = _context.PracticeQuestions.Where(pq => pq.PracticeId == p.Id).Count(),
                               instruction = p.Instruction,
                               attempt_started_by = u.Id
                           }
                           ).FirstOrDefault();

            if (practiceAttempt == null) return null;

            return practiceAttempt;
        }

        internal PracticeAttemptAllQuestionsViewModel GetPracticeAttemptPracticeQuestions(int language_id, int practice_id)
        {
            PracticeAttemptAllQuestionsViewModel paqvm = (from p in _context.Practices

                                                          where p.Id == practice_id && p.IsActive == true
                                                          select new PracticeAttemptAllQuestionsViewModel
                                                          {
                                                              practice_id = p.Id,
                                                              practice_name = p.Name,
                                                              language = _context.Languages.Where(l => l.Id == p.LanguageId).FirstOrDefault().Code,
                                                              language_id = p.LanguageId,
                                                              module = p.Module,
                                                              module_id = p.ModuleId,
                                                              module_name = (p.Module == Constant.Subject) ?
                                                                _context.Subjects.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name :
                                                                _context.Categories.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name
                                                          }
                                                      ).FirstOrDefault();

            if (paqvm == null) return null;

            var Lang1 = _context.Languages.Where(l => l.Id == language_id).FirstOrDefault();
            var Lang2 = _context.Languages.Where(l => l.Code == "en").FirstOrDefault();
            var Lang3 = _context.Languages.Where(l => l.Id == paqvm.language_id).FirstOrDefault();
            if (Lang2 == null) Lang2 = Lang3;

            List<PracticeQuestions> practiceQns = _context.PracticeQuestions.Where(p => p.PracticeId == paqvm.practice_id && p.IsActive == true).ToList();

            var qns = (from pq in practiceQns
                       join qu in _context.Questions on pq.QuestionId equals qu.Id
                       join qt in _context.QuestionTypes on qu.TypeId equals qt.Id
                       join ql in _context.QuestionLanguges on qu.Id equals ql.QuestionId into qnslans
                       
                       //where qnslans.All(x => x.LanguageId == Lang1.Id || x.LanguageId == Lang2.Id || x.LanguageId == Lang3.Id)

                       select new
                       {
                            p = pq,
                            q = qu,
                            t = qt,
                            ql = qnslans
                       });

            List<PracticeAttemptQuestionsViewModel> qnsList = new List<PracticeAttemptQuestionsViewModel>();

            foreach(var qDetails in qns)
            {
                PracticeAttemptQuestionsViewModel qd = new PracticeAttemptQuestionsViewModel();
                qd.id = qDetails.q.Id;
                var qlan = qDetails.ql.Where(i => i.LanguageId == Lang1.Id).FirstOrDefault();
                var Lang = Lang1;

                if (qlan == null)
                {
                    qlan = qDetails.ql.Where(i => i.LanguageId == Lang2.Id).FirstOrDefault();
                    Lang = Lang2;
                }

                if (qlan == null)
                {
                    qlan = qDetails.ql.Where(i => i.LanguageId == Lang3.Id).FirstOrDefault();
                    Lang = Lang3;
                }
                qd.language_id = Lang.Id;
                qd.language_code = Lang.Code;
                qd.type_code = qDetails.t.Code;
                qd.type_text = qDetails.t.Name;
                qd.question_text = qlan.Question;
                qd.answer_explanation = qlan.AnswerExplanation;
                qd.complexity_code = qDetails.q.ComplexityCode;

                qnsList.Add(qd);
            }
            
            paqvm.questions = qnsList;

            foreach (PracticeAttemptQuestionsViewModel qvm in qnsList)
            {
                List<PracticeAttemptQuestionOptionViewModel> options = (from q in _context.Questions
                                                                        join qo in _context.QuestionOptions on q.Id equals qo.QuestionId
                                                                        join qol in _context.QuestionOptionLanguages on qo.Id equals qol.QuestionOptionId

                                                                        where q.Id == qvm.id
                                                                        && qo.IsActive == true
                                                                        && qol.LanguageId == qvm.language_id && qol.IsActive == true

                                                                        select new PracticeAttemptQuestionOptionViewModel
                                                                        {
                                                                            id = qo.Id,
                                                                            text = qol.OptionText,
                                                                            isCorrect = (bool)qo.IsCorrect
                                                                        }
                                                  ).ToList();

                qvm.options = options;
            }

            paqvm.total_questions = qnsList.Count;

            return paqvm;
        }

        /*
                internal PracticeAttemptAllQuestionsViewModel GetPracticeAttemptQuestions(int language_id, int attempt_id)
                {
                    PracticeAttemptAllQuestionsViewModel paqvm = (from a in _context.PracticeAttempts
                                                              join p in _context.Practices on a.PracticeId equals p.Id

                                                              where a.Id == attempt_id && a.IsActive == true
                                                              select new PracticeAttemptAllQuestionsViewModel
                                                                  {
                                                                      practice_id = p.Id,
                                                                      practice_name = p.Name,
                                                                      practice_language = (int)p.LanguageId,
                                                                      module = p.Module,
                                                                      module_id = p.ModuleId,
                                                                      module_name = (p.Module == Constant.Subject) ?
                                                                        _context.Subjects.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name :
                                                                        _context.Categories.Where(s => s.Id == p.ModuleId).FirstOrDefault().Name
                                                              }
                                                              ).FirstOrDefault();

                    if (paqvm == null) return null;

                    List<PracticeAttemptQuestionsViewModel> qns = (from pq in _context.PracticeQuestions
                                                                   join q in _context.Questions on pq.QuestionId equals q.Id
                                                                   join ql in _context.QuestionLanguges on q.Id equals ql.QuestionId

                                                                   where pq.PracticeId == paqvm.practice_id
                                                                   && (ql.LanguageId == language_id || ql.LanguageId == paqvm.practice_language)

                                                                   select new PracticeAttemptQuestionsViewModel
                                                                   {
                                                                       id = q.Id,
                                                                       language_id = (int)ql.LanguageId,
                                                                       language_code = _context.Languages.Where(l => l.Id == ql.LanguageId).FirstOrDefault().Code,
                                                                       type_code = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Code,
                                                                       type_text = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Name,
                                                                       question_text = ql.Question,
                                                                   }
                                                             ).ToList();

                        if (qns == null) return null;
                        List<int> allSelectedIds = new List<int>();

                        foreach (PracticeAttemptQuestionsViewModel q in qns)
                        {
                            PracticeAttemptAnswers paa = _context.PracticeAttemptAnswers.Where(aa => aa.PracticeAttemptId == attempt_id && aa.QuestionId == q.id).FirstOrDefault();
                            List<int> selectedIds = new List<int>();
                            if (paa == null)
                            {
                                q.isVisited = false;
                            }
                            else
                            {
                                q.isVisited = paa.IsVisited == null ? false : (bool)paa.IsVisited;
                                selectedIds = (paa.StudentAnswer == null || paa.StudentAnswer.Length == 0) ? null : paa.StudentAnswer.Split(',').Select(int.Parse).ToList();
                            }
                            if (selectedIds != null) allSelectedIds.AddRange(selectedIds);

                        }

                        //return questions based on language selected during attempt
                        List<PracticeAttemptQuestionsViewModel> qns1 = new List<PracticeAttemptQuestionsViewModel>();
                        List<PracticeAttemptQuestionsViewModel> qns2 = new List<PracticeAttemptQuestionsViewModel>();

                        qns1 = qns.GroupBy(plem => plem.id).Select(group => group.First()).ToList();
                        qns2 = qns.GroupBy(plem => plem.id).Select(group => group.Last()).ToList();

                        int n1 = qns1.Where(x => x.language_id == language_id).Count();
                        int n2 = qns2.Where(x => x.language_id == language_id).Count();

                        qns = n2 > n1 ? qns2 : qns1;

                        paqvm.questions = qns;

                        foreach (PracticeAttemptQuestionsViewModel qvm in qns)
                        {
                            List<PracticeAttemptQuestionOptionViewModel> options = (from q in _context.Questions
                                                                                join qo in _context.QuestionOptions on q.Id equals qo.QuestionId
                                                                                join qol in _context.QuestionOptionLanguages on qo.Id equals qol.QuestionOptionId

                                                                                where q.Id == qvm.id
                                                                                && qo.IsActive == true
                                                                                && qol.LanguageId == qvm.language_id && qol.IsActive == true

                                                                                select new PracticeAttemptQuestionOptionViewModel
                                                                                {
                                                                                    id = qo.Id,
                                                                                    text = qol.OptionText,
                                                                                    isSelected = allSelectedIds.Contains(qo.Id)
                                                                                }
                                                              ).ToList();

                            qvm.options = options;
                        }

                        paqvm.total_questions = qns.Count;            

                        return paqvm;
                }
        */

        internal ExamAttemptViewModel GetExamAttemptById(int newExamAttemptId)
        {
            ExamAttemptViewModel examattempt = new ExamAttemptViewModel();
            examattempt = (from ea in _context.ExamAttempts
                                                join e in _context.Exams on ea.ExamId equals e.Id
                                                join u in _context.Users on ea.CreatedBy equals u.Id
                                                where ea.Id == newExamAttemptId
                                                select new ExamAttemptViewModel
                                                {
                                                    exam_id = ea.ExamId,
                                                    attempt_id = ea.Id,
                                                    attempts_allowed = (short)e.AttemptsAllowed,
                                                    attempts_completed = (short)_context.ExamAttempts.Where(a => a.ExamId == ea.ExamId).ToList().Count,
                                                    attempt_status = ea.Status,
                                                    attempt_started_on = (DateTime)ea.CreatedOn,
                                                    instruction = e.Instruction
                                                }
                           ).FirstOrDefault();

            if (examattempt == null) return null;

            List<ExamSections> examSections;
            List<ExamQuestionsMarkWeight> examQuestions;
            List<ExamAttemptSectionsViewModel> examAttemptSections = new List<ExamAttemptSectionsViewModel>();
            examattempt.total_questions = 0;
            examattempt.total_marks = 0;

            examSections = _context.ExamSections.Where(s => s.ExamId == examattempt.exam_id && s.IsActive == true).ToList();

            foreach (ExamSections s in examSections)
            {
                ExamAttemptSectionsViewModel eas = new ExamAttemptSectionsViewModel();

                eas.id = s.Id;
                eas.name = _context.Subjects.Where(sub => sub.Id == s.SubjectId).FirstOrDefault().Name.ToString();
                eas.sequence = (short)s.SubjectSequence;
                eas.duration = s.SubjectDuration;
                eas.cutoff_mark = 0;
                
                examQuestions = _context.ExamQuestionsMarkWeight.Where(q => q.ExamSectionId == s.Id).ToList();
                if (examQuestions.Count() > 0)
                {
                    eas.total_questions = examQuestions.Count();
                    examattempt.total_questions += examQuestions.Count();
                }

                foreach (ExamQuestionsMarkWeight q in examQuestions)
                {
                    if (q.MarkForCorrectAnswer != null)
                    {
                        eas.total_marks = (double)q.MarkForCorrectAnswer;
                        examattempt.total_marks += (double)q.MarkForCorrectAnswer;
                    }                        
                }

                examAttemptSections.Add(eas);
            }
            examattempt.sections = examAttemptSections;

            return examattempt;
        }

        internal ExamAttemptViewModel GetExamAttemptBasicById(int newExamAttemptId)
        {
            ExamAttemptViewModel examattempt = (from ea in _context.ExamAttempts
                                                   join e in _context.Exams on ea.ExamId equals e.Id
                                                   join u in _context.Users on ea.CreatedBy equals u.Id

                                                   where ea.Id == newExamAttemptId
                                                   select new ExamAttemptViewModel
                                                   {
                                                       exam_id = ea.ExamId,
                                                       attempt_id = ea.Id,
                                                       attempts_allowed = (short)e.AttemptsAllowed,
                                                       attempts_completed = (short)_context.ExamAttempts.Where(a => a.ExamId == ea.ExamId).ToList().Count,
                                                   }
                           ).FirstOrDefault();

            return examattempt;
        }


        internal List<ExamAttemptViewModel> GetAllExamAttemptsOfTheExam(int exam_id, int? user_id, string sortBy, string sortOrder)
        {
            List<ExamAttempts> attempts;
            List<ExamAttemptViewModel> attemptList = new List<ExamAttemptViewModel>();

            if (user_id == null)
            {
                attempts = _context.ExamAttempts.Where(e => e.ExamId == exam_id).Where(e => e.IsActive == true).ToList();
            }
            else
            {
                attempts = _context.ExamAttempts.Where(e => e.ExamId == exam_id && e.CreatedBy == user_id).ToList();
            }


            foreach (ExamAttempts a in attempts)
            {
                ExamAttemptViewModel eav = GetExamAttemptBasicById(a.Id);
                attemptList.Add(eav);
            }

            //List<QuestionViewModel> questionListNew = new List<QuestionViewModel>();
            if ((sortOrder != null && sortOrder.Length > 0) || (sortBy != null && sortBy.Length > 0))
            {
                if (sortOrder != null && sortOrder.Equals("D"))
                {
                    switch (sortBy.ToUpper())
                    {
                        case "ID": attemptList = attemptList.OrderByDescending(a => a.attempt_id).ToList(); break;
                        case "QUESTION": attemptList = attemptList.OrderByDescending(a => a.total_questions).ToList(); break;
                    }

                }
                else
                {
                    switch (sortBy.ToUpper())
                    {
                        case "ID": attemptList = attemptList.OrderBy(a => a.attempt_id).ToList(); break;
                        case "QUESTION": attemptList = attemptList.OrderBy(a => a.total_questions).ToList(); break;
                    }
                }
            }


            return attemptList;
        }

        internal List<ExamAttemptViewModel> GetAllExamAttempts(int? user_id)
        {
            List<ExamAttempts> attempts;
            List<ExamAttemptViewModel> attemptList = new List<ExamAttemptViewModel>();

            if (user_id == null)
            {
                attempts = _context.ExamAttempts.Where(e => e.ExamId == 1).Where(e => e.IsActive == true).ToList();
            }
            else
            {
                attempts = _context.ExamAttempts.Where(e => e.ExamId == 1 && e.CreatedBy == user_id).ToList();
            }

            foreach (ExamAttempts a in attempts)
            {
                ExamAttemptViewModel eav = GetExamAttemptBasicById(a.Id);
                attemptList.Add(eav);
            }

            return attemptList;
        }


        internal ExamAttemptAllQuestionsViewModel GetExamAttemptQuestions(int language_id, int attempt_id)
        {
            ExamAttemptAllQuestionsViewModel eaqvm = (from a in _context.ExamAttempts
                                                      join e in _context.Exams on a.ExamId equals e.Id

                                                      where a.Id == attempt_id && a.IsActive == true

                                                      select new ExamAttemptAllQuestionsViewModel
                                                      {
                                                          exam_id = e.Id,
                                                          exam_name = e.Name,
                                                          exam_language = (int)e.LanguageId,
                                                          time_left = a.RemainingTimeSeconds
                                                      }
                                                      ).FirstOrDefault();

            if (eaqvm == null) return null;
            eaqvm.attempt_id = attempt_id;

            List<ExamAttemptSectionQuestionsViewModel> eaSectionsList = (from s in _context.ExamSections
                                                                         join sub in _context.Subjects on s.SubjectId equals sub.Id
                                                                         
                                                                         where s.ExamId ==  eaqvm.exam_id && s.IsActive == true
                                                                         
                                                                         select new ExamAttemptSectionQuestionsViewModel
                                                                         {
                                                                             id = s.Id,
                                                                             section_duration = s.SubjectDuration,
                                                                             section_sequence = s.SubjectSequence,
                                                                             subject_id = sub.Id,
                                                                             subject_name = sub.Name,
                                                                             duration = s.SubjectDuration,
                                                                             cutoff_mark = s.TotalMarks //TODO: cutoff mark
                                                                         }
                                                      ).ToList();

            if (eaSectionsList == null) return null;

            eaqvm.sections = eaSectionsList;

            foreach(ExamAttemptSectionQuestionsViewModel s in eaSectionsList)
            {
                 List<ExamAttemptQuestionsViewModel> qns = (from eq in _context.ExamQuestionsMarkWeight
                                                            join q in _context.Questions on eq.QuestionId equals q.Id
                                                            join ql in _context.QuestionLanguges on q.Id equals ql.QuestionId

                                                            where eq.ExamSectionId == s.id 
                                                            && (ql.LanguageId ==  language_id || ql.LanguageId == eaqvm.exam_language)

                                                            select new ExamAttemptQuestionsViewModel
                                                            {
                                                                id = q.Id,
                                                                language_id = (int)ql.LanguageId,
                                                                language_code = _context.Languages.Where(l => l.Id == ql.LanguageId).FirstOrDefault().Code,
                                                                type_code = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Code,
                                                                type_text = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Name,
                                                                question_text = ql.Question,
                                                                correct_marks = eq.MarkForCorrectAnswer,
                                                                wrong_marks = eq.MarkForWrongAnswer,
                                                            }
                                                      ).ToList();
                
                if (qns == null) return null;
                List<int> allSelectedIds = new List<int>();

                foreach (ExamAttemptQuestionsViewModel q in qns)
                {
                    ExamAttemptsAnswer eaa = _context.ExamAttemptsAnswer.Where(aa => aa.ExamAttemptId == attempt_id && aa.QuestionId == q.id).FirstOrDefault();
                    List<int> selectedIds = new List<int>();
                    if (eaa == null) 
                    {
                        q.isVisited = false;
                        q.isReviewMarked = false;
                    } else
                    {
                        q.isReviewMarked = eaa.IsReviewed == null ? false : (bool)eaa.IsReviewed;
                        q.isVisited = eaa.IsVisited == null ? false : (bool)eaa.IsVisited;
                        selectedIds = (eaa.StudentAnswer == null || eaa.StudentAnswer.Length == 0) ? null : eaa.StudentAnswer.Split(',').Select(int.Parse).ToList();
                    }
                    if(selectedIds != null) allSelectedIds.AddRange(selectedIds);
                    
                }
                
                //return questions based on language selected during attempt
                List<ExamAttemptQuestionsViewModel> qns1 = new List<ExamAttemptQuestionsViewModel>();
                List<ExamAttemptQuestionsViewModel> qns2 = new List<ExamAttemptQuestionsViewModel>();

                qns1 = qns.GroupBy(elem => elem.id).Select(group => group.First()).ToList();
                qns2 = qns.GroupBy(elem => elem.id).Select(group => group.Last()).ToList();

                int n1 = qns1.Where(x => x.language_id == language_id).Count();
                int n2 = qns2.Where(x => x.language_id == language_id).Count();

                qns = n2 > n1 ? qns2 : qns1;

                s.questions = qns;

                foreach (ExamAttemptQuestionsViewModel qvm in qns)
                {
                    List<ExamAttemptQuestionOptionViewModel> options = (from q in _context.Questions
                                                                        join qo in _context.QuestionOptions on q.Id equals qo.QuestionId
                                                                        join qol in _context.QuestionOptionLanguages on qo.Id equals qol.QuestionOptionId
                                                                        
                                                                        where q.Id == qvm.id 
                                                                        && qo.IsActive == true 
                                                                        && qol.LanguageId == qvm.language_id && qol.IsActive == true
                                                                        
                                                                        select new ExamAttemptQuestionOptionViewModel
                                                                        {
                                                                            id = qo.Id,
                                                                            text = qol.OptionText,
                                                                            isSelected = allSelectedIds.Contains(qo.Id)
                                                                        }
                                                      ).ToList();
                    
                    qvm.options = options;
                }

                s.total_marks = (double)qns.Sum(m => m.correct_marks);
                s.total_questions = qns.Count;                
            }


            return eaqvm;
        }


        internal List<ExamAttemptsAnswer> examAttempt_updateAttemptCorrectness(int attempt_id)
        {
            int exam_id = _context.ExamAttempts.Where(a => a.Id == attempt_id).Select(a => a.ExamId).FirstOrDefault();
            List<int> sectionIds = new List<int>();
            sectionIds = _context.ExamSections.Where(s => s.ExamId == exam_id && s.IsActive == true).Select(s => s.Id).ToList();

            List<ExamAttemptsAnswer> examAttemptsAnswers = _context.ExamAttemptsAnswer.Where(a => a.ExamAttemptId == attempt_id && a.IsActive == true).ToList();
            List<ExamAttemptsAnswer> finalAnswers = new List<ExamAttemptsAnswer>();

            foreach (ExamAttemptsAnswer answer in examAttemptsAnswers)
            {
                string type = (from q in _context.Questions 
                               join t in _context.QuestionTypes on q.TypeId equals t.Id
                               where q.Id == answer.QuestionId
                               select t.Code).FirstOrDefault();

                if(type == QuestionTypeCode.SUB.ToString())
                {
                    continue;
                }

                //Collect the list of options selected by user in the attempt
                List<int> selectedIds = new List<int>();
                selectedIds = (answer.StudentAnswer == null || answer.StudentAnswer.Length == 0) ? null : answer.StudentAnswer.Split(',').Select(int.Parse).ToList();

                //if its not visted or no option selected then go to next question 
                if (answer.IsVisited == false || selectedIds == null || selectedIds.Count <= 0)
                {
                    answer.IsCorrect = null;
                    answer.Score = 0;
                    //answer.Score = _context.ExamQuestionsMarkWeight.Where(m => m.QuestionId == answer.QuestionId && sectionIds.Contains(m.ExamSectionId)).Select(m => m.MarkForWrongAnswer)
                    finalAnswers.Add(answer);
                    continue;
                }

                //Collect the list of correct options of that question
                List<int> correctIds = new List<int>();
                correctIds = (from o in _context.QuestionOptions
                              where o.QuestionId == answer.QuestionId && o.IsCorrect == true && o.IsActive == true
                              select o.Id).ToList();

                //compare options selected with correct options
                List<int> distinct = selectedIds.Except(correctIds).ToList();
                if(distinct == null || distinct.Count == 0)
                {
                    distinct = correctIds.Except(selectedIds).ToList();
                    if (distinct == null || distinct.Count == 0)
                    {
                        answer.IsCorrect = true;
                        answer.Score = _context.ExamQuestionsMarkWeight.Where(m => m.QuestionId == answer.QuestionId && sectionIds.Contains(m.ExamSectionId)).Select(m => m.MarkForCorrectAnswer).FirstOrDefault();
                        finalAnswers.Add(answer);
                        continue;
                    }
                }
                
                answer.IsCorrect = false;
                answer.Score = _context.ExamQuestionsMarkWeight.Where(m => m.QuestionId == answer.QuestionId && sectionIds.Contains(m.ExamSectionId)).Select(m => m.MarkForWrongAnswer).FirstOrDefault();
                finalAnswers.Add(answer);
            }

            return finalAnswers;
        }

        internal ExamAttemptReportViewModel _examAttempt_getReport(int language_id, int attempt_id)
        {
            ExamAttemptReportViewModel eaqvm = (from a in _context.ExamAttempts
                                                      join e in _context.Exams on a.ExamId equals e.Id

                                                      where a.Id == attempt_id && a.IsActive == true

                                                      select new ExamAttemptReportViewModel
                                                      {
                                                          exam_id = e.Id,
                                                          exam_name = e.Name,
                                                          exam_language = (int)e.LanguageId,
                                                          time_left = a.RemainingTimeSeconds,
                                                          marks_scored = (double)a.Score
                                                      }
                                                      ).FirstOrDefault();

            if (eaqvm == null) return null;

            //num of values below score / total no of scores * 100
            List<ExamAttempts> examAttempted = _context.ExamAttempts.Where(a => a.ExamId == eaqvm.exam_id && 
                    a.Score != null && a.Status == State.COMPLETED && a.IsActive == true).ToList();
            if (examAttempted == null)
                return null;

            List<ExamAttempts> examAttemptedWithLowScore = examAttempted.Where(l => l.Score < eaqvm.marks_scored).ToList();

            float nLowScore = 0;

            if (examAttemptedWithLowScore == null)
                nLowScore = 0;
            else
                nLowScore = examAttemptedWithLowScore.Count;

            eaqvm.percentile_scored = (float) (nLowScore / examAttempted.Count * 100);
                

            List<ExamAttemptSectionReportViewModel> eaSectionsList = (from s in _context.ExamSections
                                                                         join sub in _context.Subjects on s.SubjectId equals sub.Id

                                                                         where s.ExamId == eaqvm.exam_id && s.IsActive == true

                                                                         select new ExamAttemptSectionReportViewModel
                                                                         {
                                                                             id = s.Id,
                                                                             section_duration = s.SubjectDuration,
                                                                             section_sequence = s.SubjectSequence,
                                                                             subject_id = sub.Id,
                                                                             subject_name = sub.Name,
                                                                             duration = s.SubjectDuration,
                                                                             cutoff_mark = s.TotalMarks//TODO: cutoff mark                         
                                                                         }
                                                      ).ToList();

            if (eaSectionsList == null) return null;

            eaqvm.sections = eaSectionsList;

            foreach (ExamAttemptSectionReportViewModel s in eaSectionsList)
            {
                List<ExamAttemptQuestionReportViewModel> qns = (from eq in _context.ExamQuestionsMarkWeight
                                                           join q in _context.Questions on eq.QuestionId equals q.Id
                                                           join ql in _context.QuestionLanguges on q.Id equals ql.QuestionId
                                                           join qc in _context.QuestionCategories on q.Id equals qc.QuestionId
                                                           join cat in _context.Categories on qc.CategoryId equals cat.Id
                                                           join sub in _context.Subjects on cat.SubjectId equals sub.Id

                                                           where eq.ExamSectionId == s.id
                                                           && (ql.LanguageId == language_id || ql.LanguageId == eaqvm.exam_language)
                                                           && qc.IsActive == true
                                                           && cat.IsActive == true
                                                           && sub.Id == s.subject_id && sub.IsActive == true

                                                           select new ExamAttemptQuestionReportViewModel
                                                           {
                                                               id = q.Id,
                                                               language_id = (int)ql.LanguageId,
                                                               language_code = _context.Languages.Where(l => l.Id == ql.LanguageId).FirstOrDefault().Code,
                                                               type_code = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Code,
                                                               type_text = _context.QuestionTypes.Where(t => t.Id == q.TypeId).FirstOrDefault().Name,
                                                               topic = cat.Name,
                                                               question_text = ql.Question,
                                                               correct_marks = eq.MarkForCorrectAnswer,
                                                               wrong_marks = eq.MarkForWrongAnswer,
                                                               complexity_code = (short)q.ComplexityCode
                                                           }
                                                     ).ToList();

                if (qns == null) return null;

                List<int> allSelectedIds = new List<int>();
                foreach (ExamAttemptQuestionReportViewModel q in qns)
                {
                    ExamAttemptsAnswer eaa = _context.ExamAttemptsAnswer.Where(aa => aa.ExamAttemptId == attempt_id && aa.QuestionId == q.id).FirstOrDefault();
                    q.isAttempted = false;
                    List<int> selectedIds = new List<int>();
                    if (eaa == null)
                    {
                        q.isCorrect = false;
                    }
                    else
                    {
                        q.isCorrect = eaa.IsCorrect == null ? false : (bool)eaa.IsCorrect;
                        selectedIds = (eaa.StudentAnswer == null || eaa.StudentAnswer.Length == 0) ? null : eaa.StudentAnswer.Split(',').Select(int.Parse).ToList();
                        q.duration = eaa.AnswerDurationSeconds;
                    }
                    if (selectedIds != null && selectedIds.Count > 0)
                    {
                        allSelectedIds.AddRange(selectedIds);
                        q.isAttempted = true;
                    }
                    
                }


                //return questions based on language selected during attempt
                List<ExamAttemptQuestionReportViewModel> qns1 = new List<ExamAttemptQuestionReportViewModel>();
                List<ExamAttemptQuestionReportViewModel> qns2 = new List<ExamAttemptQuestionReportViewModel>();

                qns1 = qns.GroupBy(elem => elem.id).Select(group => group.First()).ToList();
                qns2 = qns.GroupBy(elem => elem.id).Select(group => group.Last()).ToList();

                int n1 = qns1.Where(x => x.language_id == language_id).Count();
                int n2 = qns2.Where(x => x.language_id == language_id).Count();

                qns = n2 > n1 ? qns2 : qns1;

                s.questions = qns;

                foreach (ExamAttemptQuestionReportViewModel qvm in qns)
                {
                    List<ExamAttemptOptionReportViewModel> options = (from q in _context.Questions
                                                                        join qo in _context.QuestionOptions on q.Id equals qo.QuestionId
                                                                        join qol in _context.QuestionOptionLanguages on qo.Id equals qol.QuestionOptionId

                                                                        where q.Id == qvm.id
                                                                        && qo.IsActive == true
                                                                        && qol.LanguageId == qvm.language_id && qol.IsActive == true

                                                                        select new ExamAttemptOptionReportViewModel
                                                                        {
                                                                            id = qo.Id,
                                                                            text = qol.OptionText,
                                                                            isSelected = allSelectedIds.Contains(qo.Id),
                                                                            isCorrect = (bool)qo.IsCorrect
                                                                        }
                                                      ).ToList();

                    qvm.options = options;
                }

                s.total_marks = (double)qns.Sum(m => m.correct_marks);
                s.total_nMarks = (double)qns.Sum(m => m.wrong_marks);
                s.total_questions = qns.Count;
            }


            return eaqvm;
        }

        public SubscriptionViewModel mySubscriptionDetails(int user_id)
        {
            DateTime now = NowIndianTime();
            Subscriptions sub = _context.Subscriptions.Where(s => s.UserId == user_id && s.IsActive == true &&
                    s.IsCancelled == false && s.StartDate <= now && s.EndDate >= now).FirstOrDefault();

            if (sub == null)
                return null;

            Plans plan = _context.Plans.Where(p => p.Id == sub.PlanId).FirstOrDefault();
            if (plan == null)
                return null;

            SubscriptionViewModel svm = new SubscriptionViewModel();
            svm.id = sub.Id;
            svm.IsActive = sub.IsActive;
            svm.plan_code = plan.Code;
            svm.plan_name = plan.Name;
            svm.total_exam_credits = (short)sub.TotalExamCredits;
            svm.total_practice_credits = (short)sub.TotalPracticeCredits;
            svm.remaining_exam_credits = (short)sub.RemainingExamCredits;
            svm.remaining_practice_credits = (short)sub.RemainingPracticeCredits;
            svm.start_date = sub.StartDate;
            svm.end_date = sub.EndDate;
            svm.status = sub.Status;
            svm.created_on = sub.CreatedOn;
            svm.updated_on = sub.UpdatedOn;

            return svm;
        }


        public string CreateSlug(string Title)
        {
            string Slug = Title.ToLower();
            // Replace characters specific fo croatian language
            // You don't need this part for english language
            // Also, you can replace other characters specific for other languages
            // e.g. é to e for French language etc.
            Slug = Slug.Replace("č", "c");
            Slug = Slug.Replace("ć", "c");
            Slug = Slug.Replace("š", "s");
            Slug = Slug.Replace("ž", "z");
            Slug = Slug.Replace("đ", "dj");

            // Replace - with empty space
            Slug = Slug.Replace("-", " ");

            // Replace unwanted characters with space
            Slug = Regex.Replace(Slug, "[^a-z0-9\\s-]", " ");
            // Replace multple white spaces with single space
            Slug = Regex.Replace(Slug, "\\s+", " ").Trim();
            // Replace white space with -
            Slug = Slug.Replace(" ", "-");

            return Slug;
        }

    }
}
