@namespace Oqtane.Modules.Admin.Login
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IUserService UserService
@inject IServiceProvider ServiceProvider
@inject IStringLocalizer<Index> Localizer

@if (_message != string.Empty)
{
    <ModuleMessage Message="@_message" Type="@_type" />
}
<AuthorizeView>
    <NotAuthorized>
        <form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
            <div class="container Oqtane-Modules-Admin-Login" @onkeypress="@(e => KeyPressed(e))">
                <div class="form-group">
                    <label for="Username" class="control-label">@Localizer["Username:"] </label>
                    <input type="text" @ref="username" name="Username" class="form-control username" placeholder="Username" @bind="@_username" id="Username" required />
                </div>
                <div class="form-group">
                    <label for="Password" class="control-label">@Localizer["Password:"] </label>
                    <input type="password" name="Password" class="form-control password" placeholder="Password" @bind="@_password" id="Password" required />
                </div>
                <div class="form-group">
                    <div class="form-check form-check-inline">
                        <label class="form-check-label" for="Remember">@Localizer["Remember Me?"]</label>&nbsp;
                        <input type="checkbox" class="form-check-input" name="Remember" @bind="@_remember" id="Remember" />
                    </div>
                </div>
                <button type="button" class="btn btn-primary" @onclick="Login">@Localizer["Login"]</button>
                <button type="button" class="btn btn-secondary" @onclick="Cancel">@Localizer["Cancel"]</button>
                <br /><br />
                <button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["Forgot Password"]</button>
            </div>
        </form>
    </NotAuthorized>
</AuthorizeView>

@code {
    private string _returnUrl = string.Empty;
    private string _message = string.Empty;
    private MessageType _type = MessageType.Info;
    private string _username = string.Empty;
    private string _password = string.Empty;
    private bool _remember = false;
    private bool validated = false;

    private ElementReference login;
    private ElementReference username;

    public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;

    public override List<Resource> Resources => new List<Resource>()
    {
        new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
    };

    protected override async Task OnInitializedAsync()
    {
        if (PageState.QueryString.ContainsKey("returnurl"))
        {
            _returnUrl = PageState.QueryString["returnurl"];
        }

        if (PageState.QueryString.ContainsKey("name"))
        {
            _username = PageState.QueryString["name"];
        }

        if (PageState.QueryString.ContainsKey("token"))
        {
            var user = new User();
            user.SiteId = PageState.Site.SiteId;
            user.Username = _username;
            user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);

            if (user != null)
            {
                _message = Localizer["User Account Verified Successfully. You Can Now Login With Your Username And Password Below."];
            }
            else
            {
                _message = Localizer["User Account Could Not Be Verified. Please Contact Your Administrator For Further Instructions."];
                _type = MessageType.Warning;
            }
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await username.FocusAsync();
        }
    }

    private async Task Login()
    {
        validated = true;
        var interop = new Interop(JSRuntime);
        if (await interop.FormValid(login))
        {
            if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
            {
                // server-side Blazor
                var user = new User();
                user.SiteId = PageState.Site.SiteId;
                user.Username = _username;
                user.Password = _password;
                user = await UserService.LoginUserAsync(user, false, false);

                if (user.IsAuthenticated)
                {
                    await logger.LogInformation("Login Successful For Username {Username}", _username);
                    // complete the login on the server so that the cookies are set correctly on SignalR
                    string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
                    var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
                    await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
                }
                else
                {
                    await logger.LogInformation("Login Failed For Username {Username}", _username);
                    AddModuleMessage(Localizer["Login Failed. Please Remember That Passwords Are Case Sensitive And User Accounts Require Verification When They Are Initially Created So You May Wish To Check Your Email."], MessageType.Error);
                }
            }
            else
            {
                // client-side Blazor
                var user = new User();
                user.SiteId = PageState.Site.SiteId;
                user.Username = _username;
                user.Password = _password;
                user = await UserService.LoginUserAsync(user, true, _remember);
                if (user.IsAuthenticated)
                {
                    await logger.LogInformation("Login Successful For Username {Username}", _username);
                    var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
                    authstateprovider.NotifyAuthenticationChanged();
                    NavigationManager.NavigateTo(NavigateUrl(_returnUrl, "reload"));
                }
                else
                {
                    await logger.LogInformation("Login Failed For Username {Username}", _username);
                    AddModuleMessage(Localizer["Login Failed. Please Remember That Passwords Are Case Sensitive And User Accounts Require Verification When They Are Initially Created So You May Wish To Check Your Email."], MessageType.Error);
                }
            }
        }
        else
        {
            AddModuleMessage(Localizer["Please Provide Your Username And Password"], MessageType.Warning);
        }
    }

    private void Cancel()
    {
        NavigationManager.NavigateTo(_returnUrl);
    }

    private async Task Forgot()
    {
        if (_username != string.Empty)
        {
            var user = await UserService.GetUserAsync(_username, PageState.Site.SiteId);
            if (user != null)
            {
                await UserService.ForgotPasswordAsync(user);
                _message = "Please Check The Email Address Associated To Your User Account For A Password Reset Notification";
            }
            else
            {
                _message = "User Does Not Exist";
                _type = MessageType.Warning;
            }
        }
        else
        {
            _message = "Please Enter The Username Related To Your Account And Then Select The Forgot Password Option Again";
        }

        StateHasChanged();
    }

    private async Task KeyPressed(KeyboardEventArgs e)
    {
        if (e.Code == "Enter" || e.Code == "NumpadEnter")
        {
            await Login();
        }
    }
}
