using System.Text.Json;
using ZB.MOM.WW.OtOpcUa.Core.Hosting;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Proxy;

/// <summary>
///     Static factory registration helper for <see cref="GalaxyProxyDriver"/>. Server's
///     Program.cs calls <see cref="Register"/> once at startup; the bootstrapper (task #248)
///     then materialises Galaxy DriverInstance rows from the central config DB into live
///     driver instances. No dependency on Microsoft.Extensions.DependencyInjection so the
///     driver project stays free of DI machinery.
/// </summary>
public static class GalaxyProxyDriverFactoryExtensions
{
    public const string DriverTypeName = "Galaxy";

    /// <summary>
    ///     Register the Galaxy driver factory in the supplied <see cref="DriverFactoryRegistry"/>.
    ///     Throws if 'Galaxy' is already registered — single-instance per process.
    /// </summary>
    public static void Register(DriverFactoryRegistry registry)
    {
        ArgumentNullException.ThrowIfNull(registry);
        registry.Register(DriverTypeName, CreateInstance);
    }

    internal static GalaxyProxyDriver CreateInstance(string driverInstanceId, string driverConfigJson)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
        ArgumentException.ThrowIfNullOrWhiteSpace(driverConfigJson);

        // DriverConfig column is a JSON object that mirrors GalaxyProxyOptions.
        // Required: PipeName, SharedSecret. Optional: ConnectTimeoutMs (defaults to 10s).
        // The DriverInstanceId from the row wins over any value in the JSON — the row
        // is the authoritative identity per the schema's UX_DriverInstance_Generation_LogicalId.
        using var doc = JsonDocument.Parse(driverConfigJson);
        var root = doc.RootElement;

        string pipeName = root.TryGetProperty("PipeName", out var p) && p.ValueKind == JsonValueKind.String
            ? p.GetString()!
            : throw new InvalidOperationException(
                $"GalaxyProxyDriver config for '{driverInstanceId}' missing required PipeName");
        string sharedSecret = root.TryGetProperty("SharedSecret", out var s) && s.ValueKind == JsonValueKind.String
            ? s.GetString()!
            : throw new InvalidOperationException(
                $"GalaxyProxyDriver config for '{driverInstanceId}' missing required SharedSecret");
        var connectTimeout = root.TryGetProperty("ConnectTimeoutMs", out var t) && t.ValueKind == JsonValueKind.Number
            ? TimeSpan.FromMilliseconds(t.GetInt32())
            : TimeSpan.FromSeconds(10);

        return new GalaxyProxyDriver(new GalaxyProxyOptions
        {
            DriverInstanceId = driverInstanceId,
            PipeName = pipeName,
            SharedSecret = sharedSecret,
            ConnectTimeout = connectTimeout,
        });
    }
}
