using ArchestrA;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend;

namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Tests.Backend;

/// <summary>
///     Driver.Historian.Wonderware-008 regression. The previous implementation unconditionally
///     called <c>HandleConnectionError()</c> whenever <c>StartQuery</c> returned <c>false</c>,
///     which tore down the (relatively expensive) shared SDK connection on a query-class error
///     such as a bad tag name. A burst of bad-tag queries could therefore push an otherwise
///     healthy cluster node into cooldown via the picker's <c>MarkFailed</c>. The fix
///     classifies the SDK error code: connection-class codes drop the connection; query-class
///     codes leave it intact.
/// </summary>
[Trait("Category", "Unit")]
public sealed class HistorianDataSourceStartQueryClassificationTests
{
    // ── Connection-class codes — the connection should be reset ───────────

    /// <summary>Verifies that connection-class error codes are classified as connection errors.</summary>
    /// <param name="code">The historian error code to test.</param>
    [Theory]
    [InlineData(HistorianAccessError.ErrorValue.FailedToConnect)]
    [InlineData(HistorianAccessError.ErrorValue.FailedToCreateSession)]
    [InlineData(HistorianAccessError.ErrorValue.NoReply)]
    [InlineData(HistorianAccessError.ErrorValue.NotReady)]
    [InlineData(HistorianAccessError.ErrorValue.NotInitialized)]
    [InlineData(HistorianAccessError.ErrorValue.Stopping)]
    [InlineData(HistorianAccessError.ErrorValue.Win32Exception)]
    [InlineData(HistorianAccessError.ErrorValue.InvalidResponse)]
    public void Connection_class_codes_are_classified_as_connection_errors(HistorianAccessError.ErrorValue code)
    {
        HistorianDataSource.IsConnectionClassError(code).ShouldBeTrue(
            $"{code} is a connection/server failure — the SDK connection should be reset");
    }

    // ── Query-class codes — the connection should NOT be reset ────────────

    /// <summary>Verifies that query-class error codes are NOT classified as connection errors.</summary>
    /// <param name="code">The historian error code to test.</param>
    [Theory]
    [InlineData(HistorianAccessError.ErrorValue.InvalidArgument)]   // bad tag name, etc.
    [InlineData(HistorianAccessError.ErrorValue.ValidationFailed)]  // bad query args
    [InlineData(HistorianAccessError.ErrorValue.NotApplicable)]     // wrong tag kind for query
    [InlineData(HistorianAccessError.ErrorValue.NotImplemented)]    // unsupported aggregate
    [InlineData(HistorianAccessError.ErrorValue.NoData)]            // empty range
    public void Query_class_codes_are_NOT_classified_as_connection_errors(HistorianAccessError.ErrorValue code)
    {
        HistorianDataSource.IsConnectionClassError(code).ShouldBeFalse(
            $"{code} is a query payload problem — must NOT tear down the SDK connection");
    }
}
