@using EntKube.Web.Data
@using EntKube.Web.Services
@inject KeycloakService KeycloakService
@inject StorageService StorageService
@inject ComponentLifecycleService LifecycleService

@if (loading)
{
    <div class="text-center py-5">
        <div class="spinner-border text-primary" role="status"></div>
        <p class="text-muted mt-2">Scanning for Keycloak instances...</p>
    </div>
}
else if (selectedRealm is not null && selectedKeycloak is not null)
{
    @* ── Level 3: Realm detail ── *@
    <nav class="mb-3">
        <button class="btn btn-sm btn-link text-decoration-none p-0" @onclick="BackToRealms">
            <i class="bi bi-arrow-left me-1"></i>Back to Realms
        </button>
    </nav>

    <div class="d-flex align-items-center justify-content-between mb-3">
        <div class="d-flex align-items-center gap-2">
            <i class="bi bi-shield-lock fs-4 text-primary"></i>
            <div>
                <h5 class="mb-0">@selectedRealm.DisplayName</h5>
                <small class="text-muted font-monospace">@selectedRealm.RealmName</small>
            </div>
        </div>
        @if (selectedRealm.LinkedApp is not null)
        {
            <span class="badge bg-primary-subtle text-primary border border-primary-subtle small">
                <i class="bi bi-link-45deg me-1"></i>@selectedRealm.LinkedApp.Customer.Name / @selectedRealm.LinkedApp.Name
            </span>
        }
    </div>

    <ul class="nav nav-tabs mb-3 flex-wrap">
        @foreach (string tab in new[] { "users", "idp", "groups", "orgs", "themes", "backup", "portal" })
        {
            string label = tab switch
            {
                "users" => "Users",
                "idp" => "Identity Providers",
                "groups" => "Groups",
                "orgs" => "Organizations",
                "themes" => "Themes",
                "backup" => "Backup & Restore",
                "portal" => "Customer Portal",
                _ => tab
            };
            <li class="nav-item">
                <button class="nav-link @(realmTab == tab ? "active" : "")"
                        @onclick="() => SwitchRealmTab(tab)">@label</button>
            </li>
        }
    </ul>

    @* ── Users ── *@
    @if (realmTab == "users")
    {
        @if (loadingUsers)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            <div class="d-flex justify-content-between align-items-center mb-3">
                <span class="text-muted small">@(users?.Count ?? 0) users</span>
                <button class="btn btn-sm btn-primary" @onclick="() => showAddUser = !showAddUser">
                    <i class="bi bi-person-plus me-1"></i>Add User
                </button>
            </div>

            @if (showAddUser)
            {
                <div class="card mb-3 border-primary-subtle">
                    <div class="card-body">
                        @if (userError is not null)
                        {
                            <div class="alert alert-danger py-2 small">@userError</div>
                        }
                        <div class="row g-2">
                            <div class="col-md-4">
                                <input class="form-control form-control-sm" placeholder="Username" @bind="newUserUsername" />
                            </div>
                            <div class="col-md-4">
                                <input class="form-control form-control-sm" placeholder="Email" @bind="newUserEmail" />
                            </div>
                            <div class="col-md-2">
                                <input class="form-control form-control-sm" placeholder="First name" @bind="newUserFirstName" />
                            </div>
                            <div class="col-md-2">
                                <input class="form-control form-control-sm" placeholder="Last name" @bind="newUserLastName" />
                            </div>
                            <div class="col-md-4">
                                <input type="password" class="form-control form-control-sm" placeholder="Password (optional)" @bind="newUserPassword" />
                            </div>
                        </div>
                        <div class="mt-2 d-flex gap-2">
                            <button class="btn btn-sm btn-primary" @onclick="AddUser" disabled="@savingUser">
                                @if (savingUser) { <span class="spinner-border spinner-border-sm me-1"></span> }
                                Create
                            </button>
                            <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddUser = false">Cancel</button>
                        </div>
                    </div>
                </div>
            }

            @if (users is not null)
            {
                <div class="list-group">
                    @foreach (KeycloakUserInfo user in users)
                    {
                        <div class="list-group-item py-2">
                            <div class="d-flex justify-content-between align-items-start">
                                <div>
                                    <strong>@user.Username</strong>
                                    <span class="text-muted small ms-2">@user.Email</span>
                                    @if (!user.Enabled)
                                    {
                                        <span class="badge bg-secondary-subtle text-secondary ms-1 small">Disabled</span>
                                    }
                                    @if (!user.EmailVerified)
                                    {
                                        <span class="badge bg-warning-subtle text-warning ms-1 small">Unverified</span>
                                    }
                                    @if (user.Attributes.Count > 0)
                                    {
                                        <div class="mt-1 d-flex flex-wrap gap-1">
                                            @foreach (KeyValuePair<string, List<string>> attr in user.Attributes)
                                            {
                                                <span class="badge bg-light text-secondary border font-monospace"
                                                      style="font-size:0.7rem">
                                                    @attr.Key: @string.Join(", ", attr.Value)
                                                </span>
                                            }
                                        </div>
                                    }
                                </div>
                                <button class="btn btn-sm btn-outline-danger border-0 ms-2"
                                        @onclick="() => DeleteUser(user.Id)">
                                    <i class="bi bi-trash"></i>
                                </button>
                            </div>
                        </div>
                    }
                </div>
            }
        }
    }

    @* ── Identity Providers ── *@
    @if (realmTab == "idp")
    {
        @if (loadingIdps)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            <div class="d-flex justify-content-between align-items-center mb-3">
                <span class="text-muted small">@(idps?.Count ?? 0) providers</span>
                <button class="btn btn-sm btn-primary" @onclick="() => showAddIdp = !showAddIdp">
                    <i class="bi bi-plus-circle me-1"></i>Add Provider
                </button>
            </div>

            @if (showAddIdp)
            {
                <div class="card mb-3 border-primary-subtle">
                    <div class="card-body">
                        @if (idpError is not null)
                        {
                            <div class="alert alert-danger py-2 small">@idpError</div>
                        }
                        <div class="row g-2">
                            <div class="col-md-3">
                                <input class="form-control form-control-sm" placeholder="Alias (e.g. google)" @bind="newIdpAlias" />
                            </div>
                            <div class="col-md-3">
                                <select class="form-select form-select-sm" @bind="newIdpProviderId">
                                    <option value="oidc">OpenID Connect</option>
                                    <option value="saml">SAML</option>
                                    <option value="google">Google</option>
                                    <option value="github">GitHub</option>
                                    <option value="microsoft">Microsoft</option>
                                </select>
                            </div>
                            <div class="col-md-3">
                                <input class="form-control form-control-sm" placeholder="Client ID" @bind="newIdpClientId" />
                            </div>
                            <div class="col-md-3">
                                <input type="password" class="form-control form-control-sm" placeholder="Client Secret" @bind="newIdpClientSecret" />
                            </div>
                        </div>
                        <div class="mt-2 d-flex gap-2">
                            <button class="btn btn-sm btn-primary" @onclick="AddIdp" disabled="@savingIdp">
                                @if (savingIdp) { <span class="spinner-border spinner-border-sm me-1"></span> }
                                Add
                            </button>
                            <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddIdp = false">Cancel</button>
                        </div>
                    </div>
                </div>
            }

            @if (idps is not null)
            {
                <div class="list-group">
                    @foreach (KeycloakIdpInfo idp in idps)
                    {
                        <div class="list-group-item d-flex justify-content-between align-items-center py-2">
                            <div>
                                <i class="bi bi-box-arrow-in-right me-2 text-muted"></i>
                                <strong>@idp.Alias</strong>
                                <span class="badge bg-secondary-subtle text-secondary ms-2 small">@idp.ProviderId</span>
                                @if (!idp.Enabled)
                                {
                                    <span class="badge bg-secondary-subtle text-secondary ms-1 small">Disabled</span>
                                }
                            </div>
                            <button class="btn btn-sm btn-outline-danger border-0"
                                    @onclick="() => DeleteIdp(idp.Alias)">
                                <i class="bi bi-trash"></i>
                            </button>
                        </div>
                    }
                </div>
            }
        }
    }

    @* ── Groups ── *@
    @if (realmTab == "groups")
    {
        @if (loadingGroups)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            <div class="d-flex justify-content-between align-items-center mb-3">
                <span class="text-muted small">@(groups?.Count ?? 0) groups</span>
                <button class="btn btn-sm btn-primary" @onclick="() => showAddGroup = !showAddGroup">
                    <i class="bi bi-people me-1"></i>Add Group
                </button>
            </div>

            @if (showAddGroup)
            {
                <div class="d-flex gap-2 mb-3">
                    <input class="form-control form-control-sm" placeholder="Group name" @bind="newGroupName" />
                    <button class="btn btn-sm btn-primary" @onclick="AddGroup" disabled="@savingGroup">
                        @if (savingGroup) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        Create
                    </button>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddGroup = false">Cancel</button>
                </div>
                @if (groupError is not null)
                {
                    <div class="alert alert-danger py-2 small mb-3">@groupError</div>
                }
            }

            @if (groups is not null)
            {
                <div class="list-group">
                    @foreach (KeycloakGroupInfo g in groups)
                    {
                        <div class="list-group-item d-flex justify-content-between align-items-center py-2">
                            <span><i class="bi bi-people me-2 text-muted"></i>@g.Name <span class="text-muted small">@g.Path</span></span>
                            <button class="btn btn-sm btn-outline-danger border-0"
                                    @onclick="() => DeleteGroup(g.Id)">
                                <i class="bi bi-trash"></i>
                            </button>
                        </div>
                    }
                </div>
            }
        }
    }

    @* ── Organizations ── *@
    @if (realmTab == "orgs")
    {
        @if (loadingOrgs)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            <div class="d-flex justify-content-between align-items-center mb-3">
                <span class="text-muted small">@(orgs?.Count ?? 0) organizations (Keycloak 26+)</span>
                <button class="btn btn-sm btn-primary" @onclick="() => showAddOrg = !showAddOrg">
                    <i class="bi bi-building me-1"></i>Add Organization
                </button>
            </div>

            @if (showAddOrg)
            {
                <div class="card mb-3 border-primary-subtle">
                    <div class="card-body">
                        @if (orgError is not null)
                        {
                            <div class="alert alert-danger py-2 small">@orgError</div>
                        }
                        <div class="row g-2">
                            <div class="col-md-4">
                                <input class="form-control form-control-sm" placeholder="Name" @bind="newOrgName" />
                            </div>
                            <div class="col-md-8">
                                <input class="form-control form-control-sm" placeholder="Description (optional)" @bind="newOrgDescription" />
                            </div>
                        </div>
                        <div class="mt-2 d-flex gap-2">
                            <button class="btn btn-sm btn-primary" @onclick="AddOrg" disabled="@savingOrg">
                                @if (savingOrg) { <span class="spinner-border spinner-border-sm me-1"></span> }
                                Create
                            </button>
                            <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddOrg = false">Cancel</button>
                        </div>
                    </div>
                </div>
            }

            @if (orgs is not null)
            {
                <div class="list-group">
                    @foreach (KeycloakOrganizationInfo org in orgs)
                    {
                        <div class="list-group-item py-2">
                            <strong>@org.Name</strong>
                            @if (!string.IsNullOrWhiteSpace(org.Description))
                            {
                                <span class="text-muted small ms-2">@org.Description</span>
                            }
                            @if (!org.Enabled)
                            {
                                <span class="badge bg-secondary-subtle text-secondary ms-1 small">Disabled</span>
                            }
                        </div>
                    }
                </div>
            }
        }
    }

    @* ── Themes ── *@
    @if (realmTab == "themes")
    {
        @if (realmDetails is null)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            @if (realmThemeError is not null)
            {
                <div class="alert alert-danger py-2 small mb-3">@realmThemeError</div>
            }
            <div class="row g-3" style="max-width:480px">
                <div class="col-12">
                    <label class="form-label small fw-semibold">Login Theme</label>
                    <select class="form-select form-select-sm" @bind="editLoginTheme">
                        <option value="">(default)</option>
                        @foreach (string t in realmDetails.Themes)
                        {
                            <option value="@t">@t</option>
                        }
                    </select>
                </div>
                <div class="col-12">
                    <label class="form-label small fw-semibold">Account Console Theme</label>
                    <select class="form-select form-select-sm" @bind="editAccountTheme">
                        <option value="">(default)</option>
                        @foreach (string t in realmDetails.Themes)
                        {
                            <option value="@t">@t</option>
                        }
                    </select>
                </div>
                <div class="col-12">
                    <button class="btn btn-sm btn-primary" @onclick="SaveThemes" disabled="@savingThemes">
                        @if (savingThemes) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        Save
                    </button>
                </div>
            </div>
        }
    }

    @* ── Backup & Restore ── *@
    @if (realmTab == "backup")
    {
        @if (loadingBackups)
        {
            <div class="spinner-border spinner-border-sm text-primary"></div>
        }
        else
        {
            @if (backupError is not null)
            {
                <div class="alert alert-danger py-2 small mb-3">@backupError</div>
            }

            <div class="card mb-4">
                <div class="card-body">
                    <h6 class="card-title">Create Backup</h6>
                    <div class="row g-2 align-items-end" style="max-width:400px">
                        <div class="col">
                            <label class="form-label small">Storage Bucket</label>
                            <select class="form-select form-select-sm" @bind="backupStorageLinkId">
                                <option value="@Guid.Empty">Select bucket...</option>
                                @if (storageLinks is not null)
                                {
                                    @foreach (StorageLink link in storageLinks)
                                    {
                                        <option value="@link.Id">@link.Name</option>
                                    }
                                }
                            </select>
                        </div>
                        <div class="col-auto">
                            <button class="btn btn-sm btn-primary" @onclick="CreateBackup"
                                    disabled="@(creatingBackup || backupStorageLinkId == Guid.Empty)">
                                @if (creatingBackup) { <span class="spinner-border spinner-border-sm me-1"></span> }
                                Backup Now
                            </button>
                        </div>
                    </div>
                </div>
            </div>

            @if (backups is not null && backups.Count > 0)
            {
                <h6>Backups</h6>
                <div class="list-group">
                    @foreach (KeycloakBackup b in backups)
                    {
                        <div class="list-group-item py-2">
                            <div class="d-flex justify-content-between align-items-start">
                                <div>
                                    <span class="font-monospace small">@b.RealmName</span>
                                    <span class="text-muted small ms-2">@b.CreatedAt.ToString("yyyy-MM-dd HH:mm")</span>
                                    @if (b.Status == KeycloakBackupStatus.Ready)
                                    {
                                        <span class="badge bg-success-subtle text-success ms-1 small">Ready</span>
                                        <span class="text-muted small ms-1">@FormatSize(b.SizeBytes)</span>
                                    }
                                    else if (b.Status == KeycloakBackupStatus.Failed)
                                    {
                                        <span class="badge bg-danger-subtle text-danger ms-1 small">Failed</span>
                                        <span class="text-muted small ms-1">@b.LastError</span>
                                    }
                                    else
                                    {
                                        <span class="badge bg-secondary-subtle text-secondary ms-1 small">Creating</span>
                                    }
                                </div>
                                @if (b.Status == KeycloakBackupStatus.Ready)
                                {
                                    <div class="d-flex gap-1">
                                        <button class="btn btn-sm btn-outline-primary border-0"
                                                @onclick="() => RestoreBackup(b.Id)">
                                            <i class="bi bi-arrow-counterclockwise me-1"></i>Restore
                                        </button>
                                        <button class="btn btn-sm btn-outline-danger border-0"
                                                @onclick="() => DeleteBackup(b.Id)">
                                            <i class="bi bi-trash"></i>
                                        </button>
                                    </div>
                                }
                            </div>
                        </div>
                    }
                </div>
            }
        }
    }

    @* ── Customer Portal ── *@
    @if (realmTab == "portal")
    {
        @if (portalError is not null)
        {
            <div class="alert alert-danger py-2 small mb-3">@portalError</div>
        }
        @if (selectedRealm.LinkedApp is not null)
        {
            <div class="alert alert-success d-flex align-items-center gap-2 py-2 mb-3">
                <i class="bi bi-link-45deg"></i>
                <span>Linked to <strong>@selectedRealm.LinkedApp.Customer.Name / @selectedRealm.LinkedApp.Name</strong></span>
                <button class="btn btn-sm btn-outline-secondary ms-auto" @onclick="UnlinkApp">Unlink</button>
            </div>
        }
        else
        {
            <p class="text-muted small mb-3">Link this realm to a customer app so the customer can manage users, groups, and IdPs through their portal.</p>
            <div class="row g-2 align-items-end" style="max-width:400px">
                <div class="col">
                    <label class="form-label small">App</label>
                    <select class="form-select form-select-sm" @bind="linkAppId">
                        <option value="@Guid.Empty">Select app...</option>
                        @if (apps is not null)
                        {
                            @foreach (Data.App app in apps)
                            {
                                <option value="@app.Id">@app.Customer.Name / @app.Name</option>
                            }
                        }
                    </select>
                </div>
                <div class="col-auto">
                    <button class="btn btn-sm btn-primary" @onclick="LinkApp"
                            disabled="@(linkAppId == Guid.Empty)">
                        Link
                    </button>
                </div>
            </div>
        }
    }
}
else if (selectedKeycloak is not null)
{
    @* ── Level 2: Realm list for a specific Keycloak ── *@
    <nav class="mb-3">
        <button class="btn btn-sm btn-link text-decoration-none p-0" @onclick="BackToList">
            <i class="bi bi-arrow-left me-1"></i>All Keycloak Instances
        </button>
    </nav>

    <div class="d-flex align-items-center gap-2 mb-4">
        <i class="bi bi-person-badge fs-4 text-primary"></i>
        <div>
            <h5 class="mb-0">@selectedKeycloak.Component.Name
                <span class="badge bg-secondary-subtle text-secondary ms-2 small">@selectedKeycloak.Component.Cluster.Name</span>
            </h5>
            @if (selectedKeycloak.Config?.AdminUrl is not null)
            {
                <small class="text-muted font-monospace">@selectedKeycloak.Config.AdminUrl</small>
            }
        </div>
        <button class="btn btn-sm btn-outline-secondary ms-auto" @onclick="() => showEditConfig = !showEditConfig">
            <i class="bi bi-gear me-1"></i>Settings
        </button>
    </div>

    @if (showEditConfig && selectedKeycloak.Config is not null)
    {
        <div class="card mb-4 border-secondary-subtle">
            <div class="card-header small fw-semibold bg-secondary-subtle">Keycloak Settings</div>
            <div class="card-body">
                @if (configError is not null)
                {
                    <div class="alert alert-danger py-2 small">@configError</div>
                }
                <div class="row g-2" style="max-width:560px">
                    <div class="col-md-8">
                        <label class="form-label small">Admin URL</label>
                        <input class="form-control form-control-sm" placeholder="https://auth.example.com"
                               @bind="editAdminUrl" />
                    </div>
                    <div class="col-md-4">
                        <label class="form-label small">Admin Username</label>
                        <input class="form-control form-control-sm" @bind="editAdminUsername" />
                    </div>
                    <div class="col-md-6">
                        <label class="form-label small">New Admin Password <span class="text-muted">(leave blank to keep)</span></label>
                        <input type="password" class="form-control form-control-sm" @bind="editAdminPassword" />
                    </div>
                </div>
                <div class="mt-2 d-flex gap-2">
                    <button class="btn btn-sm btn-primary" @onclick="SaveConfig" disabled="@savingConfig">
                        @if (savingConfig) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        Save
                    </button>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="() => showEditConfig = false">Cancel</button>
                </div>
            </div>
        </div>
    }

    @if (!selectedKeycloak.IsConfigured)
    {
        @* Setup form for unconfigured keycloak *@
        <div class="card border-warning-subtle">
            <div class="card-header small fw-semibold bg-warning-subtle text-warning-emphasis">
                <i class="bi bi-exclamation-triangle me-1"></i>Not Configured
            </div>
            <div class="card-body">
                @if (selectedKeycloak.Component.Status == ComponentStatus.Failed)
                {
                    <div class="alert alert-danger py-2 small mb-3">
                        <i class="bi bi-x-circle me-1"></i>
                        The install failed — likely because the database credentials weren't available before
                        the pod started. Configure the database here, then retry the install from the
                        <strong>Cluster</strong> tab.
                    </div>
                }
                <p class="text-muted small mb-3">
                    Enter the admin credentials for this Keycloak instance. Optionally link a managed
                    CNPG database — if the instance already runs against its own Postgres, leave the
                    database unselected. Credentials are synced to a Kubernetes Secret in the
                    <code>@(selectedKeycloak.Component.Namespace ?? "keycloak")</code> namespace.
                </p>
                @if (setupError is not null)
                {
                    <div class="alert alert-danger py-2 small">@setupError</div>
                }
                <div class="row g-2" style="max-width:560px">
                    <div class="col-12">
                        <label class="form-label small fw-semibold">Database</label>
                        <select class="form-select form-select-sm" @bind="setupDatabaseId">
                            <option value="@Guid.Empty">Select CNPG database...</option>
                            @if (availableDatabases is not null)
                            {
                                @foreach (CnpgDatabase db in availableDatabases)
                                {
                                    <option value="@db.Id">@db.CnpgCluster.Name / @db.Name (@db.Owner)</option>
                                }
                            }
                        </select>
                        @if (availableDatabases is not null && availableDatabases.Count == 0)
                        {
                            <div class="form-text text-warning">
                                No ready CNPG databases found on this cluster. Create one in the Databases tab first.
                            </div>
                        }
                    </div>
                    <div class="col-md-8">
                        <label class="form-label small fw-semibold">Admin URL</label>
                        <input class="form-control form-control-sm"
                               placeholder="https://auth.example.com"
                               @bind="setupAdminUrl" />
                        @if (!string.IsNullOrWhiteSpace(selectedKeycloak.SuggestedAdminUrl))
                        {
                            <div class="form-text">
                                Suggested: <a href="#" @onclick:preventDefault
                                              @onclick="UseSuggestedUrl">
                                    @selectedKeycloak.SuggestedAdminUrl
                                </a>
                            </div>
                        }
                    </div>
                    <div class="col-md-4">
                        <label class="form-label small fw-semibold">Admin Username</label>
                        <input class="form-control form-control-sm" @bind="setupUsername" />
                    </div>
                    <div class="col-md-6">
                        <label class="form-label small fw-semibold">Admin Password</label>
                        <input type="password" class="form-control form-control-sm" @bind="setupPassword" />
                    </div>
                </div>
                <div class="mt-3">
                    <button class="btn btn-sm btn-primary" @onclick="ConfigureKeycloak"
                            disabled="@(configuringKeycloak || string.IsNullOrWhiteSpace(setupAdminUrl) || string.IsNullOrWhiteSpace(setupPassword))">
                        @if (configuringKeycloak) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        <i class="bi bi-check-circle me-1"></i>Configure
                    </button>
                </div>
            </div>
        </div>
    }
    else
    {
        @* Instance-level tabs: Realms | Themes *@
        <ul class="nav nav-tabs mb-4">
            <li class="nav-item">
                <button class="nav-link @(instanceTab == "realms" ? "active" : "")"
                        @onclick='() => SwitchInstanceTab("realms")'>
                    <i class="bi bi-shield-lock me-1"></i>Realms
                </button>
            </li>
            <li class="nav-item">
                <button class="nav-link @(instanceTab == "themes" ? "active" : "")"
                        @onclick='() => SwitchInstanceTab("themes")'>
                    <i class="bi bi-palette me-1"></i>Themes
                </button>
            </li>
        </ul>

        @if (instanceTab == "themes")
        {
            @* ── Themes tab ── *@
            <div class="d-flex gap-2 mb-3 flex-wrap">
                @foreach (string type in new[] { "login", "account", "admin", "email" })
                {
                    <button class="btn btn-sm @(themeType == type ? "btn-primary" : "btn-outline-secondary")"
                            @onclick="() => SwitchThemeType(type)">
                        @(char.ToUpper(type[0]) + type[1..])
                    </button>
                }
            </div>

            @if (loadingThemes)
            {
                <div class="spinner-border spinner-border-sm text-primary me-2"></div>
                <span class="text-muted small">Loading themes...</span>
            }
            else
            {
                @if (availableThemes is not null && availableThemes.TryGetValue(themeType, out List<string>? themeNames) && themeNames.Count > 0)
                {
                    <div class="mb-3">
                        <div class="text-muted small mb-1 fw-semibold">Available themes</div>
                        <div class="d-flex flex-wrap gap-1">
                            @foreach (string name in themeNames)
                            {
                                <span class="badge bg-secondary-subtle text-secondary border font-monospace">@name</span>
                            }
                        </div>
                    </div>
                }

                <div class="mb-2">
                    <label class="form-label small fw-semibold">Custom CSS override</label>
                    <div class="form-text mb-1">
                        Stored in EntKube. Apply to realms individually via the realm's Themes tab.
                    </div>
                    <textarea class="form-control font-monospace"
                              rows="16"
                              style="font-size:0.78rem; resize:vertical"
                              placeholder="/* Custom CSS for @themeType theme */"
                              @bind="themeCss"
                              @bind:event="oninput"></textarea>
                </div>
                <div class="d-flex gap-2 align-items-center">
                    <button class="btn btn-sm btn-primary" @onclick="SaveThemeCss" disabled="@savingTheme">
                        @if (savingTheme) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        <i class="bi bi-floppy me-1"></i>Save
                    </button>
                    @if (themeSaved)
                    {
                        <span class="text-success small"><i class="bi bi-check-circle me-1"></i>Saved</span>
                    }
                    @if (themeError is not null)
                    {
                        <span class="text-danger small">@themeError</span>
                    }
                </div>
            }
        }
        else
        {
        @* Realms list *@
        @if (realmSyncError is not null)
        {
            <div class="alert alert-warning py-2 small d-flex align-items-start gap-2 mb-3">
                <i class="bi bi-exclamation-triangle-fill mt-1 flex-shrink-0"></i>
                <div>
                    <strong>Could not reach Keycloak</strong> — showing cached realms.<br />
                    <span class="text-muted">@realmSyncError</span>
                </div>
            </div>
        }
        <div class="d-flex justify-content-between align-items-center mb-3">
            <span class="text-muted small">@(realms?.Count ?? 0) realms</span>
            <button class="btn btn-sm btn-primary" @onclick="() => showCreateRealm = !showCreateRealm">
                <i class="bi bi-plus-circle me-1"></i>New Realm
            </button>
        </div>

        @if (showCreateRealm)
        {
            <div class="card mb-3 border-primary-subtle">
                <div class="card-body">
                    @if (realmError is not null)
                    {
                        <div class="alert alert-danger py-2 small">@realmError</div>
                    }
                    <div class="row g-2">
                        <div class="col-md-4">
                            <label class="form-label small">Realm ID</label>
                            <input class="form-control form-control-sm" placeholder="e.g. acme-prod" @bind="newRealmName" />
                        </div>
                        <div class="col-md-4">
                            <label class="form-label small">Display Name</label>
                            <input class="form-control form-control-sm" placeholder="e.g. Acme Production" @bind="newRealmDisplayName" />
                        </div>
                        <div class="col-md-4">
                            <label class="form-label small">Login Theme <span class="text-muted">(optional)</span></label>
                            <input class="form-control form-control-sm" placeholder="keycloak" @bind="newRealmTheme" />
                        </div>
                    </div>
                    <div class="mt-2 d-flex gap-2">
                        <button class="btn btn-sm btn-primary" @onclick="CreateRealm" disabled="@creatingRealm">
                            @if (creatingRealm) { <span class="spinner-border spinner-border-sm me-1"></span> }
                            Create
                        </button>
                        <button class="btn btn-sm btn-outline-secondary" @onclick="() => showCreateRealm = false">Cancel</button>
                    </div>
                </div>
            </div>
        }

        @if (realms is not null)
        {
            @if (realms.Count == 0)
            {
                <div class="text-center py-4 text-muted">
                    <i class="bi bi-shield-lock display-6 d-block mb-2"></i>
                    No realms yet. Create one above.
                </div>
            }
            else
            {
                <div class="list-group">
                    @foreach (KeycloakRealm realm in realms)
                    {
                        <div class="list-group-item d-flex align-items-center py-2">
                            <div class="flex-grow-1 d-flex align-items-center gap-2 cursor-pointer"
                                 @onclick="() => OpenRealm(realm)" style="cursor:pointer">
                                <i class="bi bi-shield-lock text-primary fs-5"></i>
                                <div>
                                    <strong>@realm.DisplayName</strong>
                                    <span class="text-muted small ms-2 font-monospace">@realm.RealmName</span>
                                    @if (!realm.Enabled)
                                    {
                                        <span class="badge bg-secondary-subtle text-secondary ms-1 small">Disabled</span>
                                    }
                                    @if (realm.LinkedApp is not null)
                                    {
                                        <span class="badge bg-primary-subtle text-primary border border-primary-subtle ms-1 small">
                                            <i class="bi bi-link-45deg me-1"></i>@realm.LinkedApp.Customer.Name / @realm.LinkedApp.Name
                                        </span>
                                    }
                                </div>
                            </div>
                            <div class="d-flex gap-1">
                                <button class="btn btn-sm btn-outline-primary border-0"
                                        @onclick="() => OpenRealm(realm)">
                                    <i class="bi bi-gear"></i>
                                </button>
                                <button class="btn btn-sm btn-outline-danger border-0"
                                        @onclick="() => DeleteRealm(realm.Id)"
                                        disabled="@(deletingRealmId == realm.Id)">
                                    @if (deletingRealmId == realm.Id)
                                    {
                                        <span class="spinner-border spinner-border-sm"></span>
                                    }
                                    else
                                    {
                                        <i class="bi bi-trash"></i>
                                    }
                                </button>
                            </div>
                        </div>
                    }
                </div>
            }
        }
        } @* end realms tab else *@
    }
}
else
{
    @* ── Level 1: Keycloak instance list ── *@
    @if (detectedKeycloaks is null || detectedKeycloaks.Count == 0)
    {
        <div class="text-center py-5 text-muted">
            <i class="bi bi-person-badge display-4 d-block mb-3"></i>
            <p class="mb-1">No Keycloak instances found on this tenant's clusters.</p>
            <small>Install the Keycloak component from the Components tab on one of your clusters.</small>
        </div>
    }
    else
    {
        <p class="text-muted small mb-3">
            Detected @detectedKeycloaks.Count Keycloak @(detectedKeycloaks.Count == 1 ? "instance" : "instances").
            Select one to manage realms, users, identity providers, and backups.
        </p>

        <div class="row g-3">
            @foreach (DetectedKeycloak kc in detectedKeycloaks)
            {
                <div class="col-md-6 col-lg-4">
                    <div class="card h-100 @(kc.IsConfigured ? "" : "border-warning-subtle")">
                        <div class="card-body">
                            <div class="d-flex align-items-start justify-content-between mb-2">
                                <div>
                                    <h6 class="mb-0">@kc.Component.Name</h6>
                                    <small class="text-muted">@kc.Component.Cluster.Name</small>
                                </div>
                                <div class="d-flex flex-column align-items-end gap-1">
                                    @if (kc.Component.Status == ComponentStatus.Failed)
                                    {
                                        <span class="badge bg-danger-subtle text-danger border border-danger-subtle small">
                                            <i class="bi bi-x-circle me-1"></i>Install failed
                                        </span>
                                    }
                                    @if (kc.IsConfigured)
                                    {
                                        <span class="badge bg-success-subtle text-success border border-success-subtle small">
                                            <i class="bi bi-check-circle me-1"></i>Configured
                                        </span>
                                    }
                                    else
                                    {
                                        <span class="badge bg-warning-subtle text-warning border border-warning-subtle small">
                                            <i class="bi bi-exclamation-triangle me-1"></i>Setup needed
                                        </span>
                                    }
                                </div>
                            </div>
                            @if (kc.Config?.AdminUrl is not null)
                            {
                                <div class="text-muted small font-monospace text-truncate mb-1">@kc.Config.AdminUrl</div>
                            }
                            @if (kc.Config?.CnpgDatabase is not null)
                            {
                                <div class="small mb-2">
                                    <i class="bi bi-database me-1 text-muted"></i>
                                    @kc.Config.CnpgDatabase.CnpgCluster.Name / @kc.Config.CnpgDatabase.Name
                                </div>
                            }
                        </div>
                        <div class="card-footer bg-transparent border-0 pt-0">
                            <button class="btn btn-sm btn-primary w-100" @onclick="() => SelectKeycloak(kc)">
                                @if (kc.IsConfigured)
                                {
                                    <i class="bi bi-shield-lock me-1"></i>
                                    <span>Manage Realms</span>
                                }
                                else
                                {
                                    <i class="bi bi-gear me-1"></i>
                                    <span>Configure</span>
                                }
                            </button>
                        </div>
                    </div>
                </div>
            }
        </div>
    }
}

@code {
    [Parameter] public Guid TenantId { get; set; }

    // ── Load state ────────────────────────────────────────────────────────────
    private bool loading = true;
    private List<DetectedKeycloak>? detectedKeycloaks;
    private List<KeycloakRealm>? realms;
    private List<CnpgDatabase>? availableDatabases;
    private List<StorageLink>? storageLinks;
    private List<Data.App>? apps;

    // ── Navigation ────────────────────────────────────────────────────────────
    private DetectedKeycloak? selectedKeycloak;
    private KeycloakRealm? selectedRealm;
    private string realmTab = "users";
    private string instanceTab = "realms";

    // ── Themes tab ───────────────────────────────────────────────────────────
    private string themeType = "login";
    private Dictionary<string, List<string>>? availableThemes;
    private bool loadingThemes;
    private string? themeCss;
    private bool savingTheme;
    private bool themeSaved;
    private string? themeError;

    // ── Per-tab lazy data ─────────────────────────────────────────────────────
    private List<KeycloakUserInfo>? users;
    private List<KeycloakIdpInfo>? idps;
    private List<KeycloakGroupInfo>? groups;
    private List<KeycloakOrganizationInfo>? orgs;
    private List<KeycloakBackup>? backups;
    private KeycloakRealmDetails? realmDetails;

    private bool loadingUsers, loadingIdps, loadingGroups, loadingOrgs, loadingBackups;

    // ── Setup form ────────────────────────────────────────────────────────────
    private bool configuringKeycloak;
    private string? setupError;
    private Guid setupDatabaseId;
    private string setupAdminUrl = "";
    private string setupUsername = "admin";
    private string setupPassword = "";

    // ── Edit config form ──────────────────────────────────────────────────────
    private bool showEditConfig;
    private bool savingConfig;
    private string? configError;
    private string editAdminUrl = "";
    private string editAdminUsername = "admin";
    private string editAdminPassword = "";

    // ── Realm form ────────────────────────────────────────────────────────────
    private bool showCreateRealm;
    private bool creatingRealm;
    private string? realmError;
    private string? realmSyncError;
    private string newRealmName = "";
    private string newRealmDisplayName = "";
    private string newRealmTheme = "";
    private Guid? deletingRealmId;

    // ── User form ─────────────────────────────────────────────────────────────
    private bool showAddUser;
    private bool savingUser;
    private string? userError;
    private string newUserUsername = "";
    private string newUserEmail = "";
    private string newUserFirstName = "";
    private string newUserLastName = "";
    private string newUserPassword = "";

    // ── IdP form ──────────────────────────────────────────────────────────────
    private bool showAddIdp;
    private bool savingIdp;
    private string? idpError;
    private string newIdpAlias = "";
    private string newIdpProviderId = "oidc";
    private string newIdpClientId = "";
    private string newIdpClientSecret = "";

    // ── Group form ────────────────────────────────────────────────────────────
    private bool showAddGroup;
    private bool savingGroup;
    private string? groupError;
    private string newGroupName = "";

    // ── Org form ─────────────────────────────────────────────────────────────
    private bool showAddOrg;
    private bool savingOrg;
    private string? orgError;
    private string newOrgName = "";
    private string newOrgDescription = "";

    // ── Realm theme form ──────────────────────────────────────────────────────
    private bool savingThemes;
    private string? realmThemeError;
    private string editLoginTheme = "";
    private string editAccountTheme = "";

    // ── Backup form ───────────────────────────────────────────────────────────
    private bool creatingBackup;
    private string? backupError;
    private Guid backupStorageLinkId;

    // ── Portal form ───────────────────────────────────────────────────────────
    private string? portalError;
    private Guid linkAppId;

    protected override async Task OnInitializedAsync()
    {
        detectedKeycloaks = await KeycloakService.GetDetectedKeycloaksAsync(TenantId);
        loading = false;
    }

    private async Task SelectKeycloak(DetectedKeycloak kc)
    {
        selectedKeycloak = kc;
        realms = null;
        availableDatabases = null;
        setupError = null;
        setupDatabaseId = Guid.Empty;
        setupAdminUrl = kc.SuggestedAdminUrl ?? "";
        setupPassword = "";
        instanceTab = "realms";
        availableThemes = null;
        themeCss = null;
        themeSaved = false;
        themeError = null;
        realmSyncError = null;

        if (kc.IsConfigured)
        {
            try
            {
                realms = await KeycloakService.SyncRealmsFromKeycloakAsync(TenantId, kc.Config!.Id);
            }
            catch (Exception ex)
            {
                realmSyncError = ex.Message;
                realms = await KeycloakService.GetRealmsForConfigAsync(TenantId, kc.Config!.Id);
            }
            storageLinks ??= await StorageService.GetStorageLinksAsync(TenantId);
            apps ??= await KeycloakService.GetAppsAsync(TenantId);
        }
        else
        {
            availableDatabases = await KeycloakService.GetDatabasesForComponentAsync(
                TenantId, kc.Component.Id);
        }

        if (kc.Config is not null)
        {
            editAdminUrl = kc.Config.AdminUrl ?? "";
            editAdminUsername = kc.Config.AdminUsername;
        }
    }

    private async Task SwitchInstanceTab(string tab)
    {
        instanceTab = tab;
        themeSaved = false;
        themeError = null;

        if (tab == "themes" && selectedKeycloak?.Config is not null)
        {
            await LoadThemesTab();
        }
    }

    private async Task SwitchThemeType(string type)
    {
        themeType = type;
        themeSaved = false;
        themeError = null;
        await LoadThemeCss();
    }

    private async Task LoadThemesTab()
    {
        if (selectedKeycloak?.Config is null) return;

        loadingThemes = true;
        StateHasChanged();

        try
        {
            availableThemes = await KeycloakService.GetAvailableThemesAsync(TenantId, selectedKeycloak.Config.Id);
            await LoadThemeCss();
        }
        catch
        {
            availableThemes = [];
        }
        finally
        {
            loadingThemes = false;
        }
    }

    private async Task LoadThemeCss()
    {
        if (selectedKeycloak is null) return;
        themeCss = await KeycloakService.GetThemeCssAsync(TenantId, selectedKeycloak.Component.Id, themeType);
    }

    private async Task SaveThemeCss()
    {
        if (selectedKeycloak is null) return;

        savingTheme = true;
        themeSaved = false;
        themeError = null;

        try
        {
            await KeycloakService.SaveThemeCssAsync(
                TenantId, selectedKeycloak.Component.Id, themeType, themeCss ?? "");
            themeSaved = true;
        }
        catch (Exception ex)
        {
            themeError = ex.Message;
        }
        finally
        {
            savingTheme = false;
        }
    }

    private void BackToList()
    {
        selectedKeycloak = null;
        selectedRealm = null;
        realms = null;
    }

    private async Task OpenRealm(KeycloakRealm realm)
    {
        selectedRealm = realm;
        realmTab = "users";
        users = null;
        idps = null;
        groups = null;
        orgs = null;
        backups = null;
        realmDetails = null;
        await SwitchRealmTab("users");
    }

    private void BackToRealms()
    {
        selectedRealm = null;
        users = null;
        idps = null;
        groups = null;
        orgs = null;
        backups = null;
        realmDetails = null;
    }

    private async Task SwitchRealmTab(string tab)
    {
        realmTab = tab;

        if (selectedRealm is null) return;

        switch (tab)
        {
            case "users" when users is null:
                loadingUsers = true;
                StateHasChanged();
                try { users = await KeycloakService.GetUsersAsync(TenantId, selectedRealm.Id); }
                catch (Exception ex) { userError = ex.Message; }
                finally { loadingUsers = false; }
                break;

            case "idp" when idps is null:
                loadingIdps = true;
                StateHasChanged();
                try { idps = await KeycloakService.GetIdpsAsync(TenantId, selectedRealm.Id); }
                catch (Exception ex) { idpError = ex.Message; }
                finally { loadingIdps = false; }
                break;

            case "groups" when groups is null:
                loadingGroups = true;
                StateHasChanged();
                try { groups = await KeycloakService.GetGroupsAsync(TenantId, selectedRealm.Id); }
                catch (Exception ex) { groupError = ex.Message; }
                finally { loadingGroups = false; }
                break;

            case "orgs" when orgs is null:
                loadingOrgs = true;
                StateHasChanged();
                try { orgs = await KeycloakService.GetOrganizationsAsync(TenantId, selectedRealm.Id); }
                catch (Exception ex) { orgError = ex.Message; }
                finally { loadingOrgs = false; }
                break;

            case "themes" when realmDetails is null:
                StateHasChanged();
                try
                {
                    realmDetails = await KeycloakService.GetRealmDetailsAsync(TenantId, selectedRealm.Id);
                    editLoginTheme = realmDetails.LoginTheme ?? "";
                    editAccountTheme = realmDetails.AccountTheme ?? "";
                }
                catch (Exception ex) { realmThemeError = ex.Message; }
                break;

            case "backup" when backups is null:
                loadingBackups = true;
                storageLinks ??= await StorageService.GetStorageLinksAsync(TenantId);
                StateHasChanged();
                try { backups = await KeycloakService.GetBackupsAsync(TenantId, selectedRealm.Id); }
                catch (Exception ex) { backupError = ex.Message; }
                finally { loadingBackups = false; }
                break;

            case "portal":
                apps ??= await KeycloakService.GetAppsAsync(TenantId);
                break;
        }
    }

    // ── Setup ─────────────────────────────────────────────────────────────────

    private void UseSuggestedUrl()
    {
        setupAdminUrl = selectedKeycloak?.SuggestedAdminUrl ?? "";
    }

    private async Task ConfigureKeycloak()
    {
        if (selectedKeycloak is null) return;

        configuringKeycloak = true;
        setupError = null;

        try
        {
            KeycloakComponentConfig config = await KeycloakService.ConfigureAsync(
                TenantId,
                selectedKeycloak.Component.Id,
                setupDatabaseId == Guid.Empty ? null : setupDatabaseId,
                setupUsername,
                setupPassword,
                setupAdminUrl);

            // Sync the credentials to the K8s secret immediately so the pod can start.
            await LifecycleService.SyncComponentSecretsAsync(selectedKeycloak.Component.Id);

            // Import any realms that already exist in this Keycloak instance.
            await KeycloakService.SyncRealmsFromKeycloakAsync(TenantId, config.Id);

            // Refresh detection list and re-select the now-configured keycloak.
            detectedKeycloaks = await KeycloakService.GetDetectedKeycloaksAsync(TenantId);
            DetectedKeycloak? updated = detectedKeycloaks.FirstOrDefault(
                k => k.Component.Id == selectedKeycloak.Component.Id);

            if (updated is not null)
            {
                await SelectKeycloak(updated);
            }
        }
        catch (Exception ex)
        {
            setupError = ex.Message;
        }
        finally
        {
            configuringKeycloak = false;
        }
    }

    private async Task SaveConfig()
    {
        if (selectedKeycloak?.Config is null) return;

        savingConfig = true;
        configError = null;

        try
        {
            await KeycloakService.UpdateConfigAsync(
                TenantId, selectedKeycloak.Config.Id,
                editAdminUrl, editAdminUsername,
                string.IsNullOrWhiteSpace(editAdminPassword) ? null : editAdminPassword);

            showEditConfig = false;
            detectedKeycloaks = await KeycloakService.GetDetectedKeycloaksAsync(TenantId);
            DetectedKeycloak? updated = detectedKeycloaks.FirstOrDefault(
                k => k.Component.Id == selectedKeycloak.Component.Id);
            if (updated is not null) selectedKeycloak = updated;
        }
        catch (Exception ex)
        {
            configError = ex.Message;
        }
        finally
        {
            savingConfig = false;
        }
    }

    // ── Realm CRUD ────────────────────────────────────────────────────────────

    private async Task CreateRealm()
    {
        if (selectedKeycloak?.Config is null) return;

        creatingRealm = true;
        realmError = null;

        try
        {
            await KeycloakService.CreateRealmAsync(
                TenantId, selectedKeycloak.Config.Id,
                newRealmName, newRealmDisplayName,
                string.IsNullOrWhiteSpace(newRealmTheme) ? null : newRealmTheme);

            realms = await KeycloakService.GetRealmsForConfigAsync(TenantId, selectedKeycloak.Config.Id);
            showCreateRealm = false;
            newRealmName = "";
            newRealmDisplayName = "";
            newRealmTheme = "";
        }
        catch (Exception ex)
        {
            realmError = ex.Message;
        }
        finally
        {
            creatingRealm = false;
        }
    }

    private async Task DeleteRealm(Guid realmId)
    {
        if (selectedKeycloak?.Config is null) return;

        deletingRealmId = realmId;

        try
        {
            await KeycloakService.DeleteRealmAsync(TenantId, realmId);
            realms = await KeycloakService.GetRealmsForConfigAsync(TenantId, selectedKeycloak.Config.Id);
        }
        catch (Exception ex)
        {
            realmError = ex.Message;
        }
        finally
        {
            deletingRealmId = null;
        }
    }

    // ── User CRUD ─────────────────────────────────────────────────────────────

    private async Task AddUser()
    {
        if (selectedRealm is null) return;

        savingUser = true;
        userError = null;

        try
        {
            await KeycloakService.CreateUserAsync(
                TenantId, selectedRealm.Id,
                newUserUsername, newUserEmail, newUserFirstName, newUserLastName,
                string.IsNullOrWhiteSpace(newUserPassword) ? null : newUserPassword);

            users = await KeycloakService.GetUsersAsync(TenantId, selectedRealm.Id);
            showAddUser = false;
            newUserUsername = "";
            newUserEmail = "";
            newUserFirstName = "";
            newUserLastName = "";
            newUserPassword = "";
        }
        catch (Exception ex)
        {
            userError = ex.Message;
        }
        finally
        {
            savingUser = false;
        }
    }

    private async Task DeleteUser(string userId)
    {
        if (selectedRealm is null) return;

        try
        {
            await KeycloakService.DeleteUserAsync(TenantId, selectedRealm.Id, userId);
            users = await KeycloakService.GetUsersAsync(TenantId, selectedRealm.Id);
        }
        catch (Exception ex)
        {
            userError = ex.Message;
        }
    }

    // ── IdP CRUD ──────────────────────────────────────────────────────────────

    private async Task AddIdp()
    {
        if (selectedRealm is null) return;

        savingIdp = true;
        idpError = null;

        try
        {
            await KeycloakService.CreateIdpAsync(
                TenantId, selectedRealm.Id,
                newIdpAlias, newIdpProviderId, newIdpClientId, newIdpClientSecret);

            idps = await KeycloakService.GetIdpsAsync(TenantId, selectedRealm.Id);
            showAddIdp = false;
            newIdpAlias = "";
            newIdpClientId = "";
            newIdpClientSecret = "";
        }
        catch (Exception ex)
        {
            idpError = ex.Message;
        }
        finally
        {
            savingIdp = false;
        }
    }

    private async Task DeleteIdp(string alias)
    {
        if (selectedRealm is null) return;

        try
        {
            await KeycloakService.DeleteIdpAsync(TenantId, selectedRealm.Id, alias);
            idps = await KeycloakService.GetIdpsAsync(TenantId, selectedRealm.Id);
        }
        catch (Exception ex)
        {
            idpError = ex.Message;
        }
    }

    // ── Group CRUD ────────────────────────────────────────────────────────────

    private async Task AddGroup()
    {
        if (selectedRealm is null) return;

        savingGroup = true;
        groupError = null;

        try
        {
            await KeycloakService.CreateGroupAsync(TenantId, selectedRealm.Id, newGroupName);
            groups = await KeycloakService.GetGroupsAsync(TenantId, selectedRealm.Id);
            showAddGroup = false;
            newGroupName = "";
        }
        catch (Exception ex)
        {
            groupError = ex.Message;
        }
        finally
        {
            savingGroup = false;
        }
    }

    private async Task DeleteGroup(string groupId)
    {
        if (selectedRealm is null) return;

        try
        {
            await KeycloakService.DeleteGroupAsync(TenantId, selectedRealm.Id, groupId);
            groups = await KeycloakService.GetGroupsAsync(TenantId, selectedRealm.Id);
        }
        catch (Exception ex)
        {
            groupError = ex.Message;
        }
    }

    // ── Org CRUD ──────────────────────────────────────────────────────────────

    private async Task AddOrg()
    {
        if (selectedRealm is null) return;

        savingOrg = true;
        orgError = null;

        try
        {
            await KeycloakService.CreateOrganizationAsync(
                TenantId, selectedRealm.Id, newOrgName,
                string.IsNullOrWhiteSpace(newOrgDescription) ? null : newOrgDescription);

            orgs = await KeycloakService.GetOrganizationsAsync(TenantId, selectedRealm.Id);
            showAddOrg = false;
            newOrgName = "";
            newOrgDescription = "";
        }
        catch (Exception ex)
        {
            orgError = ex.Message;
        }
        finally
        {
            savingOrg = false;
        }
    }

    // ── Themes ────────────────────────────────────────────────────────────────

    private async Task SaveThemes()
    {
        if (selectedRealm is null) return;

        savingThemes = true;
        realmThemeError = null;

        try
        {
            await KeycloakService.UpdateRealmThemesAsync(
                TenantId, selectedRealm.Id,
                string.IsNullOrWhiteSpace(editLoginTheme) ? null : editLoginTheme,
                string.IsNullOrWhiteSpace(editAccountTheme) ? null : editAccountTheme);
        }
        catch (Exception ex)
        {
            realmThemeError = ex.Message;
        }
        finally
        {
            savingThemes = false;
        }
    }

    // ── Backup ────────────────────────────────────────────────────────────────

    private async Task CreateBackup()
    {
        if (selectedRealm is null || backupStorageLinkId == Guid.Empty) return;

        creatingBackup = true;
        backupError = null;

        try
        {
            await KeycloakService.CreateBackupAsync(TenantId, selectedRealm.Id, backupStorageLinkId);
            backups = await KeycloakService.GetBackupsAsync(TenantId, selectedRealm.Id);
        }
        catch (Exception ex)
        {
            backupError = ex.Message;
        }
        finally
        {
            creatingBackup = false;
        }
    }

    private async Task RestoreBackup(Guid backupId)
    {
        backupError = null;

        try
        {
            await KeycloakService.RestoreBackupAsync(TenantId, backupId, null);
        }
        catch (Exception ex)
        {
            backupError = ex.Message;
        }
    }

    private async Task DeleteBackup(Guid backupId)
    {
        backupError = null;

        try
        {
            await KeycloakService.DeleteBackupAsync(TenantId, backupId);
            if (selectedRealm is not null)
            {
                backups = await KeycloakService.GetBackupsAsync(TenantId, selectedRealm.Id);
            }
        }
        catch (Exception ex)
        {
            backupError = ex.Message;
        }
    }

    // ── Portal ────────────────────────────────────────────────────────────────

    private async Task LinkApp()
    {
        if (selectedRealm is null || linkAppId == Guid.Empty) return;

        portalError = null;

        try
        {
            await KeycloakService.LinkRealmToAppAsync(TenantId, selectedRealm.Id, linkAppId);

            if (selectedKeycloak?.Config is not null)
            {
                realms = await KeycloakService.GetRealmsForConfigAsync(TenantId, selectedKeycloak.Config.Id);
                selectedRealm = realms.FirstOrDefault(r => r.Id == selectedRealm.Id);
            }
        }
        catch (Exception ex)
        {
            portalError = ex.Message;
        }
    }

    private async Task UnlinkApp()
    {
        if (selectedRealm is null) return;

        portalError = null;

        try
        {
            await KeycloakService.UnlinkRealmFromAppAsync(TenantId, selectedRealm.Id);

            if (selectedKeycloak?.Config is not null)
            {
                realms = await KeycloakService.GetRealmsForConfigAsync(TenantId, selectedKeycloak.Config.Id);
                selectedRealm = realms.FirstOrDefault(r => r.Id == selectedRealm.Id);
            }
        }
        catch (Exception ex)
        {
            portalError = ex.Message;
        }
    }

    // ── Utilities ─────────────────────────────────────────────────────────────

    private static string FormatSize(long bytes)
    {
        if (bytes < 1024) return $"{bytes} B";
        if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB";
        return $"{bytes / (1024.0 * 1024):F1} MB";
    }
}
