@rendermode InteractiveServer
@attribute [Authorize]

@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Authorization
@using MudBlazor
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.Components
@using OpenIddict.Abstractions
@using RobotNet.IdentityServer.Data
@using Microsoft.EntityFrameworkCore
@using System.Threading
@using static OpenIddict.Abstractions.OpenIddictConstants

@inherits LayoutComponentBase

@inject AuthenticationStateProvider AuthenticationStateProvider
@inject ISnackbar Snackbar
@inject IDialogService DialogService
@inject NavigationManager NavigationManager
@inject IOpenIddictApplicationManager ApplicationManager
@inject IOpenIddictScopeManager ScopeManager

<MudDialogProvider />
<MudSnackbarProvider />



<MudContainer MaxWidth="MaxWidth.ExtraLarge" Style="padding: 1rem;">

    <div class="app-header">
        <MudStack Row Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
            <div>
                <MudText Typo="Typo.h4" Style="font-weight: 700; margin-bottom: 8px;">
                    OpenIddict Manager
                </MudText>
                <MudText Typo="Typo.body1" Style="opacity: 0.9;">
                    Quản lý ứng dụng OAuth2 & OpenID Connect một cách dễ dàng
                </MudText>
            </div>
            <MudChip T="string" Icon="@Icons.Material.Filled.Security" Color="Color.Surface" Size="Size.Large" Style="color:white">
                @filteredApplications.Count Apps
            </MudChip>

        </MudStack>
    </div>


    <MudPaper Class="glass-card pa-4">
        <div style="padding: 1.5rem; border-bottom: 1px solid #e2e8f0; background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);">
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <MudText Typo="Typo.h6" Style="margin: 0; color: #334155; font-weight: 600;">
                    Danh sách Application
                </MudText>
                <MudButton Variant="Variant.Filled"
                           StartIcon="@Icons.Material.Filled.Add"
                           OnClick="@(() => OpenApplicationDialog())"
                           Class="add-scope-btn"
                           Style="text-transform: none; font-weight: 500;">
                    Thêm Application
                </MudButton>
            </div>
        </div>
        <MudTextField @bind-Value="applicationSearchTerm"
                      Label="Tìm kiếm application..."
                      Placeholder="Nhập Client ID, Display Name, Type hoặc ID để tìm kiếm"
                      Variant="Variant.Outlined"
                      Adornment="Adornment.Start"
                      AdornmentIcon="@Icons.Material.Filled.Search"
                      Clearable="true"
                      Immediate="true"
                      DebounceInterval="300"
                      Style="margin-top: 0.5rem;" />
        <MudTable Items="FilteredApplications"
                  Hover="true"
                  Dense="true"
                  FixedHeader="true"
                  Loading="@loadingApplications"
                  Class="compact-table"
                  Virtualize="true">
            <HeaderContent>

                <MudTh Style="width: 120px;">Client</MudTh>
                <MudTh Style="width: 100px;">Type</MudTh>
                <MudTh Style="width: 150px;">Display Name</MudTh>
                <MudTh Style="width: 80px;">Secret</MudTh>
                <MudTh Style="width: 120px;">Endpoints</MudTh>
                <MudTh Style="width: 140px;">Actions</MudTh>
            </HeaderContent>
            <RowTemplate>
                <MudTd>
                    <MudStack Spacing="1">
                        <MudText Typo="Typo.body1" Style="font-weight: 600;">@context.ClientId</MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">@context.Id[..8]...</MudText>
                    </MudStack>
                </MudTd>
                <MudTd>
                    <MudChip T="string" Size="Size.Small"
                             Color="@(context.ClientType == ClientTypes.Confidential ? Color.Primary : Color.Secondary)"
                             Variant="Variant.Filled">
                        @(context.ClientType == ClientTypes.Confidential ? "Confidential" : "Public")
                    </MudChip>
                </MudTd>
                <MudTd>
                    <MudText Typo="Typo.body2">@context.DisplayName</MudText>
                </MudTd>
                <MudTd>
                    <div class="status-badge">
                        @if (!string.IsNullOrEmpty(context.ClientSecret))
                        {
                            <MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Small" />
                            <span style="color: var(--mud-palette-success);">Yes</span>
                        }
                        else
                        {
                            <MudIcon Icon="@Icons.Material.Filled.Cancel" Color="Color.Error" Size="Size.Small" />
                            <span style="color: var(--mud-palette-error);">No</span>
                        }
                    </div>
                </MudTd>
                <MudTd>
                    @if (context.RedirectUris.Any())
                    {
                        <MudTooltip Text="@string.Join(", ", context.RedirectUris)">
                            <MudChip T="string" Size="Size.Small" Color="Color.Info" Variant="Variant.Text">
                                @context.RedirectUris.Count URIs
                            </MudChip>
                        </MudTooltip>
                    }
                    else
                    {
                        <MudText Typo="Typo.caption" Color="Color.Secondary">No URIs</MudText>
                    }
                </MudTd>
                <MudTd>
                    <div class="action-buttons">
                        <MudIconButton Icon="@Icons.Material.Filled.Visibility"
                                       Size="Size.Small"
                                       Color="Color.Info"
                                       OnClick="@(() => ViewApplicationDetails(context))"
                                       aria-label="Chi tiết" />
                        <MudIconButton Icon="@Icons.Material.Filled.Edit"
                                       Size="Size.Small"
                                       Color="Color.Warning"
                                       OnClick="@(() => EditApplication(context))"
                                       aria-label="Sửa" />
                        <MudIconButton Icon="@Icons.Material.Filled.Delete"
                                       Size="Size.Small"
                                       Color="Color.Error"
                                       OnClick="@(() => DeleteApplication(context.ClientId))"
                                       aria-label="Xóa" />
                    </div>
                </MudTd>
            </RowTemplate>
            <PagerContent>
                <MudTablePager PageSizeOptions="new int[] { 5, 10, 25, 50, 100, int.MaxValue }" />
            </PagerContent>
        </MudTable>
    </MudPaper>
</MudContainer>



<MudDialog @bind-Visible="ShowApplicationDialog"
           Options="@(new DialogOptions { MaxWidth = MaxWidth.Large, FullWidth = true, CloseOnEscapeKey = true })">
    <TitleContent>
        <MudText Typo="Typo.h6">
            <MudIcon Icon="@(editingApplication != null ? Icons.Material.Filled.Edit : Icons.Material.Filled.Add)" Class="mr-2" />
            @(editingApplication != null ? "Chỉnh sửa Application" : "Tạo Application Mới")
        </MudText>
    </TitleContent>
    <DialogContent>
        <MudContainer Style="max-height: 70vh; overflow-y: auto;">
            <MudGrid Spacing="3">

                <MudItem xs="12">
                    <MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-3">
                        <MudIcon Icon="@Icons.Material.Filled.Info" Class="mr-2" />
                        Thông tin cơ bản
                    </MudText>
                </MudItem>

                <MudItem xs="12" md="6">
                    <MudTextField @bind-Value="applicationForm.ClientId"
                                  Label="Client ID"
                                  Required="true"
                                  Variant="Variant.Outlined"
                                  Adornment="Adornment.Start"
                                  AdornmentIcon="@Icons.Material.Filled.Key" />
                </MudItem>

                <MudItem xs="12" md="6">
                    <MudTextField @bind-Value="applicationForm.DisplayName"
                                  Label="Display Name"
                                  Variant="Variant.Outlined"
                                  Adornment="Adornment.Start"
                                  AdornmentIcon="@Icons.Material.Filled.Label" />
                </MudItem>

                <MudItem xs="12" md="6">
                    <MudSelect Value="applicationForm.ClientType"
                               Label="Client Type"
                               Variant="Variant.Outlined"
                               ValueChanged="@((string value) => OnClientTypeChanged(value))"
                               Adornment="Adornment.Start"
                               AdornmentIcon="@Icons.Material.Filled.Category">
                        <MudSelectItem Value="@ClientTypes.Public"> Public</MudSelectItem>
                        <MudSelectItem Value="@ClientTypes.Confidential">  Confidential</MudSelectItem>
                    </MudSelect>
                </MudItem>

                <MudItem xs="12" md="6">
                    <MudSelect @bind-Value="applicationForm.ConsentType"
                               Label="Consent Type"
                               Variant="Variant.Outlined"
                               Adornment="Adornment.Start"
                               AdornmentIcon="@Icons.Material.Filled.VerifiedUser">
                        <MudSelectItem Value="@ConsentTypes.Explicit"> Explicit</MudSelectItem>
                        <MudSelectItem Value="@ConsentTypes.Implicit"> Implicit</MudSelectItem>
                    </MudSelect>
                </MudItem>

                @if (applicationForm.ClientType == ClientTypes.Confidential)
                {
                    <MudItem xs="12">
                        <MudTextField @bind-Value="applicationForm.ClientSecret"
                                      Label="Client Secret"
                                      InputType="InputType.Password"
                                      Variant="Variant.Outlined"
                                      Placeholder="@(editingApplication != null ? "Để trống nếu không muốn thay đổi" : "Nhập Client Secret")"
                                      HelperText="@(editingApplication != null ? "Chỉ nhập nếu muốn thay đổi" : "Mật khẩu bí mật cho ứng dụng")"
                                      Adornment="Adornment.Start"
                                      AdornmentIcon="@Icons.Material.Filled.Password" />
                    </MudItem>
                }


                <MudItem xs="12">
                    <MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-3">
                        <MudIcon Icon="@Icons.Material.Filled.Link" Class="mr-2" />
                        Cấu hình Endpoints
                    </MudText>
                </MudItem>

                <MudItem xs="12" md="6">
                    <div class="uri-input-section">
                        <MudText Typo="Typo.subtitle2" Class="mb-2">Redirect URIs</MudText>
                        <MudTextField @bind-Value="redirectUriInput"
                                      Label="Redirect URI"
                                      Placeholder="https://app.com/callback"
                                      Variant="Variant.Outlined"
                                      Adornment="Adornment.End"
                                      AdornmentIcon="@Icons.Material.Filled.Add"
                                      OnAdornmentClick="AddRedirectUri"
                                      @onkeypress="@(async (KeyboardEventArgs e) => { if (e.Key == "Enter") { AddRedirectUri(); } })" />
                        <MudStack Row Wrap="Wrap.Wrap" Class="mt-2">
                            @foreach (var uri in applicationForm.RedirectUris)
                            {
                                <MudChip T="string" Text="@uri" OnClose="@(() => RemoveRedirectUri(uri))" Color="Color.Primary" Size="Size.Small" />
                            }
                        </MudStack>
                    </div>
                </MudItem>

                <MudItem xs="12" md="6">
                    <div class="uri-input-section">
                        <MudText Typo="Typo.subtitle2" Class="mb-2">Post Logout URIs</MudText>
                        <MudTextField @bind-Value="postLogoutUriInput"
                                      Label="Post Logout URI"
                                      Placeholder="https://app.com/logout"
                                      Variant="Variant.Outlined"
                                      Adornment="Adornment.End"
                                      AdornmentIcon="@Icons.Material.Filled.Add"
                                      OnAdornmentClick="AddPostLogoutUri"
                                      @onkeypress="@(async (KeyboardEventArgs e) => { if (e.Key == "Enter") { AddPostLogoutUri(); } })" />
                        <MudStack Row Wrap="Wrap.Wrap" Class="mt-2">
                            @foreach (var uri in applicationForm.PostLogoutRedirectUris)
                            {
                                <MudChip T="string" Text="@uri" OnClose="@(() => RemovePostLogoutUri(uri))" Color="Color.Secondary" Size="Size.Small" />
                            }
                        </MudStack>
                    </div>
                </MudItem>


                <MudItem xs="12">
                    <MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-3">
                        <MudIcon Icon="@Icons.Material.Filled.Security" Class="mr-2" />
                        Permissions & Requirements
                    </MudText>
                </MudItem>

                <MudItem xs="12" md="8">
                    <MudSelect T="string"
                               Label="Permissions"
                               Variant="Variant.Outlined"
                               MultiSelection="true"
                               SelectAll="true"
                               SelectAllText="Chọn tất cả"
                               Dense="true"
                               MaxHeight="200"
                               SelectedValuesChanged="@OnPermissionSelectionChanged"
                               SelectedValues="@GetSelectedPermissions()">
                        @foreach (var permission in permissionChecks)
                        {
                            <MudSelectItem Value="@permission.Key">
                                @permission.Key.Split('.').Last()
                            </MudSelectItem>
                        }
                    </MudSelect>

                    <MudStack Row Wrap="Wrap.Wrap" Class="mt-2">
                        @foreach (var selectedPermission in GetSelectedPermissions())
                        {
                            <MudChip T="string" Text="@selectedPermission.Split('.').Last()"
                                     OnClose="@(() => RemovePermission(selectedPermission))"
                                     Color="Color.Primary"
                                     Size="Size.Small" />
                        }
                    </MudStack>
                </MudItem>
                @if (applicationForm.ClientType == ClientTypes.Public)
                {
                    <MudItem xs="12" md="4">
                        <MudText Typo="Typo.subtitle2" Class="mb-2">Requirements</MudText>
                        @foreach (var requirement in requirementChecks)
                        {
                            <MudCheckBox T="string" @bind-Checked="@requirementChecks[requirement.Key]"
                                         Label="@requirement.Key.Split('.').Last()"
                                         Dense="true" />
                        }
                    </MudItem>
                }
            </MudGrid>
        </MudContainer>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="CancelApplicationDialog"
                   Color="Color.Default"
                   StartIcon="@Icons.Material.Filled.Cancel">
            Hủy
        </MudButton>
        <MudButton OnClick="SaveApplication"
                   Color="Color.Primary"
                   Variant="Variant.Filled"
                   StartIcon="@(editingApplication != null ? Icons.Material.Filled.Update : Icons.Material.Filled.Save)">
            @(editingApplication != null ? "Cập nhật" : "Tạo mới")
        </MudButton>
    </DialogActions>
</MudDialog>


<MudDialog @bind-Visible="ShowDetailsDialog"
           Options="@(new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true })">
    <TitleContent>
        <MudText Typo="Typo.h6">
            <MudIcon Icon="@Icons.Material.Filled.Info" Class="mr-2" />
            Chi tiết Application
        </MudText>
    </TitleContent>
    <DialogContent>
        @if (selectedApplication != null)
        {
            <MudContainer Style="max-height: 60vh; overflow-y: auto;">
                <MudGrid Spacing="2">
                    <MudItem xs="12">
                        <MudPaper Class="pa-3" Style="background: linear-gradient(45deg, #f8f9ff, #e8f2ff);">
                            <MudText Typo="Typo.subtitle2" Color="Color.Primary" Class="mb-2"> Thông tin cơ bản</MudText>
                            <MudStack Spacing="1">
                                <div><strong>ID:</strong> @selectedApplication.Id</div>
                                <div><strong>Client ID:</strong> @selectedApplication.ClientId</div>
                                <div><strong>Display Name:</strong> @selectedApplication.DisplayName</div>
                                <div><strong>Type:</strong> @selectedApplication.ClientType</div>
                                <div><strong>Consent:</strong> @selectedApplication.ConsentType</div>
                            </MudStack>
                        </MudPaper>
                    </MudItem>

                    <MudItem xs="12">
                        <MudPaper Class="pa-3" Style="background: linear-gradient(45deg, #fff8f0, #fff0e6);">
                            <MudText Typo="Typo.subtitle2" Color="Color.Warning" Class="mb-2">🔒 Bảo mật</MudText>
                            <div>
                                <strong>Client Secret:</strong>
                                @if (!string.IsNullOrEmpty(selectedApplication.ClientSecret))
                                {
                                    <MudChip T="string" Color="Color.Success" Size="Size.Small">Có</MudChip>
                                }
                                else
                                {
                                    <MudChip T="string" Color="Color.Error" Size="Size.Small">Không</MudChip>
                                }
                            </div>
                        </MudPaper>
                    </MudItem>

                    @if (selectedApplication.RedirectUris.Any())
                    {
                        <MudItem xs="12">
                            <MudPaper Class="pa-3" Style="background: linear-gradient(45deg, #f0fff8, #e6fff0);">
                                <MudText Typo="Typo.subtitle2" Color="Color.Success" Class="mb-2">🔗 Redirect URIs</MudText>
                                <MudStack Row Wrap="Wrap.Wrap">
                                    @foreach (var uri in selectedApplication.RedirectUris)
                                    {
                                        <MudChip T="string" Text="@uri" Size="Size.Small" Color="Color.Success" />
                                    }
                                </MudStack>
                            </MudPaper>
                        </MudItem>
                    }

                    @if (selectedApplication.Permissions.Any())
                    {
                        <MudItem xs="12">
                            <MudPaper Class="pa-3" Style="background: linear-gradient(45deg, #fff0f8, #ffe6f0);">
                                <MudText Typo="Typo.subtitle2" Color="Color.Secondary" Class="mb-2">🛡️ Permissions</MudText>
                                <MudStack Row Wrap="Wrap.Wrap">
                                    @foreach (var permission in selectedApplication.Permissions)
                                    {
                                        <MudChip T="string" Text="@permission.Split('.').Last()" Size="Size.Small" Color="Color.Secondary" />
                                    }
                                </MudStack>
                            </MudPaper>
                        </MudItem>
                    }
                    @if (selectedApplication.Requirements.Any())
                    {
                        <MudItem xs="12">
                            <MudPaper Class="pa-3" Style="background: linear-gradient(45deg, #f7f0f8, #f6fef0);">
                                <MudText Typo="Typo.subtitle2" Color="Color.Tertiary" Class="mb-2">⚙️ Requirements</MudText>
                                @if (selectedApplication.Requirements.Any())
                                {
                                    <MudStack Row Wrap="Wrap.Wrap">
                                        @foreach (var requirement in selectedApplication.Requirements)
                                        {
                                            <MudChip T="string" Text="@requirement" Size="Size.Small" Color="Color.Secondary" />
                                        }
                                    </MudStack>
                                }
                                else
                                {
                                    <MudText Typo="Typo.caption" Color="Color.Secondary" Style="font-style: italic;">
                                        Không có requirements nào được thiết lập
                                    </MudText>
                                }
                            </MudPaper>
                        </MudItem>
                    }

                </MudGrid>
            </MudContainer>
        }
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="CloseDetailsDialog"
                   Color="Color.Primary"
                   StartIcon="@Icons.Material.Filled.Close">
            Đóng
        </MudButton>
    </DialogActions>
</MudDialog>


@code {
    private List<ApplicationInfo> filteredApplications = new();
    private bool loadingApplications = false;
    private bool ShowApplicationDialog = false;
    private bool ShowDetailsDialog = false;
    private bool showClientSecret = false;
    private ApplicationInfo? editingApplication = null;
    private ApplicationInfo? selectedApplication = null;
    private ApplicationForm applicationForm = new();
    private string redirectUriInput = string.Empty;
    private string postLogoutUriInput = string.Empty;
    private string customScopeInput = string.Empty;
    private HashSet<string> customScopes = new();
    private Dictionary<string, bool> permissionChecks = new();
    private Dictionary<string, bool> requirementChecks = new();
    private List<string> availableScopes = new();
    public class ApplicationInfo
    {
        public string Id { get; set; } = string.Empty;
        public string ApplicationType { get; set; } = string.Empty;
        public string ClientId { get; set; } = string.Empty;
        public string DisplayName { get; set; } = string.Empty;
        public string ClientType { get; set; } = string.Empty;
        public string ConsentType { get; set; } = string.Empty;
        public List<string> RedirectUris { get; set; } = new();
        public List<string> PostLogoutRedirectUris { get; set; } = new();
        public List<string> Permissions { get; set; } = new();
        public List<string> Requirements { get; set; } = new();
        public string? ClientSecret { get; set; }
    }

    public class ApplicationForm
    {
        public string ClientId { get; set; } = string.Empty;
        public string DisplayName { get; set; } = string.Empty;
        public string ClientType { get; set; } = ClientTypes.Public;
        public string ConsentType { get; set; } = ConsentTypes.Explicit;
        public string? ClientSecret { get; set; }
        public List<string> RedirectUris { get; set; } = new();
        public List<string> PostLogoutRedirectUris { get; set; } = new();
    }

    private string applicationSearchTerm = "";

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        if (authState.User.Identity?.IsAuthenticated == true)
        {
            InitializePermissionChecks();
            InitializeRequirementChecks();
            await LoadApplicationsAsync();
            await LoadAvailableScopesAsync();
        }
    }

    private void InitializePermissionChecks()
    {
        permissionChecks.Clear();

        permissionChecks.Add(Permissions.Endpoints.Authorization, false);
        permissionChecks.Add(Permissions.Endpoints.EndSession, false);
        permissionChecks.Add(Permissions.Endpoints.Token, false);
        permissionChecks.Add(Permissions.Endpoints.Introspection, false);
        permissionChecks.Add(Permissions.GrantTypes.AuthorizationCode, false);
        permissionChecks.Add(Permissions.GrantTypes.RefreshToken, false);
        permissionChecks.Add(Permissions.GrantTypes.ClientCredentials, false);
        permissionChecks.Add(Permissions.ResponseTypes.Code, false);
        permissionChecks.Add(Permissions.ResponseTypes.Token, false);
        permissionChecks.Add(Permissions.Scopes.Email, false);
        permissionChecks.Add(Permissions.Scopes.Profile, false);
        permissionChecks.Add(Permissions.Scopes.Roles, false);

        foreach (var scope in availableScopes)
        {
            var scopePermission = Permissions.Prefixes.Scope + scope;
            if (!permissionChecks.ContainsKey(scopePermission))
            {
                permissionChecks.Add(scopePermission, false);
            }
        }
    }

    private void InitializeRequirementChecks()
    {
        requirementChecks = new() {
            { Requirements.Features.ProofKeyForCodeExchange, false }
        };
    }

    private void OnClientTypeChanged(string newClientType)
    {
        applicationForm.ClientType = newClientType;
        if (newClientType == ClientTypes.Public)
        {
            applicationForm.ClientSecret = null;
        }
        StateHasChanged();
    }

    private void OnPermissionSelectionChanged(IEnumerable<string> selectedValues)
    {
        foreach (var key in permissionChecks.Keys.ToList())
        {
            permissionChecks[key] = false;
        }

        foreach (var value in selectedValues)
        {
            if (permissionChecks.ContainsKey(value))
            {
                permissionChecks[value] = true;
            }
        }

        StateHasChanged();
    }

    private IEnumerable<string> GetSelectedPermissions()
    {
        return permissionChecks.Where(x => x.Value).Select(x => x.Key);
    }

    private void RemovePermission(string permission)
    {
        if (permissionChecks.ContainsKey(permission))
        {
            permissionChecks[permission] = false;
            StateHasChanged();
        }
    }

    private IEnumerable<ApplicationInfo> FilteredApplications =>
    string.IsNullOrWhiteSpace(applicationSearchTerm)
        ? filteredApplications
        : filteredApplications.Where(r =>
            (r.ClientId != null && r.ClientId.Contains(applicationSearchTerm, StringComparison.OrdinalIgnoreCase)) ||
            (r.DisplayName != null && r.DisplayName.Contains(applicationSearchTerm, StringComparison.OrdinalIgnoreCase)) ||
            (r.ClientType != null && r.ClientType.Contains(applicationSearchTerm, StringComparison.OrdinalIgnoreCase)) ||
            (r.Id != null && r.Id.Contains(applicationSearchTerm, StringComparison.OrdinalIgnoreCase)));

    private async Task LoadApplicationsAsync()
    {
        try
        {
            loadingApplications = true;
            filteredApplications.Clear();

            await foreach (var app in ApplicationManager.ListAsync())
            {
                string? clientSecret = null;
                try
                {
                    var properties = await ApplicationManager.GetPropertiesAsync(app);
                    clientSecret = properties.ContainsKey("client_secret") ? properties["client_secret"].ToString() : null;
                    if (string.IsNullOrEmpty(clientSecret))
                    {
                        var clientType = await ApplicationManager.GetClientTypeAsync(app);
                        if (clientType == ClientTypes.Confidential)
                        {
                            clientSecret = "***";
                        }
                    }
                }
                catch
                {
                    var clientType = await ApplicationManager.GetClientTypeAsync(app);
                    if (clientType == ClientTypes.Confidential)
                    {
                        clientSecret = "***";
                    }
                }

                filteredApplications.Add(new ApplicationInfo
                {
                    Id = await ApplicationManager.GetIdAsync(app) ?? string.Empty,
                    ApplicationType = await ApplicationManager.GetApplicationTypeAsync(app) ?? string.Empty,
                    ClientId = await ApplicationManager.GetClientIdAsync(app) ?? string.Empty,
                    DisplayName = await ApplicationManager.GetDisplayNameAsync(app) ?? string.Empty,
                    ClientType = await ApplicationManager.GetClientTypeAsync(app) ?? string.Empty,
                    ConsentType = await ApplicationManager.GetConsentTypeAsync(app) ?? string.Empty,
                    RedirectUris = (await ApplicationManager.GetRedirectUrisAsync(app)).Select(u => u.ToString()).ToList(),
                    PostLogoutRedirectUris = (await ApplicationManager.GetPostLogoutRedirectUrisAsync(app)).Select(u => u.ToString()).ToList(),
                    Permissions = (await ApplicationManager.GetPermissionsAsync(app)).ToList(),
                    Requirements = (await ApplicationManager.GetRequirementsAsync(app)).ToList(),
                    ClientSecret = clientSecret
                });
            }
        }
        catch (Exception ex)
        {
            Snackbar.Add($"Lỗi khi tải applications: {ex.Message}", Severity.Error);
        }
        finally
        {
            loadingApplications = false;
            StateHasChanged();
        }
    }


    private async Task LoadAvailableScopesAsync()
    {
        try
        {
            availableScopes.Clear();

            await foreach (var scope in ScopeManager.ListAsync())
            {
                var scopeName = await ScopeManager.GetNameAsync(scope);
                if (!string.IsNullOrEmpty(scopeName))
                {
                    availableScopes.Add(scopeName);
                }
            }
        }
        catch (Exception ex)
        {
            Snackbar.Add($"Lỗi khi tải scopes: {ex.Message}", Severity.Error);
        }
    }
    private void ViewApplicationDetails(ApplicationInfo application)
    {
        selectedApplication = application;
        showClientSecret = false;
        ShowDetailsDialog = true;
    }

    private void CloseDetailsDialog()
    {
        ShowDetailsDialog = false;
        selectedApplication = null;
        showClientSecret = false;
    }

    private void ToggleClientSecretVisibility()
    {
        showClientSecret = !showClientSecret;
    }

    private async void OpenApplicationDialog(ApplicationInfo? application = null)
    {
        await LoadAvailableScopesAsync();
        InitializePermissionChecks();
        ShowApplicationDialog = true;
        editingApplication = application;
        ResetApplicationForm();

        if (application != null)
        {
            applicationForm = new ApplicationForm
            {
                ClientId = application.ClientId,
                DisplayName = application.DisplayName,
                ClientType = application.ClientType,
                ConsentType = application.ConsentType,
                RedirectUris = new(application.RedirectUris),
                PostLogoutRedirectUris = new(application.PostLogoutRedirectUris),

                ClientSecret = application.ClientType == ClientTypes.Confidential ? string.Empty : null
            };

            foreach (var permission in application.Permissions)
            {
                if (permissionChecks.ContainsKey(permission)) permissionChecks[permission] = true;
                else if (permission.StartsWith(Permissions.Prefixes.Scope)) customScopes.Add(permission[Permissions.Prefixes.Scope.Length..]);
            }

            foreach (var requirement in application.Requirements)
            {
                if (requirementChecks.ContainsKey(requirement)) requirementChecks[requirement] = true;
            }
        }
        StateHasChanged();
    }

    private void EditApplication(ApplicationInfo application) => OpenApplicationDialog(application);

    private void ResetApplicationForm()
    {
        applicationForm = new();
        redirectUriInput = string.Empty;
        postLogoutUriInput = string.Empty;
        customScopeInput = string.Empty;
        customScopes.Clear();

        foreach (var key in permissionChecks.Keys.ToList()) permissionChecks[key] = false;
        foreach (var key in requirementChecks.Keys.ToList()) requirementChecks[key] = false;
    }

    private void AddRedirectUri()
    {
        if (!string.IsNullOrWhiteSpace(redirectUriInput))
        {
            if (Uri.TryCreate(redirectUriInput.Trim(), UriKind.Absolute, out _))
            {
                if (!applicationForm.RedirectUris.Contains(redirectUriInput.Trim()))
                {
                    applicationForm.RedirectUris.Add(redirectUriInput.Trim());
                    redirectUriInput = string.Empty;
                    StateHasChanged();
                }
                else
                {
                    Snackbar.Add("URI này đã tồn tại", Severity.Warning);
                }
            }
            else
            {
                Snackbar.Add("URI không hợp lệ. Vui lòng nhập URI đầy đủ (ví dụ: https://example.com/login-callback)", Severity.Error);
            }
        }
    }

    private void RemoveRedirectUri(string uri) => applicationForm.RedirectUris.Remove(uri);

    private void AddPostLogoutUri()
    {
        if (!string.IsNullOrWhiteSpace(postLogoutUriInput))
        {

            if (Uri.TryCreate(postLogoutUriInput.Trim(), UriKind.Absolute, out _))
            {
                if (!applicationForm.PostLogoutRedirectUris.Contains(postLogoutUriInput.Trim()))
                {
                    applicationForm.PostLogoutRedirectUris.Add(postLogoutUriInput.Trim());
                    postLogoutUriInput = string.Empty;
                    StateHasChanged();
                }
                else
                {
                    Snackbar.Add("URI này đã tồn tại", Severity.Warning);
                }
            }
            else
            {
                Snackbar.Add("URI không hợp lệ. Vui lòng nhập URI đầy đủ (ví dụ: https://example.com/logout-callback)", Severity.Error);
            }
        }
    }


    private void RemovePostLogoutUri(string uri) => applicationForm.PostLogoutRedirectUris.Remove(uri);

    private void AddCustomScope()
    {
        if (!string.IsNullOrWhiteSpace(customScopeInput) && !customScopes.Contains(customScopeInput))
        {
            customScopes.Add(customScopeInput);
            customScopeInput = string.Empty;
        }
    }

    private void RemoveCustomScope(string scope) => customScopes.Remove(scope);

    private async Task SaveApplication()
    {
        try
        {
            if (string.IsNullOrWhiteSpace(applicationForm.ClientId))
            {
                Snackbar.Add("Client ID là bắt buộc", Severity.Error);
                return;
            }

            if (applicationForm.ClientType == ClientTypes.Confidential)
            {
                if (editingApplication == null && string.IsNullOrWhiteSpace(applicationForm.ClientSecret))
                {
                    Snackbar.Add("Client Secret là bắt buộc cho Confidential client", Severity.Error);
                    return;
                }
            }

            if (editingApplication != null)
            {
                var existingApp = await ApplicationManager.FindByClientIdAsync(editingApplication.ClientId);
                if (existingApp != null)
                {
                    var descriptor = new OpenIddictApplicationDescriptor
                    {
                        ClientId = applicationForm.ClientId,
                        DisplayName = applicationForm.DisplayName,
                        ClientType = applicationForm.ClientType,
                        ConsentType = applicationForm.ConsentType
                    };

                    if (applicationForm.ClientType == ClientTypes.Confidential)
                    {
                        if (!string.IsNullOrWhiteSpace(applicationForm.ClientSecret))
                        {
                            descriptor.ClientSecret = applicationForm.ClientSecret;
                        }
                    }
                    else if (applicationForm.ClientType == ClientTypes.Public)
                    {
                        descriptor.ClientSecret = null;
                    }

                    var currentDescriptor = new OpenIddictApplicationDescriptor();
                    await ApplicationManager.PopulateAsync(currentDescriptor, existingApp);

                   
                    if (applicationForm.ClientType == ClientTypes.Confidential &&
                        string.IsNullOrWhiteSpace(applicationForm.ClientSecret))
                    {
                        descriptor.ClientSecret = currentDescriptor.ClientSecret;
                    }


                    foreach (var uriString in applicationForm.RedirectUris)
                    {
                        if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
                        {
                            descriptor.RedirectUris.Add(uri);
                        }
                        else
                        {
                            Snackbar.Add($"Redirect URI không hợp lệ: {uriString}", Severity.Error);
                            return;
                        }
                    }


                    foreach (var uriString in applicationForm.PostLogoutRedirectUris)
                    {
                        if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
                        {
                            descriptor.PostLogoutRedirectUris.Add(uri);
                        }
                        else
                        {
                            Snackbar.Add($"Post Logout URI không hợp lệ: {uriString}", Severity.Error);
                            return;
                        }
                    }


                    permissionChecks.Where(x => x.Value).ToList().ForEach(kvp => descriptor.Permissions.Add(kvp.Key));
                    customScopes.ToList().ForEach(scope => descriptor.Permissions.Add(Permissions.Prefixes.Scope + scope));

                    requirementChecks.Where(x => x.Value).ToList().ForEach(kvp => descriptor.Requirements.Add(kvp.Key));

                    await ApplicationManager.UpdateAsync(existingApp, descriptor);
                }
            }
            else
            {
                var descriptor = new OpenIddictApplicationDescriptor
                {
                    ClientId = applicationForm.ClientId,
                    DisplayName = applicationForm.DisplayName,
                    ClientType = applicationForm.ClientType,
                    ConsentType = applicationForm.ConsentType,
                    ClientSecret = applicationForm.ClientType == ClientTypes.Confidential ? applicationForm.ClientSecret : null
                };

                foreach (var uriString in applicationForm.RedirectUris)
                {
                    if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
                    {
                        descriptor.RedirectUris.Add(uri);
                    }
                }

                foreach (var uriString in applicationForm.PostLogoutRedirectUris)
                {
                    if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
                    {
                        descriptor.PostLogoutRedirectUris.Add(uri);
                    }
                }

                permissionChecks.Where(x => x.Value).ToList().ForEach(kvp => descriptor.Permissions.Add(kvp.Key));
                customScopes.ToList().ForEach(scope => descriptor.Permissions.Add(Permissions.Prefixes.Scope + scope));
                requirementChecks.Where(x => x.Value).ToList().ForEach(kvp => descriptor.Requirements.Add(kvp.Key));

                await ApplicationManager.CreateAsync(descriptor);
            }

            Snackbar.Add(editingApplication != null ? "Cập nhật application thành công" : "Tạo application thành công", Severity.Success);
            ShowApplicationDialog = false;
            await LoadApplicationsAsync();
        }
        catch (Exception ex)
        {
            Snackbar.Add($"Lỗi khi lưu application: {ex.Message}", Severity.Error);
        }
    }


    private void CancelApplicationDialog()
    {
        ShowApplicationDialog = false;
        ResetApplicationForm();
    }

    private async Task DeleteApplication(string clientId)
    {
        var confirm = await DialogService.ShowMessageBox("Xác nhận xóa", $"Bạn có chắc chắn muốn xóa application '{clientId}'?", yesText: "Xóa", cancelText: "Hủy");
        if (confirm == true)
        {
            try
            {
                var app = await ApplicationManager.FindByClientIdAsync(clientId);
                if (app != null)
                {
                    await ApplicationManager.DeleteAsync(app);
                    Snackbar.Add("Xóa application thành công", Severity.Success);
                    await LoadApplicationsAsync();
                }
            }
            catch (Exception ex)
            {
                Snackbar.Add($"Lỗi khi xóa application: {ex.Message}", Severity.Error);
            }
        }
    }
}