using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;

namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Audit;

/// <summary>
/// Code-behind for the execution-chain tree page (Audit Log ParentExecutionId
/// feature). Route <c>/audit/execution-tree</c>, reached via the Audit
/// Log drilldown drawer's "View execution chain" action with
/// <c>?executionId={guid}</c>.
///
/// <para>
/// On initialization the page parses <c>?executionId=</c> (lax-parsed, matching
/// the Audit Log page's drill-in contract — an absent or unparseable value
/// leaves the page in a guidance state and issues NO service call), then asks
/// <see cref="ZB.MOM.WW.ScadaBridge.CentralUI.Services.IAuditLogQueryService.GetExecutionTreeAsync"/>
/// for the whole chain. The flat <see cref="ExecutionTreeNode"/> list is handed
/// to the recursive <c>ExecutionTree</c> component, which assembles + renders
/// the tree.
/// </para>
///
/// <para>
/// The data path mirrors the Audit Log results grid: the page talks ONLY to the
/// CentralUI <c>IAuditLogQueryService</c> facade, never <c>IAuditLogRepository</c>
/// directly, so the page can be unit-tested with a substituted service.
/// </para>
/// </summary>
public partial class ExecutionTreePage
{
    [Inject] private NavigationManager Navigation { get; set; } = null!;

    // The parsed ?executionId= value, or null when absent / unparseable.
    private Guid? _executionId;

    // The flat chain returned by the query service; null until the load
    // completes (or when no id was supplied).
    private IReadOnlyList<ExecutionTreeNode>? _nodes;

    private bool _loading;
    private string? _error;

    // Execution-Tree Node Detail Modal feature — state backing the
    // <ExecutionDetailModal>. A double-click on a tree node sets
    // _modalExecutionId + flips _modalOpen true; the modal loads that
    // execution's audit rows on the closed → open transition. _modalOpen is the
    // visibility gate — _modalExecutionId is left intact across a close (it is
    // harmless while the modal is hidden and avoids a flicker if reopened).
    private Guid? _modalExecutionId;
    private bool _modalOpen;

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        _executionId = ParseExecutionId();
        if (_executionId is null)
        {
            // No id — render guidance, do not touch the service.
            return;
        }

        await LoadChainAsync(_executionId.Value);
    }

    /// <summary>
    /// Lax-parses <c>?executionId=</c>. Returns null when the param is absent or
    /// is not a valid <see cref="Guid"/> — the page then shows guidance instead
    /// of an error, consistent with the Audit Log page's drill-in handling.
    /// </summary>
    private Guid? ParseExecutionId()
    {
        var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
        var query = QueryHelpers.ParseQuery(uri.Query);
        if (query.TryGetValue("executionId", out var values)
            && Guid.TryParse(values.ToString(), out var parsed))
        {
            return parsed;
        }
        return null;
    }

    private async Task LoadChainAsync(Guid executionId)
    {
        _loading = true;
        _error = null;
        try
        {
            _nodes = await AuditLogQueryService.GetExecutionTreeAsync(executionId);
        }
        catch (Exception ex)
        {
            // A transient DB outage degrades this page to an error banner
            // rather than killing the circuit — the same defensive posture the
            // Audit Log grid takes around its query.
            _error = $"Could not load the execution chain: {ex.Message}";
            _nodes = null;
        }
        finally
        {
            _loading = false;
        }
    }

    /// <summary>
    /// Raised by <c>ExecutionTree</c> (bubbled up from a node double-click) with
    /// the activated node's <c>ExecutionId</c>. Opens the
    /// <c>ExecutionDetailModal</c> for that execution — the modal loads its
    /// audit rows on the closed → open transition.
    /// </summary>
    private void HandleNodeActivated(Guid executionId)
    {
        _modalExecutionId = executionId;
        _modalOpen = true;
    }

    /// <summary>
    /// Raised by <c>ExecutionDetailModal</c> when the user dismisses it. Flips
    /// the visibility gate closed; <see cref="_modalExecutionId"/> is left as-is.
    /// </summary>
    private void HandleModalClose() => _modalOpen = false;
}
