@* Create/edit modal for an equipment, wired straight into IUnsTreeService. The host page owns
   visibility and supplies the parent line id (create) or the loaded EquipmentEditDto (edit), plus
   the cluster-scoped UNS-line and driver lists. The EquipmentId is system-generated (decision #125)
   so it is never an editable field — only shown read-only on edit. On a successful save it raises
   OnSaved so the host can reload the tree. *@
@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-xl" role="document">
            <div class="modal-content">
                <EditForm Model="_form" OnValidSubmit="SaveAsync" FormName="equipmentModal">
                    <DataAnnotationsValidator />
                    <div class="modal-header">
                        <h5 class="modal-title">@(IsNew ? "New equipment" : "Edit equipment")</h5>
                        <button type="button" class="btn-close" aria-label="Close" @onclick="CancelAsync"></button>
                    </div>
                    <div class="modal-body">
                        <h6 class="text-muted">Identity</h6>
                        @if (!IsNew)
                        {
                            <div class="mb-3">
                                <label class="form-label">EquipmentId</label>
                                <input class="form-control form-control-sm mono" value="@Existing?.EquipmentId" disabled />
                                <div class="form-text">System-generated; never operator-edited.</div>
                            </div>
                        }
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-name">Name</label>
                                <InputText id="eq-name" @bind-Value="_form.Name" class="form-control form-control-sm mono"
                                           placeholder="machine-01" />
                                <div class="form-text">UNS level 5 segment; lowercase letters, digits, dashes, up to 32 chars.</div>
                                <ValidationMessage For="@(() => _form.Name)" />
                            </div>
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-machinecode">MachineCode</label>
                                <InputText id="eq-machinecode" @bind-Value="_form.MachineCode" class="form-control form-control-sm mono"
                                           placeholder="machine_001" />
                                <ValidationMessage For="@(() => _form.MachineCode)" />
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-line">UNS line</label>
                                <InputSelect id="eq-line" @bind-Value="_form.UnsLineId" class="form-select form-select-sm">
                                    <option value="">— pick a line —</option>
                                    @foreach (var (id, display) in Lines)
                                    {
                                        <option value="@id">@display</option>
                                    }
                                </InputSelect>
                                <ValidationMessage For="@(() => _form.UnsLineId)" />
                            </div>
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-driver">Driver instance</label>
                                <InputSelect id="eq-driver" @bind-Value="_form.DriverInstanceId" class="form-select form-select-sm">
                                    <option value="">(none / driver-less)</option>
                                    @foreach (var (id, display) in Drivers)
                                    {
                                        <option value="@id">@display</option>
                                    }
                                </InputSelect>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-ztag">ZTag (ERP)</label>
                                <InputText id="eq-ztag" @bind-Value="_form.ZTag" class="form-control form-control-sm" />
                                <div class="form-text">Unique fleet-wide via ExternalIdReservation.</div>
                            </div>
                            <div class="col-md-6 mb-3">
                                <label class="form-label" for="eq-sap">SAPID</label>
                                <InputText id="eq-sap" @bind-Value="_form.SAPID" class="form-control form-control-sm" />
                            </div>
                        </div>
                        <div class="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">Surface in deployments</label>
                            </div>
                        </div>

                        <hr />
                        <h6 class="text-muted">OPC 40010 identification (optional)</h6>
                        <div class="row">
                            <div class="col-md-4 mb-3"><label class="form-label">Manufacturer</label><InputText @bind-Value="_form.Manufacturer" class="form-control form-control-sm" /></div>
                            <div class="col-md-4 mb-3"><label class="form-label">Model</label><InputText @bind-Value="_form.Model" class="form-control form-control-sm" /></div>
                            <div class="col-md-4 mb-3"><label class="form-label">SerialNumber</label><InputText @bind-Value="_form.SerialNumber" class="form-control form-control-sm" /></div>
                        </div>
                        <div class="row">
                            <div class="col-md-3 mb-3"><label class="form-label">HardwareRevision</label><InputText @bind-Value="_form.HardwareRevision" class="form-control form-control-sm" /></div>
                            <div class="col-md-3 mb-3"><label class="form-label">SoftwareRevision</label><InputText @bind-Value="_form.SoftwareRevision" class="form-control form-control-sm" /></div>
                            <div class="col-md-3 mb-3"><label class="form-label">Year of construction</label><InputNumber @bind-Value="_form.YearOfConstruction" class="form-control form-control-sm" /></div>
                            <div class="col-md-3 mb-3"><label class="form-label">AssetLocation</label><InputText @bind-Value="_form.AssetLocation" class="form-control form-control-sm" /></div>
                        </div>
                        <div class="row">
                            <div class="col-md-6 mb-3"><label class="form-label">ManufacturerUri</label><InputText @bind-Value="_form.ManufacturerUri" class="form-control form-control-sm mono" /></div>
                            <div class="col-md-6 mb-3"><label class="form-label">DeviceManualUri</label><InputText @bind-Value="_form.DeviceManualUri" class="form-control form-control-sm mono" /></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 equipment; <c>false</c> to edit <see cref="Existing"/>.</summary>
    [Parameter] public bool IsNew { get; set; }

    /// <summary>The parent line id used to default the UNS-line select on create.</summary>
    [Parameter] public string? UnsLineId { get; set; }

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

    /// <summary>The selectable UNS lines — scoped to the equipment's cluster by the host — as <c>(Id, Display)</c> pairs.</summary>
    [Parameter] public IReadOnlyList<(string Id, string Display)> Lines { get; set; } = Array.Empty<(string, string)>();

    /// <summary>The selectable drivers — scoped to the equipment's cluster by the host — as <c>(Id, Display)</c> pairs.</summary>
    [Parameter] public IReadOnlyList<(string Id, string Display)> Drivers { get; set; } = Array.Empty<(string, string)>();

    /// <summary>Raised after a successful create/save so the host can reload 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;

    protected override void OnParametersSet()
    {
        // Rebuild the working form whenever the host (re)opens the modal for a fresh target.
        if (IsNew)
        {
            _form = new FormModel { UnsLineId = UnsLineId ?? "" };
        }
        else if (Existing is not null)
        {
            _form = new FormModel
            {
                Name = Existing.Name,
                MachineCode = Existing.MachineCode,
                UnsLineId = Existing.UnsLineId,
                DriverInstanceId = Existing.DriverInstanceId,
                ZTag = Existing.ZTag,
                SAPID = Existing.SAPID,
                Manufacturer = Existing.Manufacturer,
                Model = Existing.Model,
                SerialNumber = Existing.SerialNumber,
                HardwareRevision = Existing.HardwareRevision,
                SoftwareRevision = Existing.SoftwareRevision,
                YearOfConstruction = Existing.YearOfConstruction,
                AssetLocation = Existing.AssetLocation,
                ManufacturerUri = Existing.ManufacturerUri,
                DeviceManualUri = Existing.DeviceManualUri,
                Enabled = Existing.Enabled,
            };
        }
        _error = null;
    }

    private async Task SaveAsync()
    {
        _busy = true;
        _error = null;
        try
        {
            var input = new EquipmentInput(
                _form.Name,
                _form.MachineCode,
                _form.UnsLineId,
                _form.DriverInstanceId,
                _form.ZTag,
                _form.SAPID,
                _form.Manufacturer,
                _form.Model,
                _form.SerialNumber,
                _form.HardwareRevision,
                _form.SoftwareRevision,
                _form.YearOfConstruction,
                _form.AssetLocation,
                _form.ManufacturerUri,
                _form.DeviceManualUri,
                _form.Enabled);

            var result = IsNew
                ? await Svc.CreateEquipmentAsync(input)
                : await Svc.UpdateEquipmentAsync(Existing!.EquipmentId, 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-z0-9-]{1,32}$", ErrorMessage = "Lowercase letters, digits, dashes only; max 32 chars.")]
        public string Name { get; set; } = "";
        [Required] public string MachineCode { get; set; } = "";
        [Required] public string UnsLineId { get; set; } = "";
        public string? DriverInstanceId { get; set; }
        public string? ZTag { get; set; }
        public string? SAPID { get; set; }
        public string? Manufacturer { get; set; }
        public string? Model { get; set; }
        public string? SerialNumber { get; set; }
        public string? HardwareRevision { get; set; }
        public string? SoftwareRevision { get; set; }
        public short? YearOfConstruction { get; set; }
        public string? AssetLocation { get; set; }
        public string? ManufacturerUri { get; set; }
        public string? DeviceManualUri { get; set; }
        public bool Enabled { get; set; } = true;
    }
}
