@page "/login"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@using ZB.MOM.WW.OtOpcUa.Admin.Security
@inject IHttpContextAccessor Http
@inject ILdapAuthService LdapAuth
@inject NavigationManager Nav

<div class="row justify-content-center mt-5">
    <div class="col-md-5">
        <div class="card">
            <div class="card-body">
                <h4 class="mb-4">OtOpcUa Admin — sign in</h4>

                <EditForm Model="_input" OnValidSubmit="SignInAsync" FormName="login">
                    <div class="mb-3">
                        <label class="form-label">Username</label>
                        <InputText @bind-Value="_input.Username" class="form-control" autocomplete="username"/>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">Password</label>
                        <InputText type="password" @bind-Value="_input.Password" class="form-control" autocomplete="current-password"/>
                    </div>

                    @if (_error is not null) { <div class="alert alert-danger">@_error</div> }

                    <button class="btn btn-primary w-100" type="submit" disabled="@_busy">
                        @(_busy ? "Signing in…" : "Sign in")
                    </button>
                </EditForm>

                <hr/>
                <small class="text-muted">
                    LDAP bind against the configured directory. Dev defaults to GLAuth on
                    <code>localhost:3893</code>.
                </small>
            </div>
        </div>
    </div>
</div>

@code {
    private sealed class Input
    {
        public string Username { get; set; } = string.Empty;
        public string Password { get; set; } = string.Empty;
    }

    private Input _input = new();
    private string? _error;
    private bool _busy;

    private async Task SignInAsync()
    {
        _error = null;
        _busy = true;
        try
        {
            if (string.IsNullOrWhiteSpace(_input.Username) || string.IsNullOrWhiteSpace(_input.Password))
            {
                _error = "Username and password are required";
                return;
            }

            var result = await LdapAuth.AuthenticateAsync(_input.Username, _input.Password, CancellationToken.None);
            if (!result.Success)
            {
                _error = result.Error ?? "Sign-in failed";
                return;
            }

            if (result.Roles.Count == 0)
            {
                _error = "Sign-in succeeded but no Admin roles mapped for your LDAP groups. Contact your administrator.";
                return;
            }

            var ctx = Http.HttpContext
                ?? throw new InvalidOperationException("HttpContext unavailable at sign-in");

            var claims = new List<Claim>
            {
                new(ClaimTypes.Name, result.DisplayName ?? result.Username ?? _input.Username),
                new(ClaimTypes.NameIdentifier, _input.Username),
            };
            foreach (var role in result.Roles)
                claims.Add(new Claim(ClaimTypes.Role, role));
            foreach (var group in result.Groups)
                claims.Add(new Claim("ldap_group", group));

            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(identity));

            ctx.Response.Redirect("/");
        }
        finally { _busy = false; }
    }
}
