@page "/dashboard"
@page "/dashboards/{DashboardId?}"
@implements IAsyncDisposable
@inject IOptions<AppSettings> AppSettingsOptions
@inject NavigationManager Navigation
@inject IDashboardApiClient DashboardApi

<PageTitle>Dashboards</PageTitle>

<div class="dashboard-shell">
    <aside class="dashboard-nav">
        <div class="dashboard-nav-title">Dashboards</div>
        @if (dashboards.Count == 0)
        {
            <div class="px-3 py-2 text-muted">Keine Dashboards vorhanden.</div>
        }
        else
        {
            @foreach (var dashboard in dashboards)
            {
                <NavLink class="dashboard-nav-link" href="@($"dashboards/{dashboard.Id}?mode={(IsDesigner ? "designer" : "viewer")}")">@dashboard.Name</NavLink>
            }
        }
    </aside>
    <section class="dashboard-content">
        <div class="mb-3">
            <DxButton RenderStyle="ButtonRenderStyle.Primary" Click="@ToggleMode">
                @(IsDesigner ? "Zum Viewer wechseln" : "Zum Designer wechseln")
            </DxButton>
        </div>
        <DxDashboard @key="DashboardKey" Endpoint="@DashboardEndpoint" InitialDashboardId="@SelectedDashboardId" WorkingMode="@CurrentMode" style="width: 100%; height: 800px;">
        </DxDashboard>
    </section>
</div>

@code {
    [Parameter] public string? DashboardId { get; set; }
    [SupplyParameterFromQuery] public string? Mode { get; set; }

    private readonly List<DashboardInfoDto> dashboards = new();
    private HubConnection? _hubConnection;

    private bool IsDesigner => !string.Equals(Mode, "viewer", StringComparison.OrdinalIgnoreCase);
    private WorkingMode CurrentMode => IsDesigner ? WorkingMode.Designer : WorkingMode.ViewerOnly;
    private string SelectedDashboardId { get; set; } = string.Empty;
    private string DashboardKey => $"{SelectedDashboardId}-{(IsDesigner ? "designer" : "viewer")}";

    private string DashboardEndpoint => $"{AppSettingsOptions.Value.ApiBaseUrl.TrimEnd('/')}/api/dashboard";
    private string HubEndpoint => $"{AppSettingsOptions.Value.ApiBaseUrl.TrimEnd('/')}/hubs/dashboards";

    protected override async Task OnInitializedAsync()
    {
        await RefreshDashboards();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!firstRender) return;

        _hubConnection = new HubConnectionBuilder()
            .WithUrl(HubEndpoint)
            .WithAutomaticReconnect()
            .Build();

        _hubConnection.On("DashboardsChanged", async () =>
        {
            await RefreshDashboards();
        });

        await _hubConnection.StartAsync();
    }

    protected override async Task OnParametersSetAsync()
    {
        var requestedId = string.IsNullOrWhiteSpace(DashboardId) || string.Equals(DashboardId, "default", StringComparison.OrdinalIgnoreCase)
            ? null
            : DashboardId;

        var resolved = !string.IsNullOrWhiteSpace(requestedId)
            ? dashboards.FirstOrDefault(d => string.Equals(d.Id, requestedId, StringComparison.OrdinalIgnoreCase))
            : dashboards.FirstOrDefault(d => string.Equals(d.Id, "DefaultDashboard", StringComparison.OrdinalIgnoreCase))
              ?? dashboards.FirstOrDefault();

        if (resolved == null)
        {
            return;
        }

        SelectedDashboardId = resolved.Id;

        if (!string.Equals(DashboardId, resolved.Id, StringComparison.OrdinalIgnoreCase))
        {
            Navigation.NavigateTo($"dashboards/{resolved.Id}?mode={(IsDesigner ? "designer" : "viewer")}", replace: true);
        }
    }

    private void ToggleMode()
    {
        var targetMode = IsDesigner ? "viewer" : "designer";
        Navigation.NavigateTo($"dashboards/{SelectedDashboardId}?mode={targetMode}", replace: true);
    }

    private async Task RefreshDashboards()
    {
        var latest = await DashboardApi.GetAllAsync();
        if (latest.Count == dashboards.Count && latest.All(d => dashboards.Any(x => x.Id == d.Id && x.Name == d.Name)))
        {
            return;
        }

        dashboards.Clear();
        dashboards.AddRange(latest);
        await InvokeAsync(StateHasChanged);
    }

    public async ValueTask DisposeAsync()
    {
        if (_hubConnection != null)
        {
            await _hubConnection.DisposeAsync();
        }
    }
}