using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using ZpcBulletinBoard.Models;

namespace ZpcBulletinBoard.Pages.User
{
    [IgnoreAntiforgeryToken(Order = 1005)]
    [AllowAnonymous]
    public class LoginModel : PageModel
    {
        private readonly UserManager<IdentityApplicationUser> _userManager;
        private readonly SignInManager<IdentityApplicationUser> _loginManager;
        private readonly RoleManager<IdentityApplicationRole> _roleManager;
        //private readonly ILogger<LogoutModel> _logger;

        public LoginModel(UserManager<IdentityApplicationUser> userManager, SignInManager<IdentityApplicationUser> loginManager, RoleManager<IdentityApplicationRole> roleManager)
        {
            _userManager = userManager;
            _loginManager = loginManager;
            _roleManager = roleManager;
            //_logger = logger;
        }

        [BindProperty]
        public InputModel Input { get; set; }

        public IActionResult OnGetToken()
        {
            return new ObjectResult(new {id = 0});
        }

        public IActionResult OnGet()
        {
            //IdentityApplicationUser identityApplicationUser = new IdentityApplicationUser
            //{
            //    Name = "Master",
            //    Surname = "Admin",
            //    UserName = "admin",
            //    NormalizedUserName = "admin",
            //    Email = "admin@domain.com",
            //    NormalizedEmail = "admin@domain.com",
            //    EmailConfirmed = true,
            //    DateCreated = DateTime.Now,
            //    DateValidUntil = DateTime.MaxValue,
            //    PhoneNumber = "123456789",
            //    PhoneNumberConfirmed = true,
            //    Active = true,
            //    IdCompanyFk = 1
            //};

            //IdentityResult identityResult = _userManager.CreateAsync(identityApplicationUser, "Master#Admin22!").Result;

            //if (identityResult.Succeeded)
            //{
            //    if (!_roleManager.RoleExistsAsync("TransportThingUser").Result)
            //    {
            //        IdentityApplicationRole normalUserRole = new IdentityApplicationRole
            //        {
            //            Name = "TransportThingUser",
            //            Description = "TransporThing uporabniki"
            //        };

            //        _roleManager.CreateAsync(normalUserRole).Wait();
            //    }

            //    if (!_roleManager.RoleExistsAsync("ProjecThingUser").Result)
            //    {
            //        IdentityApplicationRole normalUserRole = new IdentityApplicationRole
            //        {
            //            Name = "ProjecThingUser",
            //            Description = "ProjecThing uporabniki"
            //        };

            //        _roleManager.CreateAsync(normalUserRole).Wait();
            //    }

            //    if (!_roleManager.RoleExistsAsync("Administrator").Result)
            //    {
            //        IdentityApplicationRole normalUserRole = new IdentityApplicationRole
            //        {
            //            Name = "Administrator",
            //            Description = "Administratorji"
            //        };

            //        _roleManager.CreateAsync(normalUserRole).Wait();
            //    }

            //    _userManager.AddToRoleAsync(identityApplicationUser, "Administrator").Wait();

            //    //return RedirectToPage("/Administration/Users/Index");
            //}
            //else
            //{
            //    ModelState.AddModelError("", string.Join(",", identityResult.Errors.Select(x => x.Description)));
            //}

            return Page();
        }

        public async Task<IActionResult> OnPostAsync(string returnUrl)
        {
            returnUrl ??= Url.Content("~/");
            
            if (!ModelState.IsValid)
            {
                return Page();
            }

            if (ModelState.IsValid)
            {
                //TODO samo za DEV
                //var result = await _loginManager.PasswordSignInAsync(Input.UserName, Input.Password, Input.RememberLogin, false);
                var result = await _loginManager.PasswordSignInAsync("Admin", "*zpcBulletinBoard2024*", Input.RememberLogin, false);

                if (result.Succeeded)
                {
                    // to get current user info
                    //var user = await _userManager.FindByNameAsync(Input.UserName);

                    //var user = await _userManager.GetUserAsync(User);
                    //_logger.LogInformation($"Login: {user.Name} {user.Surname} - {user.Company.Title}");

                    return RedirectToPage("/Index");
                }
                
                if (result.IsLockedOut)
                {
                    //var user = await _userManager.GetUserAsync(User); //TODO: ?? verjetno ne bo delalo
                    //_logger.LogInformation($"LoginLocked: {user.Name} {user.Surname} - {user.Company.Title}");

                    ModelState.AddModelError("", "Uporabnik je zaklenjen!");
                }
                else
                {
                    //_logger.LogInformation($"LoginFail: {Input.UserName}");

                    ModelState.AddModelError("", "Nepravilna prijava!");
                }
            }

            return Page();
        }

        //public async Task<IActionResult> Login([FromBody] UserLoginRequest user)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        // check if the user with the same email exist
        //        var existingUser = await _userManager.FindByEmailAsync(user.Email);

        //        if (existingUser == null)
        //        {
        //            // We dont want to give to much information on why the request has failed for security reasons
        //            return BadRequest(new RegistrationResponse()
        //            {
        //                Result = false,
        //                Errors = new List<string>(){
        //                    "Invalid authentication request"
        //                }
        //            });
        //        }

        //        // Now we need to check if the user has inputed the right password
        //        var isCorrect = await _userManager.CheckPasswordAsync(existingUser, user.Password);

        //        if (isCorrect)
        //        {
        //            var jwtToken = GenerateJwtToken(existingUser);

        //            return Ok(new RegistrationResponse()
        //            {
        //                Result = true,
        //                Token = jwtToken
        //            });
        //        }
        //        else
        //        {
        //            // We dont want to give to much information on why the request has failed for security reasons
        //            return BadRequest(new RegistrationResponse()
        //            {
        //                Result = false,
        //                Errors = new List<string>(){
        //                    "Invalid authentication request"
        //                }
        //            });
        //        }
        //    }

        //    return BadRequest(new RegistrationResponse()
        //    {
        //        Result = false,
        //        Errors = new List<string>(){
        //            "Invalid payload"
        //        }
        //    });
        //}

        //private string GenerateJwtToken(IdentityUser user)
        //{
        //    // Now its ime to define the jwt token which will be responsible of creating our tokens
        //    var jwtTokenHandler = new JwtSecurityTokenHandler();

        //    // We get our secret from the appsettings
        //    var key = Encoding.ASCII.GetBytes(_jwtConfig.Secret);

        //    // we define our token descriptor
        //    // We need to utilise claims which are properties in our token which gives information about the token
        //    // which belong to the specific user who it belongs to
        //    // so it could contain their id, name, email the good part is that these information
        //    // are generated by our server and identity framework which is valid and trusted
        //    var tokenDescriptor = new SecurityTokenDescriptor
        //    {
        //        Subject = new ClaimsIdentity(new[]
        //        {
        //            new Claim("Id", user.Id),
        //            new Claim(JwtRegisteredClaimNames.Sub, user.Email),
        //            new Claim(JwtRegisteredClaimNames.Email, user.Email),
        //            // the JTI is used for our refresh token which we will be convering in the next video
        //            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        //        }),
        //        // the life span of the token needs to be shorter and utilise refresh token to keep the user signedin
        //        // but since this is a demo app we can extend it to fit our current need
        //        Expires = DateTime.UtcNow.AddHours(6),
        //        // here we are adding the encryption alogorithim information which will be used to decrypt our token
        //        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
        //    };

        //    var token = jwtTokenHandler.CreateToken(tokenDescriptor);

        //    var jwtToken = jwtTokenHandler.WriteToken(token);

        //    return jwtToken;
        //}

        //public async Task<IActionResult> OnPostTokenAsync(string userName, string password)
        //{
        //    var user = await _userManager.FindByNameAsync(userName);

        //    if (user != null)
        //    {
        //        var result = await _loginManager.UserManager.CheckPasswordAsync(user, password);

        //        if (result)
        //        {
        //            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("!Appli$cation#2021#!"));

        //            var claims = new []
        //            {
        //                new Claim(JwtRegisteredClaimNames.Name, user.Name),
        //                new Claim(JwtRegisteredClaimNames.Email, user.Email),
        //                new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds()}"), //TODO skrajšaj
        //                new Claim(JwtRegisteredClaimNames.Iss, "EveryThing"),
        //                new Claim(JwtRegisteredClaimNames.Aud, "Android"),
        //                new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
        //                new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
        //                new Claim(JwtRegisteredClaimNames.Jti, $"{Guid.NewGuid()}")
        //            };

        //            var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims));
        //            string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

        //            return new ObjectResult(jwtToken);
        //        }
        //    }

        //    return BadRequest();
        //}

        public class InputModel
        {
            [Required(ErrorMessage = "Polje uporabniško ime je obvezno")]
            [Display(Name = "Uporabniško ime")]
            public string UserName { get; set; }

            [Required(ErrorMessage = "Polje geslo je obvezno")]
            [DataType(DataType.Password)]
            [Display(Name = "Geslo")]
            public string Password { get; set; }

            public bool RememberLogin { get; set; }
        }
    }
}