using ZB.MOM.WW.OtOpcUa.Commons.Types;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Configuration.Validation;
///
/// Deploy gate for credential references (lmxopcua#815): every DriverConfig and DeviceConfig of a driver type
/// listed in must carry its credential fields as blank, an acceptable
/// literal, or a reference inside that driver's namespace (e.g. Galaxy secret:galaxy/… /
/// env:OTOPCUA_GALAXY_…). The same table the AdminUI save path, Test Connect, live browse and every
/// driver's resolve-time check read — so the gate and the runtime cannot disagree.
///
///
/// Heidenhain is excluded here only because already reports the same rule
/// (as ) through the shared parser; reporting it twice would
/// duplicate every error. The message names the field and the allowed forms, never the value.
///
public static class CredentialReferenceDeployChecks
{
/// A credential field holding a reference outside the driver's namespace (or a refused literal).
public const string Code = "CredentialReferenceOutOfScope";
/// Runs the gate.
/// The draft.
/// The errors.
public static IReadOnlyList Errors(DraftSnapshot draft)
{
var errors = new List();
foreach (var driver in draft.DriverInstances)
{
if (string.Equals(driver.DriverType, DriverTypeNames.Heidenhain, StringComparison.OrdinalIgnoreCase)) continue;
if (!DriverCredentialPolicy.TryGet(driver.DriverType, out _)) continue;
foreach (var problem in DriverCredentialPolicy.DescribeProblems(driver.DriverType, driver.DriverConfig))
errors.Add(new(Code, $"{driver.DriverType} driver '{driver.Name}': {problem}", driver.DriverInstanceId));
foreach (var device in draft.Devices.Where(d => string.Equals(d.DriverInstanceId, driver.DriverInstanceId, StringComparison.Ordinal)))
{
foreach (var problem in DriverCredentialPolicy.DescribeProblems(driver.DriverType, device.DeviceConfig))
errors.Add(new(Code, $"{driver.DriverType} device '{device.Name}': {problem}", device.DeviceId));
}
}
return errors;
}
}