using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;

namespace Radzen.Blazor
{
    /// <summary>
    /// A pre-built login form component with username/password fields and optional "Remember Me", "Register", and "Reset Password" features.
    /// RadzenLogin provides a ready-to-use authentication UI that can be customized with events for login, registration, and password reset flows.
    /// Must be placed inside a <see cref="RadzenTemplateForm{TItem}"/>.
    /// Eliminates the need to manually create login forms by providing a complete, styled login interface.
    /// Features pre-configured text and password inputs, optional switch for persistent sessions (Remember Me), optional link to registration page/modal,
    /// optional link for password recovery (Reset Password), browser password manager integration with autocomplete, customizable labels/button text/layout via parameters,
    /// Login/Register/ResetPassword event callbacks for implementing auth logic, and built-in required field validation.
    /// Handle the Login event to authenticate users with your backend. Use AllowRegister and AllowResetPassword to show/hide those links based on your auth requirements.
    /// </summary>
    /// <example>
    /// Basic login form:
    /// <code>
    /// &lt;RadzenTemplateForm Data=@("Login")&gt;
    ///     &lt;RadzenLogin Login=@OnLogin /&gt;
    /// &lt;/RadzenTemplateForm&gt;
    /// @code {
    ///     async Task OnLogin(LoginArgs args)
    ///     {
    ///         // Authenticate with backend
    ///         var result = await authService.Login(args.Username, args.Password);
    ///         if (result.Success)
    ///             NavigationManager.NavigateTo("/dashboard");
    ///     }
    /// }
    /// </code>
    /// Full-featured login with all options:
    /// <code>
    /// &lt;RadzenTemplateForm Data=@("Login")&gt;
    ///     &lt;RadzenLogin AllowRegister="true" AllowResetPassword="true"
    ///                  Login=@OnLogin Register=@OnRegister ResetPassword=@OnResetPassword
    ///                  UserText="Email" RememberMe="true" /&gt;
    /// &lt;/RadzenTemplateForm&gt;
    /// </code>
    /// </example>
    public partial class RadzenLogin : RadzenComponent
    {
        /// <summary>
        /// Gets or sets a value indicating whether automatic complete of inputs is enabled.
        /// </summary>
        /// <value><c>true</c> if automatic complete of inputs is enabled; otherwise, <c>false</c>.</value>
        [Parameter]
        public bool AutoComplete { get; set; } = true;

        /// <summary>
        /// Gets or sets a value indicating the type of built-in autocomplete
        /// the browser should use.
        /// <see cref="Blazor.AutoCompleteType" />
        /// </summary>
        /// <value>
        /// The type of built-in autocomplete.
        /// </value>
        [Parameter]
        public AutoCompleteType UserNameAutoCompleteType { get; set; } = AutoCompleteType.Username;

        /// <summary>
        /// Gets or sets a value indicating the type of built-in autocomplete
        /// the browser should use.
        /// <see cref="Blazor.AutoCompleteType" />
        /// </summary>
        /// <value>
        /// The type of built-in autocomplete.
        /// </value>
        [Parameter]
        public AutoCompleteType PasswordAutoCompleteType { get; set; } = AutoCompleteType.CurrentPassword;

        /// <summary>
        /// Gets or sets the design variant of the form field.
        /// </summary>
        /// <value>The variant of the form field.</value>
        [Parameter]
        public Variant? FormFieldVariant { get; set; }

        /// <inheritdoc />
        protected override string GetComponentCssClass()
        {
            return "rz-login";
        }

        string? username;
        /// <summary>
        /// Gets or sets the username.
        /// </summary>
        /// <value>The username.</value>
        [Parameter]
        public string? Username { get; set; }

        string? password;
        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>The password.</value>
        [Parameter]
        public string? Password { get; set; }

        private bool rememberMe;
        /// <summary> Sets the initial value of the remember me switch.</summary>
        [Parameter]
        public bool RememberMe { get; set; }

        /// <summary>
        /// Gets or sets the login callback.
        /// </summary>
        /// <value>The login callback.</value>
        [Parameter]
        public EventCallback<LoginArgs> Login { get; set; }

        /// <summary>
        /// Gets or sets the register callback.
        /// </summary>
        /// <value>The register callback.</value>
        [Parameter]
        public EventCallback Register { get; set; }

        /// <summary>
        /// Gets or sets the reset password callback.
        /// </summary>
        /// <value>The reset password callback.</value>
        [Parameter]
        public EventCallback<string> ResetPassword { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether register is allowed.
        /// </summary>
        /// <value><c>true</c> if register is allowed; otherwise, <c>false</c>.</value>
        [Parameter]
        public bool AllowRegister { get; set; } = true;

        /// <summary>
        /// Asks the user whether to remember their credentials. Set to <c>false</c> by default.
        /// </summary>
        [Parameter]
        public bool AllowRememberMe { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether reset password is allowed.
        /// </summary>
        /// <value><c>true</c> if reset password is allowed; otherwise, <c>false</c>.</value>
        [Parameter]
        public bool AllowResetPassword { get; set; } = true;

        /// <summary>
        /// Gets or sets a value indicating whether default login button is shown.
        /// </summary>
        /// <value><c>true</c> if default login button is shown; otherwise, <c>false</c>.</value>
        [Parameter]
        public bool ShowLoginButton { get; set; } = true;

        private string? loginText;

        /// <summary>
        /// Gets or sets the login text.
        /// </summary>
        /// <value>The login text.</value>
        [Parameter]
        public string LoginText { get => loginText ?? Localize(nameof(RadzenStrings.Login_LoginText)); set => loginText = value; }

        private string? registerText;

        /// <summary>
        /// Gets or sets the register text.
        /// </summary>
        /// <value>The register text.</value>
        [Parameter]
        public string RegisterText { get => registerText ?? Localize(nameof(RadzenStrings.Login_RegisterText)); set => registerText = value; }

        private string? rememberMeText;

        /// <summary> Gets or sets the remember me text.</summary>
        [Parameter]
        public string RememberMeText { get => rememberMeText ?? Localize(nameof(RadzenStrings.Login_RememberMeText)); set => rememberMeText = value; }

        private string? registerMessageText;

        /// <summary>
        /// Gets or sets the register message text.
        /// </summary>
        /// <value>The register message text.</value>
        [Parameter]
        public string RegisterMessageText { get => registerMessageText ?? Localize(nameof(RadzenStrings.Login_RegisterMessageText)); set => registerMessageText = value; }

        private string? resetPasswordText;

        /// <summary>
        /// Gets or sets the reset password text.
        /// </summary>
        /// <value>The reset password text.</value>
        [Parameter]
        public string ResetPasswordText { get => resetPasswordText ?? Localize(nameof(RadzenStrings.Login_ResetPasswordText)); set => resetPasswordText = value; }

        private string? userText;

        /// <summary>
        /// Gets or sets the user text.
        /// </summary>
        /// <value>The user text.</value>
        [Parameter]
        public string UserText { get => userText ?? Localize(nameof(RadzenStrings.Login_UserText)); set => userText = value; }

        private string? userRequired;

        /// <summary>
        /// Gets or sets the user required text.
        /// </summary>
        /// <value>The user required text.</value>
        [Parameter]
        public string UserRequired { get => userRequired ?? Localize(nameof(RadzenStrings.Login_UserRequired)); set => userRequired = value; }

        private string? passwordText;

        /// <summary>
        /// Gets or sets the password text.
        /// </summary>
        /// <value>The password text.</value>
        [Parameter]
        public string PasswordText { get => passwordText ?? Localize(nameof(RadzenStrings.Login_PasswordText)); set => passwordText = value; }

        private string? passwordRequired;

        /// <summary>
        /// Gets or sets the password required.
        /// </summary>
        /// <value>The password required.</value>
        [Parameter]
        public string PasswordRequired { get => passwordRequired ?? Localize(nameof(RadzenStrings.Login_PasswordRequired)); set => passwordRequired = value; }

        /// <summary>
        /// Called when login.
        /// </summary>
        protected async Task OnLogin()
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                await Login.InvokeAsync(new LoginArgs { Username = username, Password = password, RememberMe = rememberMe });
            }
        }

        private string Id(string name)
        {
            return $"{GetId()}-{name}";
        }

        /// <inheritdoc />
        protected override void OnInitialized()
        {
            username = Username;
            password = Password;
            rememberMe = RememberMe;
            base.OnInitialized();
        }

        /// <inheritdoc />
        public override async Task SetParametersAsync(ParameterView parameters)
        {
            if (parameters.DidParameterChange(nameof(Username), Username))
            {
                username = parameters.GetValueOrDefault<string>(nameof(Username));
            }

            if (parameters.DidParameterChange(nameof(Password), Password))
            {
                password = parameters.GetValueOrDefault<string>(nameof(Password));
            }

            if (parameters.DidParameterChange(nameof(RememberMe), RememberMe))
            {
                rememberMe = parameters.GetValueOrDefault<bool>(nameof(RememberMe));
            }

            await base.SetParametersAsync(parameters);
        }

        /// <summary>
        /// Handles the reset event.
        /// </summary>
        /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected async Task OnReset(EventArgs args)
        {
            await ResetPassword.InvokeAsync(username);
        }

        /// <summary>
        /// Called when register.
        /// </summary>
        protected async Task OnRegister()
        {
            await Register.InvokeAsync(EventArgs.Empty);
        }
    }
}
