using Opc.Ua;
using Opc.Ua.Client;
using Serilog;

namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;

/// <summary>
///     Production session factory that creates real OPC UA sessions.
/// </summary>
internal sealed class DefaultSessionFactory : ISessionFactory
{
    private static readonly ILogger Logger = Log.ForContext<DefaultSessionFactory>();

    /// <summary>Creates a new OPC UA session.</summary>
    /// <param name="config">The OPC UA application configuration.</param>
    /// <param name="endpoint">The endpoint description to connect to.</param>
    /// <param name="sessionName">The name for the session.</param>
    /// <param name="sessionTimeoutMs">The session timeout in milliseconds.</param>
    /// <param name="identity">The user identity for the session.</param>
    /// <param name="ct">The cancellation token.</param>
    /// <returns>An adapter wrapping the created session.</returns>
    public async Task<ISessionAdapter> CreateSessionAsync(
        ApplicationConfiguration config,
        EndpointDescription endpoint,
        string sessionName,
        uint sessionTimeoutMs,
        UserIdentity identity,
        CancellationToken ct)
    {
        var endpointConfig = EndpointConfiguration.Create(config);
        var configuredEndpoint = new ConfiguredEndpoint(null, endpoint, endpointConfig);

        var session = await Session.Create(
            config,
            configuredEndpoint,
            false,
            sessionName,
            sessionTimeoutMs,
            identity,
            null);

        Logger.Information("Session created: {SessionName} -> {EndpointUrl}", sessionName, endpoint.EndpointUrl);
        return new DefaultSessionAdapter(session);
    }
}