using System;
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;
using SQLitePCL;

namespace OnlineAssessment.V1.Controllers
{
    [Authorize]
    [ApiVersion("1.0")]
    [Route("v{version:apiVersion}/[controller]")]
    public class UserGroupsController : BaseController<UserGroups, EFCoreUserGroupRepository>
    {
        EFCoreUserGroupRepository _repository;
        string responseMessage = string.Empty;
        public UserGroupsController(EFCoreUserGroupRepository repository) : base(repository)
        {
            _repository = repository;
        }

        /// <summary>
        /// Get list of all User Groups of a class
        /// </summary>
        /// <returns></returns>
        [HttpGet("Classes/{class_id}")]
        [Authorize(Roles = "Admin,Teacher")]
        public IActionResult GetAllUserGroupsOfTheClass(int class_id, [FromQuery] string sortBy, string sortOrder)
        {
            IActionResult returnResponse;

            //Check: class validity
            ClassViewModel cls = _repository.GetAnyClassById(base.InstituteId, class_id);
            if (cls == null || cls.isActive == false) 
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            
            List<UserGroupViewAllModel> iList = _repository.GetAllUserGroupsOfTheClass(base.InstituteId, class_id, sortBy, sortOrder);
            if (iList == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.NoData.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(iList));
            }
            return returnResponse;

        }

        /// <summary>
        /// Get list of all User Groups of the institute
        /// </summary>
        /// <returns></returns>
        [HttpGet("list")]
        [Authorize(Roles = "Admin,Teacher,Student")]
        public IActionResult GetAllUserGroups([FromQuery] string sortBy, string sortOrder)
        {
            IActionResult returnResponse;

            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            List<UserGroupViewAllModel> iList = _repository.GetAllUserGroups(base.InstituteId, user_id, sortBy, sortOrder);
            if (iList == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.NoData.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(iList));
            }
            return returnResponse;

        }


        /// <summary>
        /// Get the list of User Groups of a user
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Get()
        {
            IActionResult returnResponse;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            dynamic entity = _repository.GetUserGroupsByUserId(base.InstituteId, user_id);
            if (entity == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotFound.ToString(), Constant.UserGroup);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));

            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(entity));
            }
            return returnResponse;
        }


        /// <summary>
        /// Get the detail of a User Group
        /// </summary>
        /// <param name="user_group_id"></param>
        /// <returns></returns>
        [HttpGet("{user_group_id}")]
        [Authorize(Roles = "Admin,Teacher")]
        public IActionResult Get(int user_group_id)
        {
            IActionResult returnResponse;
            dynamic entity = _repository.GetUserGroupById(base.InstituteId, user_group_id);
            if (entity == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotFound.ToString(), Constant.UserGroup);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));

            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(entity));
            }
            return returnResponse;
        }

        /// <summary>
        /// Add a new User Group
        /// </summary>
        /// <param name="class_id"></param>
        /// <param name="usergroup"></param>
        /// <returns></returns>
        [HttpPost("Classes/{class_id}")]
        [Authorize(Roles = "Admin")]
        public IActionResult AddUserGroup(int class_id, [FromBody] UserGroupAddModel usergroup)
        {
            IActionResult returnResponse;

            //Check: class validity
            if (usergroup == null || class_id != usergroup.class_id)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }

            UserGroupViewModel newUserGrup = _repository.AddUserGroupOfTheClass(base.InstituteId, usergroup);

            if (newUserGrup.id > 0) //Successfully Added
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(newUserGrup));
            }
            else
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotAdded.ToString(), Constant.UserGroup);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            return returnResponse;
        }


        /// <summary>
        /// Update a new User Group
        /// </summary>
        ///<param name="user_group_id"></param>
        /// <param name="usergroup"></param>
        /// <returns></returns>
        [HttpPost("{user_group_id}/Update")]
        [Authorize(Roles = "Admin")]
        public IActionResult UpdateUserGroupOfTheInstitute(int user_group_id, [FromBody] UserGroupEditModel usergroup)
        {
            IActionResult returnResponse = null;

            UserGroupViewModel newUserGrup = _repository.UpdateUserGroupOfTheInstitute(base.InstituteId, user_group_id, usergroup);
            if (newUserGrup == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotUpdated.ToString(), Constant.UserGroup);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(newUserGrup));
            }
            return returnResponse;
        }


        /// <summary>
        /// Get users of user group
        /// </summary>
        /// <param name="user_group_id"></param>
        /// <returns></returns>
        [HttpGet("{user_group_id}/Users")]
        [Authorize(Roles = "Admin,Teacher")]
        public IActionResult GetUsersOfUserGroup(int user_group_id)
        {
            IActionResult returnResponse;
            dynamic entity = _repository.GetUserOfTheUserGroup(base.InstituteId, user_group_id);
            if (entity == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotFound.ToString(), Constant.Role);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(entity));
            }
            return returnResponse;
            //TODO: GetUsersOfUserGroup >>>>>>>>>>>>>>>>>>>>>>> Not Implemented Exception
            //return Ok(ReturnResponse.GetFailureStatus(new NotImplementedException().Message));
        }


        /// <summary>
        /// Get users of user group
        /// </summary>
        /// <param name="user_group_id"></param>
        /// <returns></returns>
        [HttpPost("{user_group_id}/Delete")]
        [Authorize(Roles = "Admin")]
        public IActionResult DeleteUserGroup(int user_group_id)
        {
            IActionResult returnResponse;
            int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity);

            dynamic entity = _repository.DeleteTheUserGroup(base.InstituteId, user_id, user_group_id);
            if (entity == null)
            {
                responseMessage = _repository.GetMessageByCode(Message.ObjectNotFound.ToString(), Constant.Role);
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                returnResponse = Ok(ReturnResponse.GetSuccessStatus(entity));
            }
            return returnResponse;
        }

        /// <summary>
        /// Attch users to the user group
        /// </summary>
        /// <param name="user_group_id"></param>
        /// <param name="userIdList"></param>
        /// <returns></returns>
        [HttpPost("{user_group_id}/AttachUsers")]
        [Authorize(Roles = "Admin")]
        public IActionResult AttachUsersToUserGroup(int user_group_id, [FromBody] UserIdList userIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            if (userIdList == null || userIdList.IdList == null || userIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }

            //TODO: check if works fine
            int recordsEffected = _repository.AttachUsersToUserGroup(base.InstituteId, user_group_id, userIdList, 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>
        /// Attch users to the user group
        /// </summary>
        /// <param name="user_group_id"></param>
        /// <param name="userIdList"></param>
        /// <returns></returns>
        [HttpPost("{user_group_id}/DetachUsers")]
        [Authorize(Roles = "Admin")]
        public IActionResult DetachUsersToUserGroup(int user_group_id, [FromBody] UserIdList userIdList)
        {
            IActionResult returnResponse = null;
            string return_message = string.Empty;
            if (userIdList == null || userIdList.IdList == null || userIdList.IdList.Count == 0)
            {
                responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString());
                returnResponse = Ok(ReturnResponse.GetFailureStatus(responseMessage));
            }
            else
            {
                int recordsEffected = _repository.DetachUsersToUserGroup(user_group_id, userIdList, 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;
        }




    }
}
