using Admin.NET.Plugin.AiDOP.Manufacturing;
using Admin.NET.Plugin.AiDOP.Manufacturing.Dto;
using Xunit;
namespace Admin.NET.Plugin.AiDOP.Tests.S6.Manufacturing;
///
/// S6 Phase 1B 过程检规解析器 裁决逻辑单测(纯函数 Decide,无 DB)。
/// 覆盖 MATCHED / NO_MATCH / AMBIGUOUS / VERSION / INVALID_SPEC + 日期归一化 + tokenize。
///
public class S6ProcessSpecResolverTests
{
private static S6SpecCandidate C(long id, string wjbh, int version, string sxrj, int detail) =>
new() { Id = id, Wjbh = wjbh, Bb = "A." + version, Version = version, Sxrj = sxrj, DetailCount = detail };
private static readonly DateTime Ref = new(2026, 9, 1);
[Fact]
public void Matched_SingleEffectiveWjbh()
{
var r = S6ProcessSpecResolver.Decide(new[] { C(101, "UATD-GC-001", 1, "2026-08-28", 2) }, Ref);
Assert.Equal(S6SpecResolveStatus.Matched, r.Status);
Assert.Equal(101, r.MatchedSpecId);
Assert.Equal(1, r.CandidateCount);
}
[Fact]
public void NoMatch_EmptyCandidates()
{
var r = S6ProcessSpecResolver.Decide(System.Array.Empty(), Ref);
Assert.Equal(S6SpecResolveStatus.NoMatch, r.Status);
}
[Fact]
public void Ambiguous_TwoDistinctWjbhBothEffective()
{
var r = S6ProcessSpecResolver.Decide(new[]
{
C(201, "UATD-GC-002", 1, "2026-08-28", 2),
C(202, "UATD-GC-006", 1, "2026-08-28", 2),
}, Ref);
Assert.Equal(S6SpecResolveStatus.Ambiguous, r.Status);
Assert.Equal(2, r.CandidateCount);
Assert.Null(r.MatchedSpecId);
}
[Fact]
public void Version_SameWjbhPicksNewestEffective()
{
var r = S6ProcessSpecResolver.Decide(new[]
{
C(301, "UATD-GC-003", 1, "2026-08-28", 2),
C(302, "UATD-GC-003", 2, "2026-08-29", 2),
}, Ref);
Assert.Equal(S6SpecResolveStatus.Matched, r.Status);
Assert.Equal(302, r.MatchedSpecId); // 同 wjbh 取 sxrj 最新版本
Assert.Equal(1, r.CandidateCount);
}
[Fact]
public void InvalidSpec_MatchedButNoDetail()
{
var r = S6ProcessSpecResolver.Decide(new[] { C(401, "UATD-GC-009", 1, "2026-08-28", 0) }, Ref);
Assert.Equal(S6SpecResolveStatus.InvalidSpec, r.Status);
}
[Fact]
public void NoMatch_OnlyFutureEffective()
{
var r = S6ProcessSpecResolver.Decide(new[] { C(501, "UATD-GC-010", 1, "2027-01-01", 2) }, Ref);
Assert.Equal(S6SpecResolveStatus.NoMatch, r.Status);
}
[Fact]
public void NormalizeDate_HandlesFreeTextFormats()
{
Assert.NotNull(S6ProcessSpecResolver.NormalizeDate("2026-08-28"));
Assert.NotNull(S6ProcessSpecResolver.NormalizeDate("2025.12.12"));
Assert.NotNull(S6ProcessSpecResolver.NormalizeDate("2025-05-28 00:00:00"));
Assert.Null(S6ProcessSpecResolver.NormalizeDate(""));
Assert.Null(S6ProcessSpecResolver.NormalizeDate("包装(灭菌类)"));
}
[Fact]
public void Tokenize_SplitsMixedDelimiters()
{
var t = S6ProcessSpecResolver.Tokenize("91HC1N7;91HC1N8,98BC19A、982C01911 91HC12N");
Assert.Contains("91HC1N7", t);
Assert.Contains("98BC19A", t);
Assert.Contains("982C01911", t);
Assert.Equal(5, t.Count);
}
}