using ASP.Back.Libraries;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Build.Framework;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using TeamManiacs.Core.Enums;
using TeamManiacs.Core.Models;
using TeamManiacs.Data;

namespace ASP.Back.Controllers
{  
    [Route("api/[controller]")]
    [ApiController]
    public class PwdMgmtController : ControllerBase
    {
        private readonly TeamManiacsDbContext _context;
        private static Emailer? _emailer;
        private static PasswordManagement? passwordManagement;
        public PwdMgmtController(TeamManiacsDbContext context, IWebHostEnvironment hostEnvironment, Emailer emailer)
        {
            _context = context;
            _emailer = emailer;
            passwordManagement = new PasswordManagement(hostEnvironment);
        }


        // PUT api/<ValuesController>/
        [HttpPut]
        public async Task<IActionResult> Put([FromBody] NewPwd newPwd)
        {
            Users? user = null;
            string message = "";
            if (passwordManagement == null)
            {
                return BadRequest();
            }
            //Validate code
            if(newPwd.OldPassword == null)
            {
                AuthCode? ourCode = _context.AuthCodes.FirstOrDefault(x => x.Uid == newPwd.AuthCode.Uid && x.Type == CodeType.PwdReset);
                if (ourCode == null)
                {
                    return NotFound();
                }
                if (ourCode.Code != newPwd.AuthCode.Code)
                {
                    return BadRequest();
                }
                await Delete(ourCode);
                user = await _context.UserModels.FindAsync(newPwd.AuthCode.Uid);
                message = "No User Found";


            }
            else
            {
                user = passwordManagement.Authenticate(_context, new Login(newPwd.AuthCode.Uid, newPwd.OldPassword));
                message = "Failed to authenticate user";

            }

            if (user == null)
            {
                return StatusCode(400, new { Message = message });
            }
            user.Password = passwordManagement.EncryptPassword(newPwd.NewPassword);
            _context.Entry(user).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return StatusCode(200, new { Message = "Password Changed Successfully, Please Relogin" });
        }
        // PUT api/<ValuesController>/
        [HttpPut("frgot/")]
        public async Task<IActionResult> Put([FromBody] PwdResetForm pwdReset)
        {
            //I should make sure we have an email also submitted here to prevent spamming. 
            if (_emailer == null)
            {
                return BadRequest();
            }
            //Generate a new code, if user is inactive, code will not be generated. 
            Users? user = _context.UserModels.FirstOrDefault(x =>
                                                       x.Email.ToLower() == pwdReset.Email.ToLower());

            if (user == null)
            {
                return NotFound();
            }

            if (user.Status == TeamManiacs.Core.Enums.UserStatus.inactive)
            {
                return BadRequest();
            }

            //Make sure we don't already have an existing code...

            AuthCode? ourCode = _context.AuthCodes.FirstOrDefault(x => x.Uid == user.UserId && x.Type == CodeType.PwdReset);
          
            //if we do Delete it!
            if (ourCode != null)
            {
                await Delete(ourCode);
            }

            //Generate code
            AuthCode authCode = ControllerHelpers.GenerateAuthCode(user.UserId);
            authCode.Type = CodeType.PwdReset;
            if (authCode == null)
            {
                return BadRequest();
            }

            await _context.AuthCodes.AddAsync(authCode);

            await _context.SaveChangesAsync();

            //We've got all our authentication methods created and added to the DB.
            //Lets send an email to the user so they can reset their password.
            _emailer.SendResetPasswordLink(pwdReset.Email, authCode.Code, user.UserId.ToString());

            return StatusCode(200, new { Message = "Good Code" });
        }

        private async Task<int> Delete(AuthCode usersCode)
        {
            _context.AuthCodes.Remove(usersCode);

            return await _context.SaveChangesAsync();
        }
    }

}
