@* Create/edit modal for an equipment-bound scripted alarm, wired straight into IUnsTreeService. The host
   page owns visibility and supplies the owning equipment id (create) or the loaded ScriptedAlarmEditDto
   (edit), plus the candidate predicate-script list. The owning equipment is fixed by the tab, so there is
   no equipment selector. On a successful save it raises OnSaved so the host can refresh the equipment's
   alarms in place. Lifted from the standalone ScriptedAlarmEdit page (retired in a later task). *@
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns
@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">
                <EditForm Model="_form" OnValidSubmit="SaveAsync" FormName="scriptedAlarmModal">
                    <DataAnnotationsValidator />
                    <div class="modal-header">
                        <h5 class="modal-title">@(IsNew ? "New scripted alarm" : "Edit scripted alarm")</h5>
                        <button type="button" class="btn-close" aria-label="Close" @onclick="CancelAsync"></button>
                    </div>
                    <div class="modal-body">
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="alarm-id">ScriptedAlarmId</label>
                                <InputText id="alarm-id" @bind-Value="_form.ScriptedAlarmId" disabled="@(!IsNew)"
                                           class="form-control form-control-sm mono" />
                                <ValidationMessage For="@(() => _form.ScriptedAlarmId)" />
                            </div>
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="alarm-name">Name</label>
                                <InputText id="alarm-name" @bind-Value="_form.Name" class="form-control form-control-sm" />
                                <ValidationMessage For="@(() => _form.Name)" />
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="alarm-type">AlarmType</label>
                                <InputSelect id="alarm-type" @bind-Value="_form.AlarmType" class="form-select form-select-sm">
                                    <option value="LimitAlarm">LimitAlarm</option>
                                    <option value="DiscreteAlarm">DiscreteAlarm</option>
                                    <option value="OffNormalAlarm">OffNormalAlarm</option>
                                    <option value="AlarmCondition">AlarmCondition</option>
                                </InputSelect>
                                <ValidationMessage For="@(() => _form.AlarmType)" />
                            </div>
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="alarm-severity">Severity (1-1000)</label>
                                <InputNumber id="alarm-severity" @bind-Value="_form.Severity" class="form-control form-control-sm" />
                                <ValidationMessage For="@(() => _form.Severity)" />
                            </div>
                        </div>
                        <div class="mb-3">
                            <label class="form-label" for="alarm-script">Predicate script</label>
                            <InputSelect id="alarm-script" @bind-Value="_form.PredicateScriptId" class="form-select form-select-sm">
                                <option value="">— pick script —</option>
                                @foreach (var (id, display) in Scripts)
                                {
                                    <option value="@id">@display</option>
                                }
                            </InputSelect>
                            <ValidationMessage For="@(() => _form.PredicateScriptId)" />
                        </div>
                        <div class="mb-3">
                            <label class="form-label" for="alarm-message">Message template</label>
                            <InputTextArea id="alarm-message" @bind-Value="_form.MessageTemplate" rows="3"
                                           class="form-control form-control-sm"
                                           placeholder="{equipment.MachineCode} temperature out of range: {value}°C" />
                            <ValidationMessage For="@(() => _form.MessageTemplate)" />
                        </div>
                        <div class="row">
                            <div class="col-md-4 mb-3">
                                <label class="form-label">HistorizeToAveva</label>
                                <div class="form-check form-switch">
                                    <InputCheckbox @bind-Value="_form.HistorizeToAveva" class="form-check-input" />
                                    <label class="form-check-label">Route to HistorianGateway</label>
                                </div>
                            </div>
                            <div class="col-md-4 mb-3">
                                <label class="form-label">Retain</label>
                                <div class="form-check form-switch">
                                    <InputCheckbox @bind-Value="_form.Retain" class="form-check-input" />
                                    <label class="form-check-label">Retain active alarms on restart</label>
                                </div>
                            </div>
                            <div class="col-md-4 mb-3">
                                <label class="form-label">Enabled</label>
                                <div class="form-check form-switch">
                                    <InputCheckbox @bind-Value="_form.Enabled" class="form-check-input" />
                                    <label class="form-check-label">Spawn this alarm in deployments</label>
                                </div>
                            </div>
                        </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="submit" class="btn btn-primary" disabled="@_busy">
                            @if (_busy) { <span class="spinner-border spinner-border-sm me-1"></span> }
                            @(IsNew ? "Create" : "Save changes")
                        </button>
                    </div>
                </EditForm>
            </div>
        </div>
    </div>
}

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

    /// <summary><c>true</c> to create a new scripted alarm; <c>false</c> to edit <see cref="Existing"/>.</summary>
    [Parameter] public bool IsNew { get; set; }

    /// <summary>The owning equipment id the created alarm binds to (used only on create).</summary>
    [Parameter] public string? EquipmentId { get; set; }

    /// <summary>The scripted alarm being edited, when <see cref="IsNew"/> is <c>false</c>.</summary>
    [Parameter] public ScriptedAlarmEditDto? Existing { get; set; }

    /// <summary>The candidate predicate scripts as <c>(Id, Display)</c> pairs.</summary>
    [Parameter] public IReadOnlyList<(string Id, string Display)> Scripts { get; set; } = Array.Empty<(string, string)>();

    /// <summary>Raised after a successful create/save so the host can refresh the equipment's alarms and close.</summary>
    [Parameter] public EventCallback OnSaved { get; set; }

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

    private FormModel _form = new();
    private bool _busy;
    private string? _error;

    // Tracks which open this modal last loaded for, so unrelated Blazor Server re-renders don't
    // rebuild _form and clobber in-progress edits. Null while closed.
    private string? _loadedKey;

    protected override void OnParametersSet()
    {
        if (!Visible)
        {
            _loadedKey = null;   // closed → next open reloads fresh
            return;
        }

        // Guard against unrelated re-renders. In Blazor Server any live-status push re-invokes
        // OnParametersSet; without this the rebuild below would silently discard whatever the
        // operator has typed. Only rebuild when the modal OPENS or the target entity CHANGES.
        var key = IsNew ? "<new>" : Existing?.ScriptedAlarmId;
        if (key == _loadedKey) return;   // same open, re-render → preserve in-progress form edits
        _loadedKey = key;

        // Rebuild the working form whenever the host (re)opens the modal for a fresh target.
        if (IsNew)
        {
            _form = new FormModel();
        }
        else if (Existing is not null)
        {
            _form = new FormModel
            {
                ScriptedAlarmId = Existing.ScriptedAlarmId,
                Name = Existing.Name,
                AlarmType = Existing.AlarmType,
                Severity = Existing.Severity,
                MessageTemplate = Existing.MessageTemplate,
                PredicateScriptId = Existing.PredicateScriptId,
                HistorizeToAveva = Existing.HistorizeToAveva,
                Retain = Existing.Retain,
                Enabled = Existing.Enabled,
            };
        }
        _error = null;
    }

    private async Task SaveAsync()
    {
        _busy = true;
        _error = null;
        try
        {
            var input = new ScriptedAlarmInput(_form.ScriptedAlarmId, _form.Name, _form.AlarmType, _form.Severity,
                _form.MessageTemplate, _form.PredicateScriptId, _form.HistorizeToAveva, _form.Retain, _form.Enabled);

            var result = IsNew
                ? await Svc.CreateScriptedAlarmAsync(EquipmentId!, input)
                : await Svc.UpdateScriptedAlarmAsync(Existing!.ScriptedAlarmId, input, Existing.RowVersion);

            if (result.Ok)
            {
                await OnSaved.InvokeAsync();
            }
            else
            {
                _error = result.Error;
            }
        }
        finally
        {
            _busy = false;
        }
    }

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

    private sealed class FormModel
    {
        [Required, RegularExpression("^[A-Za-z0-9_-]+$")] public string ScriptedAlarmId { get; set; } = "";
        [Required] public string Name { get; set; } = "";
        [Required] public string AlarmType { get; set; } = "LimitAlarm";
        [Range(1, 1000)] public int Severity { get; set; } = 500;
        [Required] public string PredicateScriptId { get; set; } = "";
        [Required] public string MessageTemplate { get; set; } = "";
        public bool HistorizeToAveva { get; set; } = true;
        public bool Retain { get; set; } = true;
        public bool Enabled { get; set; } = true;
    }
}
