@namespace ZB.MOM.WW.Theme
@* Components/LoginCard.razor — static form-POST sign-in card.
   SECURITY NOTES:
   - ReturnUrl is echoed into a hidden field verbatim; the consuming app's POST handler
     MUST validate it is a local/relative URL before redirecting to prevent open-redirect.
   - This form is NOT auto-protected by Blazor antiforgery; the caller MUST pass an
     antiforgery token via ChildContent (e.g. <AntiforgeryToken />). *@
<div class="login-wrap rise">
    <section class="panel">
        <div class="login-body">
            @* The product token is wrapped in its own span so consumers can restyle
               it and tests can assert the product in isolation (kit issue #5). Set
               Heading to replace the whole heading copy (e.g. for localization). *@
            @if (!string.IsNullOrWhiteSpace(Heading))
            {
                <h1 class="login-title">@Heading</h1>
            }
            else
            {
                <h1 class="login-title"><span class="login-product">@Product</span> &mdash; sign in</h1>
            }
            <form method="post" action="@Action" data-enhance="false">
                @if (!string.IsNullOrEmpty(ReturnUrl))
                {
                    <input type="hidden" name="returnUrl" value="@ReturnUrl" />
                }
                @ChildContent  @* e.g. <AntiforgeryToken/> supplied by the app *@
                <div class="mb-3">
                    <label class="form-label" for="username">Username</label>
                    <input id="username" name="username" type="text"
                           class="form-control form-control-sm" autocomplete="username" />
                </div>
                <div class="mb-3">
                    <label class="form-label" for="password">Password</label>
                    <input id="password" name="password" type="password"
                           class="form-control form-control-sm" autocomplete="current-password" />
                </div>
                @if (!string.IsNullOrWhiteSpace(Error))
                {
                    <div class="panel notice login-error">@Error</div>
                }
                <button class="btn btn-primary w-100" type="submit">Sign in</button>
            </form>
        </div>
    </section>
</div>

@code {
    /// <summary>
    /// Product name shown in the card heading (rendered inside a
    /// <c>&lt;span class="login-product"&gt;</c>, followed by the &quot;&#8212; sign in&quot;
    /// suffix). Required. Ignored when <see cref="Heading"/> is set.
    /// </summary>
    [Parameter, EditorRequired] public string Product { get; set; } = string.Empty;

    /// <summary>
    /// Optional full heading override. When set (non-whitespace), it replaces the
    /// default <c>&lt;Product&gt; &#8212; sign in</c> heading entirely — use it to
    /// localize or fully customize the heading copy. When unset, the default heading
    /// (with <see cref="Product"/> in a <c>.login-product</c> span) is rendered.
    /// </summary>
    [Parameter] public string? Heading { get; set; }

    /// <summary>
    /// Form <c>action</c> URL the sign-in POST targets. Defaults to <c>/auth/login</c>.
    /// </summary>
    [Parameter] public string Action { get; set; } = "/auth/login";

    /// <summary>
    /// Optional URL to redirect to after a successful login. Echoed into a hidden
    /// <c>returnUrl</c> field. The consuming app's POST handler MUST validate this is
    /// a local/relative URL before redirecting — do not redirect to arbitrary values
    /// to prevent open-redirect vulnerabilities.
    /// </summary>
    [Parameter] public string? ReturnUrl { get; set; }

    /// <summary>
    /// Optional error message shown as a notice above the submit button (e.g. a failed login).
    /// </summary>
    [Parameter] public string? Error { get; set; }

    /// <summary>
    /// Content rendered inside the form, before the username/password fields.
    /// The caller MUST supply an antiforgery token here (e.g. <c>&lt;AntiforgeryToken /&gt;</c>)
    /// because this static POST form is not auto-protected by Blazor's antiforgery middleware.
    /// </summary>
    [Parameter] public RenderFragment? ChildContent { get; set; }
}
