@* v3 Batch 3 "+ Add reference" picker: reuses the Raw project tree (RawTree) in picker mode to
   multi-select raw tags, scoped to the equipment's own cluster. The cluster scope is structural —
   IUnsTreeService.LoadReferencePickerRootAsync hands back a SINGLE cluster root, so raw tags of any
   other cluster are simply unreachable through the tree, not merely hidden. On commit the selected
   tag ids are added as UnsTagReference rows via AddReferencesAsync; the host reloads its Tags list. *@
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Raw
@inject IUnsTreeService Svc

@if (Visible)
{
    <div class="modal-backdrop fade show" style="display:block"></div>
    <div class="modal fade show" tabindex="-1" role="dialog" style="display:block">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Add tag references</h5>
                    <button type="button" class="btn-close" aria-label="Close" @onclick="CancelAsync"></button>
                </div>
                <div class="modal-body">
                    <p class="text-muted small mb-2">
                        Pick raw tags to reference under this equipment. The tree is scoped to the
                        equipment's cluster. Tick individual tags, or use a device / tag-group's
                        <em>“Select all tags below”</em> menu to pull many at once.
                    </p>

                    @if (_loading)
                    {
                        <p class="text-muted"><span class="spinner-border spinner-border-sm me-1"></span>Loading…</p>
                    }
                    else if (_roots.Count == 0)
                    {
                        <p class="text-muted">This equipment does not resolve to a cluster, so there are no raw tags to reference.</p>
                    }
                    else
                    {
                        <div class="border rounded p-2" style="max-height:50vh; overflow:auto">
                            <RawTree Roots="_roots" PickerMode="true" SelectedTagIds="_selected"
                                     OnSelectionChanged="OnSelectionChanged"
                                     ResolveDescendantTagIds="ResolveDescendantsAsync" />
                        </div>
                    }

                    @if (!string.IsNullOrWhiteSpace(_error))
                    {
                        <div class="text-danger small mt-2">@_error</div>
                    }
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-outline-secondary" @onclick="CancelAsync" disabled="@_busy">Cancel</button>
                    <button type="button" class="btn btn-primary" @onclick="CommitAsync" disabled="@(_busy || _selected.Count == 0)">
                        @if (_busy) { <span class="spinner-border spinner-border-sm me-1"></span> }
                        Add @_selected.Count reference@(_selected.Count == 1 ? "" : "s")
                    </button>
                </div>
            </div>
        </div>
    </div>
}

@code {
    /// <summary>Whether the modal is shown. The host owns this flag.</summary>
    [Parameter] public bool Visible { get; set; }

    /// <summary>The equipment the selected raw tags are referenced under.</summary>
    [Parameter] public string? EquipmentId { get; set; }

    /// <summary>Raised after references are committed so the host can reload its Tags list and close.</summary>
    [Parameter] public EventCallback OnCommitted { get; set; }

    /// <summary>Raised when the user cancels so the host can close.</summary>
    [Parameter] public EventCallback OnCancel { get; set; }

    private IReadOnlyList<RawNode> _roots = Array.Empty<RawNode>();
    private readonly HashSet<string> _selected = new(StringComparer.Ordinal);
    private bool _busy;
    private bool _loading;
    private string? _error;
    private bool _wasVisible;

    protected override async Task OnParametersSetAsync()
    {
        // Reset + reload only on the false→true transition so re-renders while open don't wipe state.
        if (Visible && !_wasVisible)
        {
            _selected.Clear();
            _error = null;
            _roots = Array.Empty<RawNode>();
            _loading = true;
            StateHasChanged();

            var root = string.IsNullOrEmpty(EquipmentId)
                ? null
                : await Svc.LoadReferencePickerRootAsync(EquipmentId);
            _roots = root is null ? Array.Empty<RawNode>() : new[] { root };
            _loading = false;
        }
        _wasVisible = Visible;
    }

    private Task<IReadOnlyList<string>> ResolveDescendantsAsync(RawNode node) =>
        Svc.LoadDescendantTagIdsAsync(node);

    // RawTree mutates _selected in place; this just re-renders the footer count.
    private void OnSelectionChanged() => StateHasChanged();

    private async Task CommitAsync()
    {
        if (_selected.Count == 0) { return; }
        _busy = true;
        _error = null;
        try
        {
            var res = await Svc.AddReferencesAsync(EquipmentId!, _selected.ToList());
            if (res.Ok) { await OnCommitted.InvokeAsync(); }
            else { _error = res.Error; }
        }
        finally
        {
            _busy = false;
        }
    }

    private Task CancelAsync() => OnCancel.InvokeAsync();
}
