@page "/design/connections/create"
@page "/design/connections/{Id:int}/edit"
@page "/design/data-connections/create"
@page "/design/data-connections/{Id:int}/edit"
@using ScadaLink.Security
@using ScadaLink.Commons.Entities.Sites
@using ScadaLink.Commons.Interfaces.Repositories
@using ScadaLink.Commons.Types.DataConnections
@using ScadaLink.Commons.Types.Flattening
@using ScadaLink.Commons.Serialization
@using ScadaLink.Commons.Validators
@using ScadaLink.CentralUI.Components.Forms
@attribute [Authorize(Policy = AuthorizationPolicies.RequireDesign)]
@inject ISiteRepository SiteRepository
@inject NavigationManager NavigationManager

<div class="container-fluid mt-3">
    <div class="d-flex align-items-center mb-3">
        <button class="btn btn-outline-secondary btn-sm me-3" @onclick="GoBack">&larr; Back</button>
        <h4 class="mb-0">@(Id.HasValue ? "Edit Data Connection" : "Add Data Connection")</h4>
    </div>

    @if (_loading)
    {
        <LoadingSpinner IsLoading="true" />
    }
    else
    {
        <div class="card mb-3">
            <div class="card-body">
                <div class="mb-2">
                    <label class="form-label small">Site</label>
                    @if (_siteLocked)
                    {
                        <input type="text"
                               class="form-control form-control-plaintext form-control-sm"
                               readonly
                               value="@_siteName" />
                        <div class="form-text">Site is locked after creation.</div>
                    }
                    else
                    {
                        <select class="form-select form-select-sm" @bind="_formSiteId">
                            <option value="0">Select site...</option>
                            @foreach (var site in _sites)
                            {
                                <option value="@site.Id">@site.Name</option>
                            }
                        </select>
                    }
                </div>
                <div class="mb-3">
                    <label class="form-label small">Name</label>
                    <input type="text" class="form-control form-control-sm" @bind="_formName" />
                </div>

                <h6 class="text-muted mt-3">Primary endpoint</h6>
                <OpcUaEndpointEditor Title="Primary Endpoint"
                                     IdPrefix="primary"
                                     Config="_primaryConfig"
                                     IsLegacy="_primaryIsLegacy"
                                     Errors="_primaryErrors" />

                <h6 class="text-muted mt-3">
                    Backup endpoint
                    @if (!_showBackup)
                    {
                        <span class="badge bg-light text-muted border ms-2">Optional</span>
                    }
                </h6>
                @if (!_showBackup)
                {
                    <div class="mb-3">
                        <button type="button" class="btn btn-outline-secondary btn-sm"
                                @onclick="EnableBackup">Add Backup Endpoint</button>
                    </div>
                }
                else
                {
                    <OpcUaEndpointEditor Title="Backup Endpoint"
                                         IdPrefix="backup"
                                         Config="_backupConfig"
                                         IsLegacy="_backupIsLegacy"
                                         Errors="_backupErrors" />
                    <div class="mb-2">
                        <label class="form-label small">Failover Retry Count</label>
                        <input type="number" class="form-control form-control-sm" style="max-width: 120px;"
                               min="1" max="20" @bind="_formFailoverRetryCount" />
                        <div class="form-text">Retries before failing over to backup endpoint.</div>
                    </div>
                    <div class="mb-3">
                        <button type="button" class="btn btn-outline-danger btn-sm"
                                @onclick="RemoveBackup">Remove Backup</button>
                    </div>
                }

                @if (_formError != null)
                {
                    <div class="text-danger small mt-2">@_formError</div>
                }
                <div class="mt-3">
                    <button class="btn btn-success btn-sm me-1" @onclick="SaveConnection">Save</button>
                    <button class="btn btn-outline-secondary btn-sm" @onclick="GoBack">Cancel</button>
                </div>
            </div>
        </div>
    }
</div>

@code {
    [Parameter] public int? Id { get; set; }
    [SupplyParameterFromQuery] public int? SiteId { get; set; }

    private bool _loading = true;
    private DataConnection? _editingConnection;
    private List<Site> _sites = new();
    private int _formSiteId;
    private string _siteName = string.Empty;
    private bool _siteLocked;
    private string _formName = string.Empty;
    private OpcUaEndpointConfig _primaryConfig = new();
    private OpcUaEndpointConfig _backupConfig = new();
    private bool _primaryIsLegacy;
    private bool _backupIsLegacy;
    private bool _showBackup;
    private int _formFailoverRetryCount = 3;
    private ValidationResult? _primaryErrors;
    private ValidationResult? _backupErrors;
    private string? _formError;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            _sites = (await SiteRepository.GetAllSitesAsync()).ToList();

            if (Id.HasValue)
            {
                _editingConnection = await SiteRepository.GetDataConnectionByIdAsync(Id.Value);
                if (_editingConnection != null)
                {
                    _formSiteId = _editingConnection.SiteId;
                    _siteName = _sites.FirstOrDefault(s => s.Id == _formSiteId)?.Name ?? $"Site {_formSiteId}";
                    _siteLocked = true;
                    _formName = _editingConnection.Name;

                    (_primaryConfig, _primaryIsLegacy) =
                        OpcUaEndpointConfigSerializer.Deserialize(_editingConnection.PrimaryConfiguration);

                    if (!string.IsNullOrWhiteSpace(_editingConnection.BackupConfiguration))
                    {
                        (_backupConfig, _backupIsLegacy) =
                            OpcUaEndpointConfigSerializer.Deserialize(_editingConnection.BackupConfiguration);
                        _showBackup = true;
                        _formFailoverRetryCount = _editingConnection.FailoverRetryCount;
                    }
                }
            }
            else if (SiteId.HasValue)
            {
                var site = _sites.FirstOrDefault(s => s.Id == SiteId.Value);
                if (site != null)
                {
                    _formSiteId = site.Id;
                    _siteName = site.Name;
                    _siteLocked = true;
                }
            }
        }
        catch (Exception ex)
        {
            _formError = $"Failed to load: {ex.Message}";
        }
        finally
        {
            _loading = false;
        }
    }

    private async Task SaveConnection()
    {
        _formError = null;
        if (_formSiteId == 0) { _formError = "Site is required."; return; }
        if (string.IsNullOrWhiteSpace(_formName)) { _formError = "Name is required."; return; }

        _primaryErrors = OpcUaEndpointConfigValidator.Validate(_primaryConfig, "Primary.");
        _backupErrors = _showBackup
            ? OpcUaEndpointConfigValidator.Validate(_backupConfig, "Backup.")
            : null;

        if (!_primaryErrors.IsValid || (_backupErrors is { IsValid: false }))
        {
            _formError = "Fix the errors below before saving.";
            return;
        }

        var primaryJson = OpcUaEndpointConfigSerializer.Serialize(_primaryConfig);
        var backupJson = _showBackup ? OpcUaEndpointConfigSerializer.Serialize(_backupConfig) : null;

        try
        {
            if (_editingConnection != null)
            {
                _editingConnection.Name = _formName.Trim();
                _editingConnection.Protocol = "OpcUa";
                _editingConnection.PrimaryConfiguration = primaryJson;
                _editingConnection.BackupConfiguration = backupJson;
                _editingConnection.FailoverRetryCount = _showBackup ? _formFailoverRetryCount : 3;
                await SiteRepository.UpdateDataConnectionAsync(_editingConnection);
            }
            else
            {
                var conn = new DataConnection(_formName.Trim(), "OpcUa", _formSiteId)
                {
                    PrimaryConfiguration = primaryJson,
                    BackupConfiguration = backupJson,
                    FailoverRetryCount = _showBackup ? _formFailoverRetryCount : 3
                };
                await SiteRepository.AddDataConnectionAsync(conn);
            }
            await SiteRepository.SaveChangesAsync();
            NavigationManager.NavigateTo("/design/connections");
        }
        catch (Exception ex)
        {
            _formError = $"Save failed: {ex.Message}";
        }
    }

    private void EnableBackup() => _showBackup = true;

    private void RemoveBackup()
    {
        _showBackup = false;
        _backupConfig = new OpcUaEndpointConfig();
        _backupIsLegacy = false;
        _formFailoverRetryCount = 3;
    }

    private void GoBack() => NavigationManager.NavigateTo("/design/connections");
}
