using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OnlineAssessment.Common;
using OnlineAssessment.Data.EFCore;
using OnlineAssessment.Domain.Models;
using OnlineAssessment.Domain.ViewModels;

namespace OnlineAssessment.V1.Controllers
{
    [ApiController]
    [ApiVersion("1.0")]
    [Route("v{version:apiVersion}")]
    public class QuestionsController : BaseController<Institutes, EFCoreInstituteRepository>
    {
        EFCoreInstituteRepository _repository;
        string responseMessage = string.Empty;

        public QuestionsController(EFCoreInstituteRepository repository) : base(repository)
        {
            _repository = repository;
        }

        
        #region Questions

        /// <summary>
        /// Get all questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="class_id"></param>
        /// <param name="type"></param>
        /// <param name="module"></param>
        /// <param name="module_id"></param>
        /// <param name="complexity"></param>
        /// <param name="author_id"></param>
        /// <param name="translation_missing"></param>
        /// <param name="sortBy"></param>
        /// <param name="sortOrder"></param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpGet("{language}/Classes/{class_id}/Questions")]
        [Authorize(Roles = "Admin")]
        public IActionResult GetAllQuestionsOfTheClass(string language, int class_id, [FromQuery] string type, string module, int module_id, int complexity, int author_id, string translation_missing, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize)
        {
            IActionResult returnResponse;
            QuestionViewAllPagedModel qnsListPaged = new QuestionViewAllPagedModel();
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0)
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            int translation_missing_id = _repository.GetLanguageIdByCode(translation_missing);
            if (translation_missing_id <= 0)
                translation_missing_id = -1;

            if (pageNumber == null) pageNumber = 1;
            if (pageSize == null) pageSize = 20;

            if(module == null)
            {
                module = Constant.Class.ToUpper();
                module_id = class_id;
            }

            module = module.ToUpper();

            if (!(module == Constant.Class.ToUpper() || module == Constant.Subject.ToUpper() 
                || module == Constant.Category.ToUpper()))
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            List<QuestionViewAllModel> theList = _repository.GetAllQuestionsOfClass(base.InstituteId, user_id, language_id, class_id, type, module, module_id, complexity, author_id, translation_missing_id, sortBy, sortOrder);

            if (pageNumber != null && pageSize != null)
            {
                    PaginatedList<QuestionViewAllModel> pList = PaginatedList<QuestionViewAllModel>.CreateAsync(theList, (int)pageNumber, (int)pageSize);
                    qnsListPaged.total_count = theList.Count;
                    qnsListPaged.total_pages = pList.TotalPages;
                    qnsListPaged.page_index = pList.PageIndex;
                    qnsListPaged.next = pList.HasNextPage;
                    qnsListPaged.previous = pList.HasPreviousPage;
                    qnsListPaged.questions = pList;
            }
            
            returnResponse = Ok(ReturnResponse.GetSuccessStatus(qnsListPaged));
            
            return returnResponse;
        }


        /// <summary>
        /// Get all draft questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="class_id"></param>
        /// <param name="type"></param>
        /// <param name="module"></param>
        /// <param name="module_id"></param>
        /// <param name="complexity"></param>
        /// <param name="sortBy"></param>
        /// <param name="sortOrder"></param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpGet("{language}/Classes/{class_id}/DraftQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult GetAllDraftQuestionsOfTheClass(string language, int class_id, [FromQuery] string type, string module, int module_id, int complexity, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize)
        {
            IActionResult returnResponse;
            QuestionViewAllPagedModel qnsListPaged = new QuestionViewAllPagedModel();
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0)
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            if (pageNumber == null) pageNumber = 1;
            if (pageSize == null) pageSize = 20;

            if (module == null)
            {
                module = Constant.Class.ToUpper();
                module_id = class_id;
            }

            module = module.ToUpper();

            if (!(module == Constant.Class.ToUpper() || module == Constant.Subject.ToUpper()
                || module == Constant.Category.ToUpper()))
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            List<QuestionViewAllModel> theList = _repository.GetAllDraftQuestionsOfClass(base.InstituteId, user_id, language_id, class_id, type, module, module_id, complexity, -1, sortBy, sortOrder);

            if (pageNumber != null && pageSize != null)
            {
                    PaginatedList<QuestionViewAllModel> pList = PaginatedList<QuestionViewAllModel>.CreateAsync(theList, (int)pageNumber, (int)pageSize);
                    qnsListPaged.total_count = theList.Count;
                    qnsListPaged.total_pages = pList.TotalPages;
                    qnsListPaged.page_index = pList.PageIndex;
                    qnsListPaged.next = pList.HasNextPage;
                    qnsListPaged.previous = pList.HasPreviousPage;
                    qnsListPaged.questions = pList;
            }
            returnResponse = Ok(ReturnResponse.GetSuccessStatus(qnsListPaged));
            return returnResponse;
        }


        /// <summary>
        /// Get all draft questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="class_id"></param>
        /// <param name="type"></param>
        /// <param name="module"></param>
        /// <param name="module_id"></param>
        /// <param name="complexity"></param>
        /// <param name="translation_missing"></param>
        /// <param name="sortBy"></param>
        /// <param name="sortOrder"></param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpGet("{language}/Classes/{class_id}/BookmarkedQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult GetAllBookmarkedQuestionsOfTheClass(string language, int class_id, [FromQuery] string type, string module, int module_id, int complexity, string translation_missing, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize)
        {
            IActionResult returnResponse;
            QuestionViewAllPagedModel qnsListPaged = new QuestionViewAllPagedModel();
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0)
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            int translation_missing_id = _repository.GetLanguageIdByCode(translation_missing);
            if (translation_missing_id <= 0)
                translation_missing_id = -1;


            if (pageNumber == null) pageNumber = 1;
            if (pageSize == null) pageSize = 20;

            if (module == null)
            {
                module = Constant.Class.ToUpper();
                module_id = class_id;
            }

            module = module.ToUpper();

            if (!(module == Constant.Class.ToUpper() || module == Constant.Subject.ToUpper()
                || module == Constant.Category.ToUpper()))
            {
                returnResponse = Ok(ReturnResponse.GetFailureStatus(Message.InvalidInput.ToString()));
                return returnResponse;
            }

            List<QuestionViewAllModel> theList = _repository.GetAllBookmarkedQuestionsOfClass(base.InstituteId, user_id, language_id, class_id, type, module, module_id, complexity, translation_missing_id, sortBy, sortOrder);

            if (pageNumber != null && pageSize != null)
            {
                    PaginatedList<QuestionViewAllModel> pList = PaginatedList<QuestionViewAllModel>.CreateAsync(theList, (int)pageNumber, (int)pageSize);
                    qnsListPaged.total_count = theList.Count;
                    qnsListPaged.total_pages = pList.TotalPages;
                    qnsListPaged.page_index = pList.PageIndex;
                    qnsListPaged.next = pList.HasNextPage;
                    qnsListPaged.previous = pList.HasPreviousPage;
                    qnsListPaged.questions = pList;
            }
            returnResponse = Ok(ReturnResponse.GetSuccessStatus(qnsListPaged));
            
            return returnResponse;
        }


        /// <summary>
        /// Get details of a question
        /// </summary>
        /// <param name="language"></param>
        /// <param name="question_id"></param>
        /// <returns></returns>
        [HttpGet("{language}/Questions/{question_id}")]
        [Authorize(Roles = "Admin")]
        public IActionResult GetQuestions(string language, int question_id)
        {
            IActionResult returnResponse;

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            QuestionViewModel question = _repository.GetQuestionById(base.InstituteId, -1, language_id, question_id);
            
            returnResponse = Ok(ReturnResponse.GetSuccessStatus(question));
            
            return returnResponse;
        }

        /// <summary>
        /// Add new question
        /// </summary>
        /// <param name="language"></param>
        /// <param name="newQuestion"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions")]
        [Authorize(Roles = "Admin")]
        public IActionResult AddQuestions(string language, [FromBody] QuestionAddModel newQuestion)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            CategoryViewModel subCategory = _repository.GetCategoryByID(base.InstituteId, language_id, newQuestion.topic_id);

            QuestionViewModel question = null;

            if ((!(ModelState.IsValid)) || subCategory == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.InvalidInput, responseMessage));
                return returnResponse;
            }
            else if (newQuestion.type == QuestionTypeCode.MCQ.ToString())
            {
                question = _repository.AddMultipleChoiceQuestion(base.InstituteId, language_id, user_id, newQuestion);
            }
            else if (newQuestion.type == QuestionTypeCode.MRQ.ToString())
            {
                question = _repository.AddMultipleResposeQuestion(base.InstituteId, language_id, user_id, newQuestion);
            }
            else if (newQuestion.type == QuestionTypeCode.TNF.ToString())
            {
                question = _repository.AddTrueFalseQuestion(base.InstituteId, language_id, user_id, newQuestion);
            }
            else if (newQuestion.type == QuestionTypeCode.SUB.ToString())
            {
                question = _repository.AddSubjectiveQuestion(base.InstituteId, language_id, user_id, newQuestion);
            }

            if (question == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.ObjectNotAdded, responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(question));
            }

            return returnResponse;
        }

        /// <summary>
        /// Add new question
        /// </summary>
        /// <param name="language"></param>
        /// <param name="newQuestion"></param>
        /// <returns></returns>
        [HttpPost("{language}/AddBulkQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult BulkAddQuestions(string language, [FromBody] QuestionBulkAddModel questionList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            if (questionList == null || questionList.questions == null) return null;

            List<QuestionViewModel> retQuestions = new List<QuestionViewModel>();

            foreach (QuestionAddModel qns in questionList.questions)
            {
                QuestionViewModel question;
                CategoryViewModel category = _repository.GetCategoryByID(base.InstituteId, language_id, qns.topic_id);

                if ((!(ModelState.IsValid)) || category == null)
                {
                    question = null;

                    //responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                    //returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
                else if (qns.type == QuestionTypeCode.MCQ.ToString())
                {
                    question = _repository.AddMultipleChoiceQuestion(base.InstituteId, language_id, user_id, qns);
                    if (question == null)
                    {
                        responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.Question);
                        returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                    }
                    else
                    {
                        retQuestions.Add(question);
                    }
                }
                else if (qns.type == QuestionTypeCode.MRQ.ToString())
                {
                    question = _repository.AddMultipleResposeQuestion(base.InstituteId, language_id, user_id, qns);
                    if (question == null)
                    {
                        responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.Question);
                        returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                    }
                    else
                    {
                        retQuestions.Add(question);
                    }
                }
                else if (qns.type == QuestionTypeCode.TNF.ToString())
                {
                    question = _repository.AddTrueFalseQuestion(base.InstituteId, language_id, user_id, qns);
                    if (question == null)
                    {
                        responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.Question);
                        returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                    }
                    else
                    {
                        retQuestions.Add(question);
                    }
                }
            }

            returnResponse = Ok(ReturnResponse.GetSuccessStatus(retQuestions));

            return returnResponse;
        }


        /// <summary>
        /// Add new question
        /// </summary>
        /// <param name="language"></param>
        /// <param name="newQuestion"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions/{question_id}/CloneQuestionLanguage")]
        [Authorize(Roles = "Admin")]
        public IActionResult CloneQuestionLanguage(string language, int question_id, [FromBody] QuestionCloneModel newQuestion)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            QuestionViewModel question = null;

            if ((!(ModelState.IsValid)))
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                return returnResponse;
            }
            else
            {
                question = _repository.CloneQuestion(base.InstituteId, language_id, question_id, user_id, newQuestion);
            }

            if (question == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.Institute);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(question));
            }

            return returnResponse;
        }

        /// <summary>
        /// <summary>
        /// Edit a question
        /// </summary>
        /// <param name="language"></param>
        /// <param name="question_id"></param>
        /// <param name="question"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions/{question_id}/Update")]
        [Authorize(Roles = "Admin")]
        public IActionResult UpdateQuestionOfTheInstitute(string language, int question_id, [FromBody] QuestionEditModel question)
        {
            IActionResult returnResponse = null;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            if (question_id != question.id)
            {
                responseMessage = _repository.GetMessageByCode(Message.IdMismatchBetweenBodyAndQueryString.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                return returnResponse;
            }

            string return_message = string.Empty;
            QuestionViewModel theQuestion = _repository.UpdateQuestion(base.InstituteId, language_id, user_id, question);
            if (theQuestion == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotUpdated.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(theQuestion));
            }
            return returnResponse;
        }

        /// <summary>
        /// Delete a question
        /// </summary>
        /// <param name="question_id"></param>
        /// <returns></returns>
        [HttpPost("Questions/{question_id}/Delete")]
        [Authorize(Roles = "Admin")]
        public IActionResult DeleteQuestionOfTheInstitute(int question_id)
        {
            IActionResult returnResponse = null;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);


            int returnResult = _repository.DeleteQuestion(base.InstituteId, user_id, -1, question_id);
            if (returnResult <= 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotDeleted.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectDeleteSuccessfully.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(responseMessage));
            }
            return returnResponse;
        }

        /// <summary>
        /// Delete question list
        /// </summary>
        /// <param name="language"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions/Delete")]
        [Authorize(Roles = "SuperAdmin,Admin")]
        public IActionResult DeleteQuestions(string language, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            int returnResult = _repository.DeleteQuestionsList(base.InstituteId, language_id, user_id, -1, questionIdList, out return_message);
            if (returnResult <= 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotDeleted.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectDeleteSuccessfully.ToString(), Constant.Question);
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(responseMessage));
            }
            return returnResponse;
        }

        /// <summary>
        /// Publish Questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions/Publish")]
        [Authorize(Roles = "Admin")]
        public IActionResult PublishQuestions(string language, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;


            if (questionIdList == null || questionIdList.IdList == null || questionIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                int recordsEffected = _repository.PublishQuestions(base.InstituteId, language_id, user_id, -1, questionIdList, out return_message);
                if (recordsEffected == 0)
                {
                    responseMessage = _repository.GetMessageByCode(Message.FailedToAttach.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
                else
                {
                    returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
                }
            }
            return returnResponse;
        }

        /// <summary>
        /// Attach Category To Questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="category_id"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("{language}/Categories/{category_id}/AttachQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult AttachCategoryToQuestions(string language, int category_id, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
              
            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            CategoryViewModel category = _repository.GetCategoryByID(base.InstituteId, language_id, category_id);

            if (questionIdList == null || questionIdList.IdList == null || questionIdList.IdList.Count == 0 || category == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }

            foreach (int question_id in questionIdList.IdList)
            {
                QuestionViewModel q;
                q = _repository.GetQuestionById(base.InstituteId, -1, language_id, question_id);
                if(q == null)
                {
                    responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
            }
            
            //TODO: check if works fine
            int recordsEffected = _repository.AttachCategoryToQuestions(category_id, questionIdList, out return_message);
            if (recordsEffected < 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.FailedToAttach.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
            }
            
            return returnResponse;
        }

        /// <summary>
        /// Detach Subcategory From Questions
        /// </summary>
        /// <param name="category_id"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("Categories/{category_id}/DetachQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult DetachCategoryFromQuestions(int category_id, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            if (questionIdList == null || questionIdList.IdList == null || questionIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                int recordsEffected = _repository.DetachCategoryFromQuestions(category_id, questionIdList, out return_message);
                if (recordsEffected < 0)
                {
                    responseMessage = _repository.GetMessageByCode(Message.FailedToDetach.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
                else
                {
                    returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
                }
            }
            return returnResponse;
        }

        /// <summary>
        /// Attach Tags To Questions
        /// </summary>
        /// <param name="tag_id"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("Tags/{tag_id}/AttachQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult AttachTagsToQuestions(int tag_id, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            if (questionIdList == null || questionIdList.IdList == null || questionIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                int recordsEffected = _repository.AttachTagToQuestions(tag_id, questionIdList, out return_message);
                if (recordsEffected == 0)
                {
                    responseMessage = _repository.GetMessageByCode(Message.FailedToAttach.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
                else
                {
                    returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
                }
            }
            return returnResponse;
        }

        /// <summary>
        /// Detach Tag From Questions
        /// </summary>
        /// <param name="tag_id"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("Tags/{tag_id}/DetachQuestions")]
        [Authorize(Roles = "Admin")]
        public IActionResult DetachTagFromQuestions(int tag_id, [FromBody] IntegerList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            if (questionIdList == null || questionIdList.IdList == null || questionIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                int recordsEffected = _repository.DetachTagFromQuestions(tag_id, questionIdList, out return_message);
                if (recordsEffected == 0)
                {
                    responseMessage = _repository.GetMessageByCode(Message.FailedToDetach.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
                else
                {
                    returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
                }
            }
            return returnResponse;
        }

        /// <summary>
        /// Attach Bookmark To Questions
        /// </summary>
        /// <param name="language"></param>
        /// <param name="questionIdList"></param>
        /// <returns></returns>
        [HttpPost("{language}/Questions/Bookmark")]
        [Authorize(Roles = "Admin")]
        public IActionResult BookmarkQuestions(string language, [FromBody] BookmarkList questionIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            int language_id = _repository.GetLanguageIdByCode(language);
            if (language_id <= 0) return null;

            if (questionIdList == null || questionIdList.IdList == null || questionIdList.isBookmark == null || questionIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }

            foreach (int question_id in questionIdList.IdList)
            {
                QuestionViewModel q;
                q = _repository.GetQuestionById(base.InstituteId, user_id, language_id, question_id);
                if (q == null)
                {
                    responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                    returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
                }
            }

            int recordsEffected = 0;
            if (questionIdList.isBookmark == true) recordsEffected = _repository.AttachBookmarkToQuestions(user_id, questionIdList, out return_message);
            else recordsEffected = _repository.DetachBookmarkFromQuestions(user_id, questionIdList, out return_message);

            if (recordsEffected == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.FailedToAttach.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message));
            }
            return returnResponse;
        }

        #endregion
        
    }
}
