using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using AutoMapper;
using InventoryTraker.Web.Attributes;
using InventoryTraker.Web.Core;
using InventoryTraker.Web.Identity;
using InventoryTraker.Web.Models;
using Microsoft.AspNet.Identity;

namespace InventoryTraker.Web.Controllers
{
	[Authorize(Roles = ApplicationRoleManager.AdminRoleName)]
    public class UserController : ControllerBase
	{
	    private readonly ApplicationUserManager _userManager;
	    private readonly IMapper _mapper;

	    public UserController(ApplicationUserManager userManager, IMapper mapper)
	    {
		    _userManager = userManager;
		    _mapper = mapper;
	    }

	    public ActionResult Index()
		{
			return View();
		}

	    public JsonResult All()
	    {
			var users =
				from u in _userManager.Users.ToList()
				let ad = _userManager.GetRoles(u.Id).Contains(ApplicationRoleManager.AdminRoleName)
				orderby u.UserName
				select new UserViewModel
				{
					UserName = u.UserName,
					Email = u.Email,
					Administrator = ad
				};

			return BetterJson(users.ToList());
	    }
		
		[ActionLog]
		[HttpPost]
		public async Task<JsonResult> Create(UserEditForm form)
		{
			if (!ModelState.IsValid)
				return GetModelStateErrorListJson();

			var user = 
				new User
				{
					Email = form.Email,
					UserName = form.UserName,
				};

			var identityResult = await _userManager.CreateAsync(user, form.Password);

			if (!identityResult.Succeeded)
				return GetErrorListJson(identityResult.Errors.ToArray());

			user = _userManager.FindByEmail(form.Email);
			if (form.Administrator)
			{
				var result = _userManager.AddToRole(user.Id, ApplicationRoleManager.AdminRoleName);
				if (!result.Succeeded)
					return GetErrorListJson(result.Errors.ToArray());
			}

			var userViewModel = _mapper.Map<UserViewModel>(user);
			userViewModel.Administrator = _userManager.IsInRole(user.Id, ApplicationRoleManager.AdminRoleName);
			return BetterJson(userViewModel);
		}

		[ActionLog]
		[HttpPost]
		public async Task<JsonResult> Edit(UserEditForm form)
		{
			if (!ModelState.IsValid)
				return GetModelStateErrorListJson();

			var user = _userManager.FindByEmail(form.Email);

			user.UserName = form.UserName;
			user.Email = form.Email;

			if (!string.IsNullOrEmpty(form.Password))
			{
				var resetResult = await _userManager.ChangePasswordAsync(user, form.Password);
				if (!resetResult.Succeeded)
					return GetErrorListJson(resetResult.Errors.ToArray());
			}

			var rolesForUser = _userManager.GetRoles(user.Id);

			if (rolesForUser.Contains(ApplicationRoleManager.AdminRoleName) && !form.Administrator)
			{
				var currentUser = _userManager.FindById(User.Identity.GetUserId());
				if (currentUser == user)
					return GetErrorListJson("Cannot remove admin from yourself");

				var result = _userManager.RemoveFromRole(user.Id, ApplicationRoleManager.AdminRoleName);
				if (!result.Succeeded)
					return GetErrorListJson(result.Errors.ToArray());
			}
			else if (!rolesForUser.Contains(ApplicationRoleManager.AdminRoleName) && form.Administrator)
			{
				var result = _userManager.AddToRole(user.Id, ApplicationRoleManager.AdminRoleName);
				if (!result.Succeeded)
					return GetErrorListJson(result.Errors.ToArray());
			}

			var identityResult = _userManager.Update(user);

			if (!identityResult.Succeeded)
				return GetErrorListJson(identityResult.Errors.ToArray());

			var userViewModel = _mapper.Map<UserViewModel>(user);
			userViewModel.Administrator = _userManager.IsInRole(user.Id, ApplicationRoleManager.AdminRoleName);
			return BetterJson(userViewModel);
		}
	}
}