namespace ZB.MOM.WW.MxGateway.Server.Configuration;

public sealed class DashboardOptions
{
    /// <summary>Gets whether the dashboard is enabled.</summary>
    public bool Enabled { get; init; } = true;

    /// <summary>Gets whether anonymous localhost access to dashboard is allowed.</summary>
    public bool AllowAnonymousLocalhost { get; init; } = true;

    /// <summary>
    /// DEV/TEST ONLY. When true, the dashboard bypasses the login form entirely and
    /// auto-authenticates EVERY request as <see cref="AutoLoginUser"/> holding both
    /// dashboard roles (Administrator + Viewer). No cookie, no LDAP bind. Default false.
    /// Unlike <see cref="AllowAnonymousLocalhost"/> (which only succeeds the authorization
    /// requirement without authenticating), this mints a real principal, so the UI behaves
    /// as a signed-in admin and applies to all clients (not just loopback). Never enable in
    /// production. See docs/plans/2026-06-16-dashboard-disable-login-design.md.
    /// </summary>
    public bool DisableLogin { get; init; }

    /// <summary>
    /// Username minted for the auto-login principal when <see cref="DisableLogin"/> is true.
    /// Null/blank falls back to the GLAuth Administrator test user <c>multi-role</c>.
    /// </summary>
    public string? AutoLoginUser { get; init; }

    /// <summary>
    /// When true (default), the dashboard auth cookie is restricted to HTTPS
    /// requests via <see cref="Microsoft.AspNetCore.Http.CookieSecurePolicy.Always"/>.
    /// Set to false for plain-HTTP dev deployments — the cookie then uses
    /// <see cref="Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest"/>,
    /// which still marks it Secure on any HTTPS request but allows it to
    /// round-trip over HTTP. Browsers silently drop Secure cookies set over
    /// plain HTTP from non-localhost hosts, so leaving this true breaks
    /// dashboard login from a remote browser unless the dashboard is served
    /// over HTTPS.
    /// </summary>
    public bool RequireHttpsCookie { get; init; } = true;

    /// <summary>
    /// Dashboard auth cookie name. When null/blank (the default) the canonical
    /// <see cref="ZB.MOM.WW.MxGateway.Server.Dashboard.DashboardAuthenticationDefaults.CookieName"/>
    /// is used. Override it (<c>MxGateway:Dashboard:CookieName</c>) to give a distinct name to a
    /// gateway that shares a hostname with another gateway instance — browser cookies are scoped
    /// by host+path but NOT by port, so two instances on the same host would otherwise clobber
    /// each other's dashboard session under a shared cookie name. Changing this signs out
    /// existing dashboard sessions on next deploy.
    /// </summary>
    public string? CookieName { get; init; }

    /// <summary>Gets the dashboard snapshot update interval in milliseconds.</summary>
    public int SnapshotIntervalMilliseconds { get; init; } = 1_000;

    /// <summary>Gets the maximum number of recent faults to display.</summary>
    public int RecentFaultLimit { get; init; } = 100;

    /// <summary>Gets the maximum number of recent sessions to display.</summary>
    public int RecentSessionLimit { get; init; } = 200;

    /// <summary>Gets whether to show full tag values in the dashboard.</summary>
    public bool ShowTagValues { get; init; }

    /// <summary>
    /// LDAP group → dashboard role mapping. Values must be one of
    /// <see cref="DashboardRoles.Admin"/> or <see cref="DashboardRoles.Viewer"/>.
    /// Users with no matching group are rejected at login.
    /// </summary>
    public Dictionary<string, string> GroupToRole { get; init; } = new(StringComparer.OrdinalIgnoreCase);

    /// <summary>
    /// LDAP group → dashboard visibility tags. A dashboard user's granted tag set
    /// is the union over the groups they belong to; a session is observable on the
    /// events hub when its tags intersect that grant. Independent of
    /// <see cref="GroupToRole"/> — a group may appear in either map, both, or
    /// neither. Visibility only: tags never gate data access.
    /// </summary>
    public Dictionary<string, string[]> GroupToTag { get; init; } = new(StringComparer.OrdinalIgnoreCase);

    /// <summary>
    /// Who may observe a session whose owning API key carries no dashboard tags.
    /// Defaults to <see cref="Configuration.UntaggedSessionVisibility.AdminOnly"/>
    /// so an upgrade tightens rather than loosens.
    /// </summary>
    public UntaggedSessionVisibility UntaggedSessionVisibility { get; init; } = UntaggedSessionVisibility.AdminOnly;
}
