#nullable enable
using System;
using System.Collections.Generic;
using System.Text;
using IGP.UnitySDK;
using IGP.UnitySDK.Core;
using IGP.UnitySDK.Network;
using Mirror;
using UnityEngine;

namespace IGP.UnitySDK.MirrorTransport
{
    [DisallowMultipleComponent]
    [AddComponentMenu("Network/IGP Mirror Transport")]
    public sealed class IGPMirrorTransport : Transport
    {
        internal const uint ConnectRequestMessageType = 41001;
        internal const uint ConnectAcceptMessageType = 41002;
        internal const uint DisconnectMessageType = 41003;
        // These values preserve the logical Mirror channel across the IGP data plane.
        // They do not describe whether the effective transport was KCP or raw UDP.
        internal const uint MirrorReliableChannelMessageType = 41010;
        internal const uint MirrorUnreliableChannelMessageType = 41011;
        internal const uint MirrorCompressedReliableChannelMessageType = 41012;
        internal const uint MirrorCompressedUnreliableChannelMessageType = 41013;
        private const int ReliablePacketMaxBytes = 512 * 1024;
        private const int LegacyUnreliablePacketMaxBytes = 12 * 1024;
        private const int DefaultRawUdpUnreliablePacketMaxBytes = 1200;
        private const int MaxQueuedMessages = 4096;
        private const int MaxQueuedMessageBytes = 16 * 1024 * 1024;
        private const float DefaultConnectRetryIntervalSeconds = 60f;
        private const float DefaultConnectTimeoutSeconds = 300f;
        private const int DefaultCompressionThresholdBytes = 2 * 1024;
        private const float DefaultMinCompressionRatio = 0.90f;
        private const int DefaultReliableBatchThresholdBytes = 1024;
        private const float DefaultPeerSilenceTimeoutSeconds = 300f;
        private const float SuppressedLogIntervalSeconds = 5f;
        private const int MessageLogHexPreviewMaxBytes = 64;
        private const int EstimatedKcpDataPlanePayloadMaxBytes = 12 * 1024;
        private const int EstimatedReliableChunkMaxBytes = 11_520;
        private const int ConnectAttemptIdBytes = 16;
        private const int ConnectAcceptConnectionIdBytes = sizeof(int);
        private const int ConnectCapabilitiesEnvelopeBytes = 9;
        private const byte ConnectCapabilitiesVersion = 1;
        private const uint ConnectCapabilityPayloadCompression = 1u << 0;

        [Header("Runtime")]
        [SerializeField] private IGPRuntimeManager? runtimeManager = null;

        [Header("Connection")]
        [SerializeField] private float connectRetryIntervalSeconds = DefaultConnectRetryIntervalSeconds;
        [SerializeField] private float connectTimeoutSeconds = DefaultConnectTimeoutSeconds;
        [Tooltip("Disconnect a Mirror peer after this many seconds without inbound data. Set higher for reconnect-heavy or large-payload sessions.")]
        [Min(1f)]
        [SerializeField] private float peerSilenceTimeoutSeconds = DefaultPeerSilenceTimeoutSeconds;

        [Header("Compression")]
        [SerializeField] private bool enablePayloadCompression = true;
        [SerializeField] private int compressionThresholdBytes = DefaultCompressionThresholdBytes;
        [SerializeField] private float minCompressionRatio = DefaultMinCompressionRatio;

        [Header("Batching")]
        [Tooltip("Prefer SDK raw UDP for Mirror unreliable channel. If raw UDP is unavailable, sends warn and fall back to reliable KCP.")]
        [SerializeField] private bool useRawUdpUnreliableLane = true;
        [Tooltip("Mirror reliable batching threshold. This limits small-message coalescing only; single messages may still be sent up to GetMaxPacketSize().")]
        [SerializeField] private int reliableBatchThresholdBytes = DefaultReliableBatchThresholdBytes;

        private readonly object queueLock = new object();
        private readonly IGPNetworkAnomalyLogLimiter anomalyLogLimiter = new IGPNetworkAnomalyLogLimiter();
        private readonly Queue<QueuedMessage> messageQueue = new Queue<QueuedMessage>();
        private readonly Dictionary<int, string> connectionIdToPlayerId = new Dictionary<int, string>();
        private readonly Dictionary<string, int> playerIdToConnectionId =
            new Dictionary<string, int>(StringComparer.Ordinal);
        private readonly Dictionary<string, bool> serverPayloadCompressionByPlayerId =
            new Dictionary<string, bool>(StringComparer.Ordinal);

        private bool runtimeBound;
        private bool hostedConnectionFailureHandled;
        private bool rawUdpFallbackWarningEmitted;
        private bool serverActive;
        private bool configurationLogged;
        private int nextConnectionId = 1;
        private string? pendingClientAddress;
        private string? pendingClientTargetPlayerId;
        private Guid? pendingClientConnectAttemptId;
        private string? connectedServerPlayerId;
        private Guid? connectedClientConnectAttemptId;
        private bool clientPayloadCompressionEnabled;
        private int clientConnectionId;
        private float nextConnectAttemptAt;
        private float connectDeadlineAt;
        private float nextSuppressedConnectLogAt;
        private int queuedMessageBytes;
        private float nextQueueDepthWarningAt;
        private float clientLastInboundFromHostAt;
        private bool? previousRetainIncomingPacketsForPolling;
        private readonly Dictionary<string, float> serverLastInboundByPlayerId =
            new Dictionary<string, float>(StringComparer.Ordinal);

        private struct QueuedMessage
        {
            public string RemotePlayerId;
            public uint MessageType;
            public byte[] Payload;
            public float EnqueuedAt;
        }

        private readonly struct ConnectRequestPayload
        {
            public ConnectRequestPayload(Guid? attemptId, uint capabilities)
            {
                AttemptId = attemptId;
                Capabilities = capabilities;
            }

            public Guid? AttemptId { get; }
            public uint Capabilities { get; }
        }

        private readonly struct ConnectAcceptPayload
        {
            public ConnectAcceptPayload(int connectionId, Guid? attemptId, uint capabilities)
            {
                ConnectionId = connectionId;
                AttemptId = attemptId;
                Capabilities = capabilities;
            }

            public int ConnectionId { get; }
            public Guid? AttemptId { get; }
            public uint Capabilities { get; }
        }

        private readonly struct PayloadSendDiagnostics
        {
            public PayloadSendDiagnostics(
                int originalBytes,
                bool compressionAttempted,
                bool compressionAccepted,
                IGPMirrorPayloadCompression.Diagnostics compression)
            {
                OriginalBytes = originalBytes;
                CompressionAttempted = compressionAttempted;
                CompressionAccepted = compressionAccepted;
                Compression = compression;
            }

            public int OriginalBytes { get; }
            public bool CompressionAttempted { get; }
            public bool CompressionAccepted { get; }
            public IGPMirrorPayloadCompression.Diagnostics Compression { get; }

            public static PayloadSendDiagnostics NotAttempted(int originalBytes)
            {
                return new PayloadSendDiagnostics(originalBytes, false, false, default);
            }

            public PayloadSendDiagnostics EnsureOriginalBytes(int fallbackBytes)
            {
                return OriginalBytes > 0 || fallbackBytes <= 0
                    ? this
                    : NotAttempted(fallbackBytes);
            }
        }

        public bool IsClientConnecting => !ClientConnected() && !string.IsNullOrWhiteSpace(pendingClientAddress);
        public string ClientTargetPlayerId => connectedServerPlayerId ?? pendingClientTargetPlayerId ?? string.Empty;
        public int ClientConnectionId => clientConnectionId;
        public int ServerConnectionCount => connectionIdToPlayerId.Count;
        public bool EnablePayloadCompression
        {
            get => enablePayloadCompression;
            set => enablePayloadCompression = value;
        }

        public int CompressionThresholdBytes
        {
            get => compressionThresholdBytes;
            set => compressionThresholdBytes = Math.Max(1, value);
        }

        public float MinCompressionRatio
        {
            get => minCompressionRatio;
            set => minCompressionRatio = Math.Min(0.99f, Math.Max(0.01f, value));
        }

        public int ReliableBatchThresholdBytes
        {
            get => NormalizeReliableBatchThreshold(reliableBatchThresholdBytes);
            set => reliableBatchThresholdBytes = NormalizeReliableBatchThreshold(value);
        }

        public bool UseRawUdpUnreliableLane
        {
            get => useRawUdpUnreliableLane;
            set
            {
                if (useRawUdpUnreliableLane != value)
                {
                    rawUdpFallbackWarningEmitted = false;
                }

                useRawUdpUnreliableLane = value;
            }
        }

        public float PeerSilenceTimeoutSeconds
        {
            get => NormalizePeerSilenceTimeout(peerSilenceTimeoutSeconds);
            set => peerSilenceTimeoutSeconds = NormalizePeerSilenceTimeout(value);
        }

        public override bool Available() => true;

        public override bool ClientConnected() => !string.IsNullOrWhiteSpace(connectedServerPlayerId);

        public override void ClientConnect(string address)
        {
            const string path = "ClientConnect";
            bool runtimeReady = TryBindRuntime();
            LogConfigurationOnce(path);
            string normalizedAddress = string.IsNullOrWhiteSpace(address) ? "host" : address.Trim();
            string targetPlayerId = ResolveServerPlayerId(normalizedAddress);
            LogAtLevel(
                runtimeReady ? IGPLogLevel.Debug : IGPLogLevel.Warning,
                path,
                $"called address={FormatValue(address)} normalizedAddress={normalizedAddress} " +
                $"target={FormatValue(targetPlayerId)} runtimeReady={runtimeReady}");

            if (ClientConnected() &&
                !string.IsNullOrWhiteSpace(targetPlayerId) &&
                string.Equals(connectedServerPlayerId, targetPlayerId, StringComparison.Ordinal))
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"ignored reason=already_connected target={targetPlayerId}");
                return;
            }

            if (ClientConnected())
            {
                CompleteClientDisconnect(sendDisconnectPacket: true, AppendPath(path, "CompleteClientDisconnect"));
            }

            bool isSamePendingTarget =
                !string.IsNullOrWhiteSpace(pendingClientAddress) &&
                (string.Equals(pendingClientAddress, normalizedAddress, StringComparison.OrdinalIgnoreCase) ||
                 (!string.IsNullOrWhiteSpace(targetPlayerId) &&
                  string.Equals(pendingClientTargetPlayerId, targetPlayerId, StringComparison.Ordinal)));

            if (!ClientConnected() && isSamePendingTarget)
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"ignored reason=already_connecting target={FormatValue(targetPlayerId)}");
                return;
            }

            pendingClientAddress = normalizedAddress;
            pendingClientTargetPlayerId = targetPlayerId;
            pendingClientConnectAttemptId = Guid.NewGuid();
            connectedClientConnectAttemptId = null;
            clientPayloadCompressionEnabled = false;
            clientConnectionId = 0;
            nextConnectAttemptAt = 0f;
            connectDeadlineAt = Now + connectTimeoutSeconds;
            nextSuppressedConnectLogAt = 0f;
            clientLastInboundFromHostAt = 0f;
            IGPLog.Info(
                "mirror-transport",
                path,
                $"pending target={FormatValue(targetPlayerId)} attemptId={pendingClientConnectAttemptId.Value:N} " +
                $"timeoutSeconds={connectTimeoutSeconds:F2} retryIntervalSeconds={connectRetryIntervalSeconds:F2}");
            ObserveRuntimeConnectionState();
        }

        public override void ClientSend(ArraySegment<byte> segment, int channelId = Channels.Reliable)
        {
            const string path = "ClientSend";
            int normalizedChannel = NormalizeChannel(channelId);
            if (!ClientConnected() || string.IsNullOrWhiteSpace(connectedServerPlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"rejected reason=client_not_connected channel={DescribeChannel(normalizedChannel)} " +
                    $"bytes={segment.Count} connectedServer={FormatValue(connectedServerPlayerId)}");
                OnClientError?.Invoke(TransportError.InvalidSend, "IGP client transport is not connected.");
                return;
            }

            var payload = CopySegment(segment);
            string serverPlayerId = connectedServerPlayerId!;
            var sendResult = TrySendPayload(serverPlayerId, payload, normalizedChannel, AppendPath(path, "TrySendPayload"));
            if (sendResult != IGPNetworkResult.kSuccess)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"client_error_invoked reason=send_failed result={sendResult}");
                OnClientError?.Invoke(TransportError.InvalidSend, "Failed to send Mirror payload over IGP.");
                return;
            }

            OnClientDataSent?.Invoke(new ArraySegment<byte>(payload), normalizedChannel);
        }

        public override void ClientDisconnect()
        {
            const string path = "ClientDisconnect";
            IGPLog.Debug(
                "mirror-transport",
                path,
                "called");
            CompleteClientDisconnect(sendDisconnectPacket: true, AppendPath(path, "CompleteClientDisconnect"));
        }

        public override Uri ServerUri()
        {
            return new Uri("igp://host");
        }

        public override bool ServerActive() => serverActive;

        public override void ServerStart()
        {
            const string path = "ServerStart";
            bool runtimeReady = TryBindRuntime();
            LogConfigurationOnce(path);
            serverActive = true;
            LogAtLevel(
                runtimeReady ? IGPLogLevel.Info : IGPLogLevel.Warning,
                path,
                $"started runtimeReady={runtimeReady}");
            ObserveRuntimeConnectionState();
        }

        public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId = Channels.Reliable)
        {
            const string path = "ServerSend";
            int normalizedChannel = NormalizeChannel(channelId);
            if (!connectionIdToPlayerId.TryGetValue(connectionId, out var remotePlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"rejected reason=unknown_connection connectionId={connectionId} " +
                    $"channel={DescribeChannel(normalizedChannel)} bytes={segment.Count}");
                OnServerError?.Invoke(connectionId, TransportError.InvalidSend, "Unknown IGP client connection.");
                return;
            }

            var payload = CopySegment(segment);
            var sendResult = TrySendPayload(remotePlayerId, payload, normalizedChannel, AppendPath(path, "TrySendPayload"));
            if (sendResult != IGPNetworkResult.kSuccess)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"server_error_invoked reason=send_failed connectionId={connectionId} result={sendResult}");
                OnServerError?.Invoke(connectionId, TransportError.InvalidSend, "Failed to send Mirror payload over IGP.");
                return;
            }

            OnServerDataSent?.Invoke(connectionId, new ArraySegment<byte>(payload), normalizedChannel);
        }

        public override void ServerDisconnect(int connectionId)
        {
            const string path = "ServerDisconnect";
            if (!connectionIdToPlayerId.TryGetValue(connectionId, out var remotePlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"ignored reason=unknown_connection connectionId={connectionId}");
                return;
            }

            TrySendControl(
                remotePlayerId,
                DisconnectMessageType,
                new byte[] { 1 },
                AppendPath(path, "TrySendControl"));
            RemoveServerConnection(
                connectionId,
                remotePlayerId,
                notifyMirror: true,
                AppendPath(path, "RemoveServerConnection"));
        }

        public override string ServerGetClientAddress(int connectionId)
        {
            const string path = "ServerGetClientAddress";
            if (connectionIdToPlayerId.TryGetValue(connectionId, out var remotePlayerId))
            {
                return remotePlayerId;
            }

            IGPLog.Warning(
                "mirror-transport",
                path,
                $"returning_empty reason=unknown_connection connectionId={connectionId}");
            return string.Empty;
        }

        public override void ServerStop()
        {
            const string path = "ServerStop";
            var activeConnections = new List<KeyValuePair<int, string>>(connectionIdToPlayerId);
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"called activeConnections={activeConnections.Count} serverActive={serverActive}");
            foreach (var entry in activeConnections)
            {
                TrySendControl(
                    entry.Value,
                    DisconnectMessageType,
                    new byte[] { 1 },
                    AppendPath(path, "TrySendControl"));
                RemoveServerConnection(
                    entry.Key,
                    entry.Value,
                    notifyMirror: false,
                    AppendPath(path, "RemoveServerConnection"));
            }

            serverActive = false;
            IGPLog.Info(
                "mirror-transport",
                path,
                "stopped");
        }

        public override int GetMaxPacketSize(int channelId = Channels.Reliable)
        {
            return NormalizeChannel(channelId) == Channels.Unreliable
                ? ResolveUnreliablePacketMaxBytes()
                : ReliablePacketMaxBytes;
        }

        public override int GetBatchThreshold(int channelId = Channels.Reliable)
        {
            return NormalizeChannel(channelId) == Channels.Unreliable
                ? ResolveUnreliablePacketMaxBytes()
                : ReliableBatchThresholdBytes;
        }

        public override void ClientEarlyUpdate()
        {
            if (NetworkClient.activeHost)
            {
                return;
            }

            TryBindRuntime();
            ObserveRuntimeConnectionState();
            ProcessQueuedMessages(forServer: false, "ClientEarlyUpdate->ProcessQueuedMessages");
            CheckClientPeerSilence();
        }

        public override void ServerEarlyUpdate()
        {
            TryBindRuntime();
            ObserveRuntimeConnectionState();
            ProcessQueuedMessages(forServer: true, "ServerEarlyUpdate->ProcessQueuedMessages");
            CheckServerPeerSilence();
        }

        public override void ClientLateUpdate()
        {
            const string path = "ClientLateUpdate";
            if (NetworkClient.activeHost)
            {
                return;
            }

            if (ClientConnected() || string.IsNullOrWhiteSpace(pendingClientAddress))
            {
                return;
            }

            pendingClientTargetPlayerId = ResolveServerPlayerId(pendingClientAddress!);
            if (string.IsNullOrWhiteSpace(pendingClientTargetPlayerId))
            {
                float pendingNow = Now;
                if (pendingNow >= nextSuppressedConnectLogAt)
                {
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"waiting reason=target_player_unresolved pendingAddress={FormatValue(pendingClientAddress)}");
                    nextSuppressedConnectLogAt = pendingNow + SuppressedLogIntervalSeconds;
                }

                return;
            }

            float now = Now;
            if (now >= connectDeadlineAt)
            {
                IGPLog.Error(
                    "mirror-transport",
                    path,
                    $"timeout target={pendingClientTargetPlayerId} timeoutSeconds={connectTimeoutSeconds:F2}");
                OnClientError?.Invoke(
                    TransportError.Timeout,
                    $"Timed out connecting to hosted player `{pendingClientTargetPlayerId}`.");
                CompleteClientDisconnect(sendDisconnectPacket: false, AppendPath(path, "CompleteClientDisconnect"));
                return;
            }

            if (now < nextConnectAttemptAt)
            {
                if (now >= nextSuppressedConnectLogAt)
                {
                    float nextAttemptIn = Math.Max(0f, nextConnectAttemptAt - now);
                    IGPLog.Debug(
                        "mirror-transport",
                        path,
                        $"suppressed reason=retry_interval target={pendingClientTargetPlayerId} " +
                        $"retryIntervalSeconds={connectRetryIntervalSeconds:F2} nextAttemptIn={nextAttemptIn:F2}s");
                    nextSuppressedConnectLogAt = now + SuppressedLogIntervalSeconds;
                }

                return;
            }

            pendingClientConnectAttemptId ??= Guid.NewGuid();
            var sendResult = TrySendControl(
                pendingClientTargetPlayerId!,
                ConnectRequestMessageType,
                BuildConnectRequestPayload(pendingClientConnectAttemptId.Value, GetLocalConnectCapabilities()),
                AppendPath(path, "TrySendControl"));
            nextConnectAttemptAt = now + connectRetryIntervalSeconds;

            if (sendResult == IGPNetworkResult.kSuccess)
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"connect_request_sent target={pendingClientTargetPlayerId} " +
                    $"attemptId={pendingClientConnectAttemptId.Value:N} " +
                    $"deadlineRemaining={(connectDeadlineAt - now):F2}s");
                return;
            }

            IGPLog.Warning(
                "mirror-transport",
                path,
                $"connect_request_failed target={pendingClientTargetPlayerId} " +
                $"attemptId={pendingClientConnectAttemptId.Value:N} result={sendResult}");
        }

        public override void Shutdown()
        {
            const string path = "Shutdown";
            IGPLog.Debug(
                "mirror-transport",
                path,
                "called");
            CompleteClientDisconnect(sendDisconnectPacket: true, AppendPath(path, "CompleteClientDisconnect"));
            ServerStop();
            runtimeManager?.KcpClient?.Tick();
            ClearQueuedMessages();
            UnbindRuntime(AppendPath(path, "UnbindRuntime"));
        }

        public override void OnApplicationQuit()
        {
            IGPLog.Debug(
                "mirror-transport",
                "OnApplicationQuit",
                "called");
            Shutdown();
            base.OnApplicationQuit();
        }

        private void ProcessQueuedMessages(bool forServer, string path)
        {
            if (forServer && !serverActive)
            {
                int pendingMessages;
                int pendingBytes;
                lock (queueLock)
                {
                    pendingMessages = messageQueue.Count;
                    pendingBytes = queuedMessageBytes;
                }

                if (pendingMessages > 0 && Now >= nextQueueDepthWarningAt)
                {
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"not_processing reason=server_not_active action=observe-only pending={pendingMessages} " +
                        $"pendingKB={(pendingBytes / 1024.0):F1}");
                    nextQueueDepthWarningAt = Now + IGPNetworkAnomalyLogLimiter.DefaultRepeatIntervalSeconds;
                }

                return;
            }

            List<QueuedMessage>? drained = null;
            int drainedBytes = 0;
            float maxDelayMs = 0f;
            int pendingAfterDrain;
            lock (queueLock)
            {
                if (messageQueue.Count == 0)
                {
                    return;
                }

                drained = new List<QueuedMessage>(messageQueue.Count);
                while (messageQueue.Count > 0)
                {
                    var item = messageQueue.Dequeue();
                    queuedMessageBytes -= item.Payload?.Length ?? 0;
                    drainedBytes += item.Payload?.Length ?? 0;
                    maxDelayMs = Math.Max(maxDelayMs, Math.Max(0f, Now - item.EnqueuedAt) * 1000f);
                    drained.Add(item);
                }

                pendingAfterDrain = messageQueue.Count;
            }

            IGPLog.Debug(
                "mirror-transport",
                path,
                $"drained target={(forServer ? "server" : "client")} count={drained.Count} bytes={drainedBytes} " +
                $"pendingAfterDrain={pendingAfterDrain} maxDelayMs={maxDelayMs:F1}");
            foreach (var message in drained)
            {
                if (forServer)
                {
                    HandleServerMessage(message, AppendPath(path, "HandleServerMessage"));
                }
                else
                {
                    HandleClientMessage(message, AppendPath(path, "HandleClientMessage"));
                }
            }
        }

        private void HandleServerMessage(QueuedMessage message, string path)
        {
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"dispatch remote={FormatValue(message.RemotePlayerId)} " +
                $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
            switch (message.MessageType)
            {
                case ConnectRequestMessageType:
                    if (!CanProcessControlMessage(AppendPath(path, "CanProcessControlMessage")))
                    {
                        return;
                    }

                    HandleServerConnectRequest(message, AppendPath(path, "HandleServerConnectRequest"));
                    break;
                case DisconnectMessageType:
                    if (!CanProcessControlMessage(AppendPath(path, "CanProcessControlMessage")))
                    {
                        return;
                    }

                    HandleServerDisconnect(message, AppendPath(path, "HandleServerDisconnect"));
                    break;
                case MirrorReliableChannelMessageType:
                case MirrorUnreliableChannelMessageType:
                case MirrorCompressedReliableChannelMessageType:
                case MirrorCompressedUnreliableChannelMessageType:
                    if (!TryBindRuntime(AppendPath(path, "TryBindRuntime"), logFailure: true) ||
                        runtimeManager?.Network == null)
                    {
                        IGPLog.Warning(
                            "mirror-transport",
                            path,
                            $"ignored reason=runtime_unavailable remote={FormatValue(message.RemotePlayerId)} " +
                            $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
                        return;
                    }

                    if (!playerIdToConnectionId.TryGetValue(message.RemotePlayerId, out var dataConnectionId))
                    {
                        IGPLog.Warning(
                            "mirror-transport",
                            path,
                            $"ignored reason=unknown_player_connection remote={FormatValue(message.RemotePlayerId)} " +
                            $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
                        return;
                    }

                    if (!TryPrepareIncomingMirrorPayload(
                            message,
                            dataConnectionId,
                            AppendPath(path, "TryPrepareIncomingMirrorPayload"),
                            out var serverPayload,
                            out var serverChannel))
                    {
                        return;
                    }

                    serverLastInboundByPlayerId[message.RemotePlayerId] = Now;
                    AcceptSessionRequest(message.RemotePlayerId, AppendPath(path, "AcceptSessionRequest"));
                    OnServerDataReceived?.Invoke(
                        dataConnectionId,
                        new ArraySegment<byte>(serverPayload),
                        serverChannel);
                    ObserveLargePayload(
                        "receive",
                        message.MessageType,
                        serverPayload.Length,
                        message.Payload.Length,
                        message.RemotePlayerId);
                    IGPLogLevel serverReceiveLogLevel = ResolvePayloadReceiveLogLevel(
                        message.MessageType,
                        serverPayload.Length,
                        message.Payload.Length);
                    if (ShouldLog(serverReceiveLogLevel))
                    {
                        LogAtLevel(
                            serverReceiveLogLevel,
                            path,
                            FormatPayloadReceiveLogMessage(
                                message.RemotePlayerId,
                                dataConnectionId,
                                message.MessageType,
                                serverChannel,
                                serverPayload,
                                message.Payload.Length));
                    }

                    break;
                default:
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"ignored reason=unknown_message_type remote={FormatValue(message.RemotePlayerId)} " +
                        $"messageType={message.MessageType} bytes={message.Payload.Length}");
                    break;
            }
        }

        private bool CanProcessControlMessage(string path)
        {
            if (!TryBindRuntime(AppendPath(path, "TryBindRuntime"), logFailure: true) ||
                runtimeManager?.Network == null)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    "rejected reason=runtime_unavailable");
                return false;
            }

            return true;
        }

        private void HandleClientMessage(QueuedMessage message, string path)
        {
            if (!IsMessageFromCurrentServer(message.RemotePlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"ignored reason=not_current_server remote={FormatValue(message.RemotePlayerId)} " +
                    $"connectedServer={FormatValue(connectedServerPlayerId)} " +
                    $"pendingServer={FormatValue(pendingClientTargetPlayerId)} " +
                    $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
                return;
            }

            IGPLog.Debug(
                "mirror-transport",
                path,
                $"dispatch remote={FormatValue(message.RemotePlayerId)} " +
                $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
            switch (message.MessageType)
            {
                case ConnectAcceptMessageType:
                    HandleClientConnectAccept(message, AppendPath(path, "HandleClientConnectAccept"));
                    break;
                case DisconnectMessageType:
                    HandleClientDisconnect(message, AppendPath(path, "HandleClientDisconnect"));
                    break;
                case MirrorReliableChannelMessageType:
                case MirrorUnreliableChannelMessageType:
                case MirrorCompressedReliableChannelMessageType:
                case MirrorCompressedUnreliableChannelMessageType:
                    if (!ClientConnected())
                    {
                        IGPLog.Warning(
                            "mirror-transport",
                            path,
                            $"ignored reason=client_not_connected remote={FormatValue(message.RemotePlayerId)} " +
                            $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length}");
                        return;
                    }

                    if (!TryPrepareIncomingMirrorPayload(
                            message,
                            connectionId: null,
                            AppendPath(path, "TryPrepareIncomingMirrorPayload"),
                            out var clientPayload,
                            out var clientChannel))
                    {
                        return;
                    }

                    clientLastInboundFromHostAt = Now;
                    OnClientDataReceived?.Invoke(
                        new ArraySegment<byte>(clientPayload),
                        clientChannel);
                    ObserveLargePayload(
                        "receive",
                        message.MessageType,
                        clientPayload.Length,
                        message.Payload.Length,
                        message.RemotePlayerId);
                    IGPLogLevel clientReceiveLogLevel = ResolvePayloadReceiveLogLevel(
                        message.MessageType,
                        clientPayload.Length,
                        message.Payload.Length);
                    if (ShouldLog(clientReceiveLogLevel))
                    {
                        LogAtLevel(
                            clientReceiveLogLevel,
                            path,
                            FormatPayloadReceiveLogMessage(
                                message.RemotePlayerId,
                                connectionId: null,
                                message.MessageType,
                                clientChannel,
                                clientPayload,
                                message.Payload.Length));
                    }

                    break;
                default:
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"ignored reason=unknown_message_type remote={FormatValue(message.RemotePlayerId)} " +
                        $"messageType={message.MessageType} bytes={message.Payload.Length}");
                    break;
            }
        }

        private bool IsMessageFromCurrentServer(string remotePlayerId)
        {
            if (!string.IsNullOrWhiteSpace(connectedServerPlayerId))
            {
                return string.Equals(connectedServerPlayerId, remotePlayerId, StringComparison.Ordinal);
            }

            if (!string.IsNullOrWhiteSpace(pendingClientTargetPlayerId))
            {
                return string.Equals(pendingClientTargetPlayerId, remotePlayerId, StringComparison.Ordinal);
            }

            return false;
        }

        private void HandleServerConnectRequest(QueuedMessage message, string path)
        {
            float now = Now;
            var connectRequest = ReadConnectRequestPayload(message.Payload);
            Guid? connectAttemptId = connectRequest.AttemptId;
            bool remoteSupportsCompression = HasCapability(
                connectRequest.Capabilities,
                ConnectCapabilityPayloadCompression);
            bool negotiatedCompression = enablePayloadCompression && remoteSupportsCompression;
            IGPLog.Info(
                "mirror-transport",
                path,
                $"called remote={FormatValue(message.RemotePlayerId)} " +
                $"attemptId={FormatAttemptId(connectAttemptId)} bytes={message.Payload.Length} " +
                $"remoteCompression={remoteSupportsCompression} negotiatedCompression={negotiatedCompression}");
            AcceptSessionRequest(message.RemotePlayerId, AppendPath(path, "AcceptSessionRequest"));
            serverLastInboundByPlayerId[message.RemotePlayerId] = now;
            bool isNewConnection =
                !playerIdToConnectionId.TryGetValue(message.RemotePlayerId, out var connectionId);

            if (isNewConnection)
            {
                connectionId = nextConnectionId++;
                playerIdToConnectionId[message.RemotePlayerId] = connectionId;
                connectionIdToPlayerId[connectionId] = message.RemotePlayerId;

                NotifyServerConnected(connectionId, message.RemotePlayerId, AppendPath(path, "NotifyServerConnected"));
            }

            serverPayloadCompressionByPlayerId[message.RemotePlayerId] = negotiatedCompression;
            TrySendControl(
                message.RemotePlayerId,
                ConnectAcceptMessageType,
                BuildConnectAcceptPayload(
                    connectionId,
                    connectAttemptId,
                    negotiatedCompression ? ConnectCapabilityPayloadCompression : 0u),
                AppendPath(path, "TrySendControl"));
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"connect_accept_sent remote={message.RemotePlayerId} " +
                $"connectionId={connectionId} attemptId={FormatAttemptId(connectAttemptId)} " +
                $"isNewConnection={isNewConnection} compression={negotiatedCompression}");
        }

        private void HandleServerDisconnect(QueuedMessage message, string path)
        {
            if (playerIdToConnectionId.TryGetValue(message.RemotePlayerId, out var disconnectedConnectionId))
            {
                IGPLog.Info(
                    "mirror-transport",
                    path,
                    $"called remote={message.RemotePlayerId} connectionId={disconnectedConnectionId}");
                RemoveServerConnection(
                    disconnectedConnectionId,
                    message.RemotePlayerId,
                    notifyMirror: true,
                    AppendPath(path, "RemoveServerConnection"));
                return;
            }

            IGPLog.Warning(
                "mirror-transport",
                path,
                $"ignored reason=unknown_player_connection remote={FormatValue(message.RemotePlayerId)}");
        }

        private void HandleClientConnectAccept(QueuedMessage message, string path)
        {
            var connectAccept = ReadConnectAcceptPayload(message.Payload);
            int acceptedConnectionId = connectAccept.ConnectionId;
            Guid? acceptedAttemptId = connectAccept.AttemptId;
            bool acceptedCompression = HasCapability(
                connectAccept.Capabilities,
                ConnectCapabilityPayloadCompression);
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"called server={FormatValue(message.RemotePlayerId)} connectionId={acceptedConnectionId} " +
                $"attemptId={FormatAttemptId(acceptedAttemptId)} bytes={message.Payload.Length} " +
                $"compression={acceptedCompression}");

            if (ClientConnected())
            {
                if (IsDuplicateConnectedAccept(message.RemotePlayerId, acceptedConnectionId, acceptedAttemptId))
                {
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"ignored reason=duplicate_connect_accept server={FormatValue(message.RemotePlayerId)} " +
                        $"connectionId={acceptedConnectionId} attemptId={FormatAttemptId(acceptedAttemptId)}");
                    return;
                }

                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"ignored reason=already_connected server={message.RemotePlayerId} " +
                    $"connectionId={acceptedConnectionId} " +
                    $"attemptId={FormatAttemptId(acceptedAttemptId)}");
                return;
            }

            if (pendingClientConnectAttemptId.HasValue &&
                acceptedAttemptId.HasValue &&
                pendingClientConnectAttemptId.Value != acceptedAttemptId.Value)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"ignored reason=stale_connect_accept server={message.RemotePlayerId} " +
                    $"connectionId={acceptedConnectionId} expectedAttemptId={pendingClientConnectAttemptId.Value:N} " +
                    $"actualAttemptId={acceptedAttemptId.Value:N}");
                return;
            }

            connectedServerPlayerId = message.RemotePlayerId;
            connectedClientConnectAttemptId = acceptedAttemptId ?? pendingClientConnectAttemptId;
            clientPayloadCompressionEnabled = enablePayloadCompression && acceptedCompression;
            clientLastInboundFromHostAt = Now;
            pendingClientAddress = null;
            pendingClientTargetPlayerId = null;
            pendingClientConnectAttemptId = null;
            clientConnectionId = acceptedConnectionId;

            AcceptSessionRequest(message.RemotePlayerId, AppendPath(path, "AcceptSessionRequest"));
            OnClientConnected?.Invoke();
            IGPLog.Info(
                "mirror-transport",
                path,
                $"connected server={message.RemotePlayerId} connectionId={acceptedConnectionId} " +
                $"attemptId={FormatAttemptId(connectedClientConnectAttemptId)} " +
                $"compression={clientPayloadCompressionEnabled}");
        }

        private void HandleClientDisconnect(QueuedMessage message, string path)
        {
            IGPLog.Info(
                "mirror-transport",
                path,
                $"called server={FormatValue(message.RemotePlayerId)} bytes={message.Payload.Length}");
            CompleteClientDisconnect(sendDisconnectPacket: false, AppendPath(path, "CompleteClientDisconnect"));
        }

        private void CompleteClientDisconnect(bool sendDisconnectPacket, string path)
        {
            var remotePlayerId = connectedServerPlayerId ?? pendingClientTargetPlayerId;
            var hadState =
                !string.IsNullOrWhiteSpace(remotePlayerId) || !string.IsNullOrWhiteSpace(pendingClientAddress);
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"called sendDisconnectPacket={sendDisconnectPacket} hadState={hadState} " +
                $"remote={FormatValue(remotePlayerId)} pendingAddress={FormatValue(pendingClientAddress)}");

            if (sendDisconnectPacket && !string.IsNullOrWhiteSpace(remotePlayerId))
            {
                TrySendControl(
                    remotePlayerId!,
                    DisconnectMessageType,
                    new byte[] { 1 },
                    AppendPath(path, "TrySendControl"));
            }
            else if (sendDisconnectPacket)
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    "disconnect_packet_skipped reason=no_remote_player");
            }

            pendingClientAddress = null;
            pendingClientTargetPlayerId = null;
            pendingClientConnectAttemptId = null;
            connectedServerPlayerId = null;
            connectedClientConnectAttemptId = null;
            clientPayloadCompressionEnabled = false;
            clientConnectionId = 0;
            nextConnectAttemptAt = 0f;
            connectDeadlineAt = 0f;
            nextSuppressedConnectLogAt = 0f;
            clientLastInboundFromHostAt = 0f;

            if (hadState)
            {
                OnClientDisconnected?.Invoke();
                IGPLog.Info(
                    "mirror-transport",
                    path,
                    "client_disconnected_notified");
            }
        }

        private void RemoveServerConnection(int connectionId, string remotePlayerId, bool notifyMirror, string path)
        {
            playerIdToConnectionId.Remove(remotePlayerId);
            connectionIdToPlayerId.Remove(connectionId);
            serverLastInboundByPlayerId.Remove(remotePlayerId);
            serverPayloadCompressionByPlayerId.Remove(remotePlayerId);
            IGPLog.Debug(
                "mirror-transport",
                path,
                $"removed connectionId={connectionId} remote={FormatValue(remotePlayerId)} notifyMirror={notifyMirror}");

            if (notifyMirror)
            {
                OnServerDisconnected?.Invoke(connectionId);
                IGPLog.Info(
                    "mirror-transport",
                    path,
                    $"server_disconnected_notified connectionId={connectionId}");
            }
        }

        private void NotifyServerConnected(int connectionId, string remotePlayerId, string path)
        {
#if IGP_MIRROR_HAS_SERVER_CONNECTED_WITH_ADDRESS
            OnServerConnectedWithAddress?.Invoke(connectionId, remotePlayerId);
#else
#pragma warning disable CS0618
            OnServerConnected?.Invoke(connectionId);
#pragma warning restore CS0618
#endif
            IGPLog.Info(
                "mirror-transport",
                path,
                $"server_connected_notified connectionId={connectionId} remote={FormatValue(remotePlayerId)}");
        }

        private static float Now => Time.unscaledTime;

        private void AcceptSessionRequest(string remotePlayerId, string path)
        {
            if (!TryBindRuntime(AppendPath(path, "TryBindRuntime"), logFailure: true) ||
                runtimeManager?.Network == null)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"skipped reason=runtime_unavailable remote={FormatValue(remotePlayerId)}");
                return;
            }

            var result = runtimeManager.Network.AcceptSessionRequest(runtimeManager.PlayerId, remotePlayerId);
            LogAtLevel(
                result == IGPNetworkResult.kSuccess ? IGPLogLevel.Debug : IGPLogLevel.Warning,
                path,
                $"accepted remote={FormatValue(remotePlayerId)} result={result}");
        }

        private IGPNetworkResult TrySendPayload(string remotePlayerId, byte[] payload, int channelId, string path)
        {
            var messageType = channelId == Channels.Unreliable
                ? MirrorUnreliableChannelMessageType
                : MirrorReliableChannelMessageType;
            var wirePayload = payload;
            var wireMessageType = messageType;
            var sendDiagnostics = PayloadSendDiagnostics.NotAttempted(payload.Length);

            if (ShouldCompressPayloadForPeer(remotePlayerId, channelId))
            {
                bool shouldLogDebug = ShouldLog(IGPLogLevel.Debug);
                bool compressed = IGPMirrorPayloadCompression.TryCompress(
                    payload,
                    CompressionThresholdBytes,
                    MinCompressionRatio,
                    out var compressedPayload,
                    out var compressionDiagnostics,
                    includePayloadProfile: shouldLogDebug);
                sendDiagnostics = new PayloadSendDiagnostics(
                    payload.Length,
                    compressionAttempted: true,
                    compressionAccepted: compressed,
                    compressionDiagnostics);
                if (compressed)
                {
                    wirePayload = compressedPayload;
                    wireMessageType = channelId == Channels.Unreliable
                        ? MirrorCompressedUnreliableChannelMessageType
                        : MirrorCompressedReliableChannelMessageType;
                }
            }

            return channelId == Channels.Unreliable
                ? TrySendUnreliable(
                    remotePlayerId,
                    wireMessageType,
                    wirePayload,
                    AppendPath(path, "TrySendUnreliable"),
                    sendDiagnostics)
                : TrySendControl(
                    remotePlayerId,
                    wireMessageType,
                    wirePayload,
                    AppendPath(path, "TrySendControl"),
                    sendDiagnostics);
        }

        private IGPNetworkResult TrySendControl(
            string remotePlayerId,
            uint messageType,
            byte[] payload,
            string path,
            PayloadSendDiagnostics sendDiagnostics = default)
        {
            sendDiagnostics = sendDiagnostics.EnsureOriginalBytes(payload.Length);
            if (string.IsNullOrWhiteSpace(remotePlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"failed reason=empty_remote message={DescribeMessageType(messageType)} bytes={payload.Length}");
                return IGPNetworkResult.kErrorInvalidState;
            }

            if (!TryBindRuntime(AppendPath(path, "TryBindRuntime"), logFailure: true) ||
                runtimeManager?.Network == null)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"failed reason=runtime_unavailable target={FormatValue(remotePlayerId)} " +
                    $"message={DescribeMessageType(messageType)} bytes={payload.Length}");
                return IGPNetworkResult.kErrorInvalidState;
            }

            if (!runtimeManager.IsKcpConnected)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"failed reason=kcp_not_connected target={FormatValue(remotePlayerId)} " +
                    $"message={DescribeMessageType(messageType)} bytes={payload.Length}");
                return IGPNetworkResult.kErrorNetworkError;
            }

            var safePayload = payload.Length == 0 ? new byte[] { 0 } : payload;
            var result = runtimeManager.Network.SendReliableData(
                runtimeManager.PlayerId,
                remotePlayerId,
                safePayload,
                (uint)safePayload.Length,
                messageType);
            if (result == IGPNetworkResult.kSuccess)
            {
                ObserveLargePayload(
                    "send",
                    messageType,
                    sendDiagnostics.OriginalBytes,
                    safePayload.Length,
                    remotePlayerId);
            }
            IGPLogLevel messageLevel = ResolvePayloadSendLogLevel(result, messageType, sendDiagnostics, safePayload.Length);
            if (ShouldLog(messageLevel))
            {
                LogAtLevel(
                    messageLevel,
                    path,
                    FormatPayloadSendLogMessage(
                        runtimeManager.PlayerId,
                        remotePlayerId,
                        messageType,
                        "kcp",
                        safePayload,
                        result,
                        sendDiagnostics));
            }

            return result;
        }

        private IGPNetworkResult TrySendUnreliable(
            string remotePlayerId,
            uint messageType,
            byte[] payload,
            string path,
            PayloadSendDiagnostics sendDiagnostics = default)
        {
            sendDiagnostics = sendDiagnostics.EnsureOriginalBytes(payload.Length);
            if (string.IsNullOrWhiteSpace(remotePlayerId))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"failed reason=empty_remote message={DescribeMessageType(messageType)} bytes={payload.Length}");
                return IGPNetworkResult.kErrorInvalidState;
            }

            if (!TryBindRuntime(AppendPath(path, "TryBindRuntime"), logFailure: true) ||
                runtimeManager?.Network == null)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"failed reason=runtime_unavailable target={FormatValue(remotePlayerId)} " +
                    $"message={DescribeMessageType(messageType)} bytes={payload.Length}");
                return IGPNetworkResult.kErrorInvalidState;
            }

            bool useRawUdp = useRawUdpUnreliableLane && runtimeManager.IsUnreliableUdpConnected;
            if (useRawUdp)
            {
                rawUdpFallbackWarningEmitted = false;
            }
            else if (useRawUdpUnreliableLane && !rawUdpFallbackWarningEmitted)
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"fallback reason=udp_unreliable_not_ready logicalChannel=unreliable effectiveTransport=kcp " +
                    $"target={FormatValue(remotePlayerId)} " +
                    $"message={DescribeMessageType(messageType)} bytes={payload.Length}");
                rawUdpFallbackWarningEmitted = true;
            }
            else if (!useRawUdpUnreliableLane)
            {
                rawUdpFallbackWarningEmitted = false;
            }

            var safePayload = payload.Length == 0 ? new byte[] { 0 } : payload;
            IGPNetworkResult result;
            string effectiveTransport;
            if (useRawUdp)
            {
                result = runtimeManager.Network.SendUnreliableData(
                    runtimeManager.PlayerId,
                    remotePlayerId,
                    safePayload,
                    (uint)safePayload.Length,
                    messageType);
                effectiveTransport = "raw-udp";
            }
            else
            {
                if (!runtimeManager.IsKcpConnected)
                {
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"failed reason=kcp_not_connected target={FormatValue(remotePlayerId)} " +
                        $"message={DescribeMessageType(messageType)} bytes={payload.Length}");
                    return IGPNetworkResult.kErrorNetworkError;
                }

                result = runtimeManager.Network.SendData(
                    runtimeManager.PlayerId,
                    remotePlayerId,
                    safePayload,
                    (uint)safePayload.Length,
                    messageType);
                effectiveTransport = "kcp";
            }
            if (result == IGPNetworkResult.kSuccess)
            {
                ObserveLargePayload(
                    "send",
                    messageType,
                    sendDiagnostics.OriginalBytes,
                    safePayload.Length,
                    remotePlayerId);
            }
            IGPLogLevel messageLevel = ResolvePayloadSendLogLevel(result, messageType, sendDiagnostics, safePayload.Length);
            if (ShouldLog(messageLevel))
            {
                LogAtLevel(
                    messageLevel,
                    path,
                    FormatPayloadSendLogMessage(
                        runtimeManager.PlayerId,
                        remotePlayerId,
                        messageType,
                        effectiveTransport,
                        safePayload,
                        result,
                        sendDiagnostics));
            }

            return result;
        }

        private bool TryBindRuntime(string path = "TryBindRuntime", bool logFailure = false)
        {
            if (runtimeBound && runtimeManager != null && runtimeManager.Network != null)
            {
                return true;
            }

            runtimeManager ??= FindAnyObjectByType<IGPRuntimeManager>();
            if (runtimeManager?.Network == null)
            {
                if (logFailure)
                {
                    IGPLog.Warning(
                        "mirror-transport",
                        path,
                        $"failed reason=runtime_or_network_missing runtimeManagerAssigned={runtimeManager != null}");
                }

                return false;
            }

            if (!runtimeBound)
            {
                previousRetainIncomingPacketsForPolling = runtimeManager.Network.RetainIncomingPacketsForPolling;
                runtimeManager.Network.RetainIncomingPacketsForPolling = false;
                runtimeManager.Network.OnDataReceived.AddListener(HandleNetworkData);
                runtimeManager.Network.OnPeerActivity.AddListener(HandlePeerActivity);
                runtimeManager.HostedConnectionStateChanged += HandleHostedConnectionStateChanged;
                runtimeBound = true;
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"bound playerId={FormatValue(runtimeManager.PlayerId)} eventOnlyReceive=true");
            }

            return true;
        }

        private void UnbindRuntime(string path)
        {
            if (!runtimeBound || runtimeManager == null)
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"skipped runtimeBound={runtimeBound} runtimeAvailable={runtimeManager?.Network != null}");
                runtimeBound = false;
                return;
            }

            if (runtimeManager.Network != null)
            {
                runtimeManager.Network.OnDataReceived.RemoveListener(HandleNetworkData);
                runtimeManager.Network.OnPeerActivity.RemoveListener(HandlePeerActivity);
            }
            runtimeManager.HostedConnectionStateChanged -= HandleHostedConnectionStateChanged;
            if (runtimeManager.Network != null && previousRetainIncomingPacketsForPolling.HasValue)
            {
                runtimeManager.Network.RetainIncomingPacketsForPolling = previousRetainIncomingPacketsForPolling.Value;
            }
            previousRetainIncomingPacketsForPolling = null;
            runtimeBound = false;
            IGPLog.Debug(
                "mirror-transport",
                path,
                "unbound");
        }

        private void HandleHostedConnectionStateChanged(IGPHostedConnectionState state)
        {
            if (state != IGPHostedConnectionState.ConnectionFailed)
            {
                hostedConnectionFailureHandled = false;
                return;
            }

            bool hasClientState =
                !string.IsNullOrWhiteSpace(connectedServerPlayerId) ||
                !string.IsNullOrWhiteSpace(pendingClientTargetPlayerId) ||
                !string.IsNullOrWhiteSpace(pendingClientAddress);
            bool hasServerState = serverActive || connectionIdToPlayerId.Count > 0;
            bool hasQueuedMessages;
            lock (queueLock)
            {
                hasQueuedMessages = messageQueue.Count > 0;
            }

            if (!hasClientState && !hasServerState && !hasQueuedMessages)
            {
                return;
            }

            const string path = "HandleHostedConnectionStateChanged";
            if (!hostedConnectionFailureHandled)
            {
                hostedConnectionFailureHandled = true;
                IGPLog.Error(
                    "mirror-transport",
                    path,
                    "disconnecting reason=hosted_connection_failed");
            }

            CompleteClientDisconnect(
                sendDisconnectPacket: false,
                AppendPath(path, "CompleteClientDisconnect"));

            foreach (var entry in new List<KeyValuePair<int, string>>(connectionIdToPlayerId))
            {
                RemoveServerConnection(
                    entry.Key,
                    entry.Value,
                    notifyMirror: true,
                    AppendPath(path, "RemoveServerConnection"));
            }

            serverActive = false;
            ClearQueuedMessages();
        }

        private void ObserveRuntimeConnectionState()
        {
            if (runtimeManager != null)
            {
                HandleHostedConnectionStateChanged(runtimeManager.CurrentHostedConnectionState);
            }
        }

        private void CheckClientPeerSilence()
        {
            if (!ClientConnected() || clientLastInboundFromHostAt <= 0f)
            {
                return;
            }

            float timeoutSeconds = PeerSilenceTimeoutSeconds;
            if (Now - clientLastInboundFromHostAt <= timeoutSeconds)
            {
                return;
            }

            string serverPlayerId = connectedServerPlayerId ?? string.Empty;
            IGPLog.Error(
                "mirror-transport",
                "CheckClientPeerSilence",
                $"disconnecting reason=host_inbound_silence timeoutSeconds={timeoutSeconds:F0} " +
                $"server={FormatValue(serverPlayerId)}");
            if (!string.IsNullOrWhiteSpace(serverPlayerId))
            {
                runtimeManager?.Network?.CloseSession(runtimeManager.PlayerId, serverPlayerId);
            }

            CompleteClientDisconnect(
                sendDisconnectPacket: false,
                "CheckClientPeerSilence->CompleteClientDisconnect");
        }

        private void CheckServerPeerSilence()
        {
            if (!serverActive || connectionIdToPlayerId.Count == 0)
            {
                return;
            }

            float now = Now;
            float timeoutSeconds = PeerSilenceTimeoutSeconds;
            foreach (var entry in new List<KeyValuePair<int, string>>(connectionIdToPlayerId))
            {
                if (!serverLastInboundByPlayerId.TryGetValue(entry.Value, out var lastInboundAt) ||
                    lastInboundAt <= 0f ||
                    now - lastInboundAt <= timeoutSeconds)
                {
                    continue;
                }

                IGPLog.Error(
                    "mirror-transport",
                    "CheckServerPeerSilence",
                    $"disconnecting reason=peer_inbound_silence timeoutSeconds={timeoutSeconds:F0} " +
                    $"connectionId={entry.Key} remote={FormatValue(entry.Value)}");
                runtimeManager?.Network?.CloseSession(runtimeManager.PlayerId, entry.Value);
                RemoveServerConnection(
                    entry.Key,
                    entry.Value,
                    notifyMirror: true,
                    "CheckServerPeerSilence->RemoveServerConnection");
            }
        }

        private void HandlePeerActivity(IGPPeerActivity activity)
        {
            const string path = "HandlePeerActivity";
            if (!IsTransportMessageType(activity.message_type))
            {
                return;
            }

            string remotePlayerId = activity.remote_peer.id;
            if (string.IsNullOrWhiteSpace(remotePlayerId))
            {
                return;
            }

            float now = Now;
            bool refreshed = false;
            if (serverActive && playerIdToConnectionId.ContainsKey(remotePlayerId))
            {
                serverLastInboundByPlayerId[remotePlayerId] = now;
                refreshed = true;
            }

            if (ClientConnected() && IsMessageFromCurrentServer(remotePlayerId))
            {
                clientLastInboundFromHostAt = now;
                refreshed = true;
            }

            if (!refreshed || !activity.is_reliable_chunk)
            {
                return;
            }

            IGPLog.Debug(
                "mirror-transport",
                path,
                $"refreshed reason=reliable_chunk_activity remote={FormatValue(remotePlayerId)} " +
                $"message={DescribeMessageType(activity.message_type)} " +
                $"channel={activity.transport_channel} " +
                $"chunk={activity.reliable_chunk_index + 1}/{activity.reliable_chunk_count}");
        }

        private void HandleNetworkData(IGPDataReceived data)
        {
            const string path = "HandleNetworkData";
            if (!IsTransportMessageType(data.message_type))
            {
                IGPLog.Warning(
                    "mirror-transport",
                    path,
                    $"ignored reason=non_transport_message remote={FormatValue(data.remote_peer.id)} " +
                    $"messageType={data.message_type} bytes={(data.data != null ? data.data.Length : 0)}");
                return;
            }

            var payload = data.data != null ? (byte[])data.data.Clone() : Array.Empty<byte>();
            if (ShouldLog(IGPLogLevel.Debug))
            {
                IGPLog.Debug(
                    "mirror-transport",
                    path,
                    $"recv remote={FormatValue(data.remote_peer.id)} " +
                    $"message={DescribeMessageType(data.message_type)} bytes={payload.Length} " +
                    $"logicalChannel={DescribeMessageChannel(data.message_type)}" +
                    $"{FormatPayloadDetail(payload)}");
            }

            lock (queueLock)
            {
                messageQueue.Enqueue(new QueuedMessage
                {
                    RemotePlayerId = data.remote_peer.id,
                    MessageType = data.message_type,
                    Payload = payload,
                    EnqueuedAt = Now,
                });
                queuedMessageBytes += payload.Length;
                WarnIfQueuedMessagesDeep();
            }
        }

        private void WarnIfQueuedMessagesDeep()
        {
            if ((messageQueue.Count <= MaxQueuedMessages && queuedMessageBytes <= MaxQueuedMessageBytes) ||
                Now < nextQueueDepthWarningAt)
            {
                return;
            }

            IGPLog.Warning(
                "mirror-transport",
                "HandleNetworkData->WarnIfQueuedMessagesDeep",
                $"inbound_queue_deep action=observe-only notDropping=true " +
                $"pending={messageQueue.Count} pendingKB={(queuedMessageBytes / 1024.0):F1} " +
                $"itemThreshold={MaxQueuedMessages} byteThresholdKB={(MaxQueuedMessageBytes / 1024.0):F0}");
            nextQueueDepthWarningAt = Now + IGPNetworkAnomalyLogLimiter.DefaultRepeatIntervalSeconds;
        }

        private void ClearQueuedMessages()
        {
            lock (queueLock)
            {
                if (messageQueue.Count > 0 || queuedMessageBytes > 0)
                {
                    IGPLog.Debug(
                        "mirror-transport",
                        "ClearQueuedMessages",
                        $"cleared pending={messageQueue.Count} bytes={queuedMessageBytes}");
                }

                messageQueue.Clear();
                queuedMessageBytes = 0;
                nextQueueDepthWarningAt = 0f;
            }

            anomalyLogLimiter.Reset();
        }

        private void ObserveLargePayload(
            string direction,
            uint messageType,
            int originalBytes,
            int wireBytes,
            string remotePlayerId)
        {
            if (!ShouldLog(IGPLogLevel.Warning))
            {
                anomalyLogLimiter.Reset();
                return;
            }

            if (!IsLargePayloadSummaryCandidate(messageType, originalBytes, wireBytes))
            {
                return;
            }

            anomalyLogLimiter.ObserveEvent(
                $"large-payload-{direction}",
                Now,
                () => $"direction={direction} remote={FormatValue(remotePlayerId)} " +
                      $"message={DescribeMessageType(messageType)} originalBytes={originalBytes} wireBytes={wireBytes} " +
                      $"thresholdBytes={IGPNetworkAnomalyThresholds.LargeReliablePayloadBytes} " +
                      $"fragmented={wireBytes > EstimatedKcpDataPlanePayloadMaxBytes}",
                message => IGPLog.Warning(
                    "mirror-transport",
                    "ObserveLargePayload",
                    message));
        }

        private static bool IsTransportMessageType(uint messageType)
        {
            return messageType == ConnectRequestMessageType ||
                   messageType == ConnectAcceptMessageType ||
                   messageType == DisconnectMessageType ||
                   messageType == MirrorReliableChannelMessageType ||
                   messageType == MirrorUnreliableChannelMessageType ||
                   messageType == MirrorCompressedReliableChannelMessageType ||
                   messageType == MirrorCompressedUnreliableChannelMessageType;
        }

        private static bool IsCompressedDataMessageType(uint messageType)
        {
            return messageType == MirrorCompressedReliableChannelMessageType ||
                   messageType == MirrorCompressedUnreliableChannelMessageType;
        }

        private static bool IsReliableDataPlaneMessageType(uint messageType)
        {
            return messageType == MirrorReliableChannelMessageType ||
                   messageType == MirrorCompressedReliableChannelMessageType;
        }

        private static bool IsDataPlaneMessageType(uint messageType)
        {
            return IsReliableDataPlaneMessageType(messageType) ||
                   messageType == MirrorUnreliableChannelMessageType ||
                   messageType == MirrorCompressedUnreliableChannelMessageType;
        }

        private static int GetMirrorChannel(uint messageType)
        {
            return messageType == MirrorUnreliableChannelMessageType ||
                   messageType == MirrorCompressedUnreliableChannelMessageType
                ? Channels.Unreliable
                : Channels.Reliable;
        }

        private bool IsDuplicateConnectedAccept(
            string serverPlayerId,
            int acceptedConnectionId,
            Guid? acceptedAttemptId)
        {
            if (!string.Equals(connectedServerPlayerId, serverPlayerId, StringComparison.Ordinal) ||
                clientConnectionId != acceptedConnectionId)
            {
                return false;
            }

            return !acceptedAttemptId.HasValue ||
                   !connectedClientConnectAttemptId.HasValue ||
                   acceptedAttemptId.Value == connectedClientConnectAttemptId.Value;
        }

        private bool ShouldCompressPayloadForPeer(string remotePlayerId, int channelId)
        {
            if (!enablePayloadCompression || channelId == Channels.Unreliable)
            {
                return false;
            }

            if (!string.IsNullOrWhiteSpace(connectedServerPlayerId) &&
                string.Equals(connectedServerPlayerId, remotePlayerId, StringComparison.Ordinal))
            {
                return clientPayloadCompressionEnabled;
            }

            return serverPayloadCompressionByPlayerId.TryGetValue(remotePlayerId, out var enabled) && enabled;
        }

        private bool TryPrepareIncomingMirrorPayload(
            QueuedMessage message,
            int? connectionId,
            string path,
            out byte[] payload,
            out int channel)
        {
            channel = GetMirrorChannel(message.MessageType);
            payload = message.Payload;
            if (!IsCompressedDataMessageType(message.MessageType))
            {
                return true;
            }

            try
            {
                int maxOriginalBytes = channel == Channels.Unreliable
                    ? ResolveUnreliablePacketMaxBytes()
                    : ReliablePacketMaxBytes;
                payload = IGPMirrorPayloadCompression.Decompress(message.Payload, maxOriginalBytes);
                if (ShouldLog(IGPLogLevel.Debug))
                {
                    IGPLog.Debug(
                        "mirror-transport",
                        path,
                        $"decompressed remote={FormatValue(message.RemotePlayerId)} " +
                        $"connectionId={(connectionId.HasValue ? connectionId.Value.ToString() : "-")} " +
                        $"channel={DescribeChannel(channel)} compressedBytes={message.Payload.Length} " +
                        $"originalBytes={payload.Length}");
                }

                return true;
            }
            catch (Exception ex)
            {
                IGPLog.Error(
                    "mirror-transport",
                    path,
                    $"failed reason=decompress_failed remote={FormatValue(message.RemotePlayerId)} " +
                    $"message={DescribeMessageType(message.MessageType)} bytes={message.Payload.Length} " +
                    $"error={ex.Message}");
                if (connectionId.HasValue)
                {
                    OnServerError?.Invoke(
                        connectionId.Value,
                        TransportError.InvalidReceive,
                        "Failed to decompress Mirror payload.");
                }
                else
                {
                    OnClientError?.Invoke(
                        TransportError.InvalidReceive,
                        "Failed to decompress Mirror payload.");
                }

                return false;
            }
        }

        private uint GetLocalConnectCapabilities()
        {
            return enablePayloadCompression ? ConnectCapabilityPayloadCompression : 0u;
        }

        private static bool HasCapability(uint capabilities, uint capability)
        {
            return (capabilities & capability) == capability;
        }

        private static byte[] BuildConnectRequestPayload(Guid connectAttemptId, uint capabilities)
        {
            var payload = new byte[ConnectAttemptIdBytes + ConnectCapabilitiesEnvelopeBytes];
            Buffer.BlockCopy(connectAttemptId.ToByteArray(), 0, payload, 0, ConnectAttemptIdBytes);
            WriteCapabilitiesEnvelope(payload, ConnectAttemptIdBytes, capabilities);
            return payload;
        }

        private static byte[] BuildConnectAcceptPayload(int connectionId, Guid? connectAttemptId, uint capabilities)
        {
            int attemptBytes = connectAttemptId.HasValue ? ConnectAttemptIdBytes : 0;
            var payload = new byte[
                ConnectAcceptConnectionIdBytes +
                attemptBytes +
                ConnectCapabilitiesEnvelopeBytes];
            Buffer.BlockCopy(BitConverter.GetBytes(connectionId), 0, payload, 0, ConnectAcceptConnectionIdBytes);
            if (connectAttemptId.HasValue)
            {
                Buffer.BlockCopy(
                    connectAttemptId.Value.ToByteArray(),
                    0,
                    payload,
                    ConnectAcceptConnectionIdBytes,
                    ConnectAttemptIdBytes);
            }

            WriteCapabilitiesEnvelope(
                payload,
                ConnectAcceptConnectionIdBytes + attemptBytes,
                capabilities);
            return payload;
        }

        private static ConnectRequestPayload ReadConnectRequestPayload(byte[] payload)
        {
            return new ConnectRequestPayload(
                TryReadGuid(payload, 0, out var connectAttemptId) ? connectAttemptId : (Guid?)null,
                TryReadCapabilitiesEnvelope(payload, ConnectAttemptIdBytes, out var capabilities)
                    ? capabilities
                    : 0u);
        }

        private static ConnectAcceptPayload ReadConnectAcceptPayload(byte[] payload)
        {
            int connectionId = payload.Length >= ConnectAcceptConnectionIdBytes
                ? BitConverter.ToInt32(payload, 0)
                : 1;
            Guid? connectAttemptId = TryReadGuid(payload, ConnectAcceptConnectionIdBytes, out var parsedAttemptId)
                ? parsedAttemptId
                : null;
            uint capabilities = 0u;
            if (TryReadCapabilitiesEnvelope(
                    payload,
                    ConnectAcceptConnectionIdBytes + ConnectAttemptIdBytes,
                    out var parsedCapabilities) ||
                TryReadCapabilitiesEnvelope(
                    payload,
                    ConnectAcceptConnectionIdBytes,
                    out parsedCapabilities))
            {
                capabilities = parsedCapabilities;
            }

            return new ConnectAcceptPayload(connectionId, connectAttemptId, capabilities);
        }

        private static void WriteCapabilitiesEnvelope(byte[] payload, int offset, uint capabilities)
        {
            payload[offset] = (byte)'I';
            payload[offset + 1] = (byte)'G';
            payload[offset + 2] = (byte)'P';
            payload[offset + 3] = (byte)'M';
            payload[offset + 4] = ConnectCapabilitiesVersion;
            WriteUInt32LittleEndian(payload, offset + 5, capabilities);
        }

        private static bool TryReadCapabilitiesEnvelope(byte[] payload, int offset, out uint capabilities)
        {
            capabilities = 0;
            if (payload.Length < offset + ConnectCapabilitiesEnvelopeBytes ||
                payload[offset] != (byte)'I' ||
                payload[offset + 1] != (byte)'G' ||
                payload[offset + 2] != (byte)'P' ||
                payload[offset + 3] != (byte)'M' ||
                payload[offset + 4] != ConnectCapabilitiesVersion)
            {
                return false;
            }

            capabilities = ReadUInt32LittleEndian(payload, offset + 5);
            return true;
        }

        private static bool TryReadGuid(byte[] payload, int offset, out Guid value)
        {
            value = Guid.Empty;
            if (payload.Length < offset + ConnectAttemptIdBytes)
            {
                return false;
            }

            var buffer = new byte[ConnectAttemptIdBytes];
            Buffer.BlockCopy(payload, offset, buffer, 0, ConnectAttemptIdBytes);
            value = new Guid(buffer);
            return true;
        }

        private static void WriteUInt32LittleEndian(byte[] payload, int offset, uint value)
        {
            payload[offset] = (byte)(value & 0xFF);
            payload[offset + 1] = (byte)((value >> 8) & 0xFF);
            payload[offset + 2] = (byte)((value >> 16) & 0xFF);
            payload[offset + 3] = (byte)((value >> 24) & 0xFF);
        }

        private static uint ReadUInt32LittleEndian(byte[] payload, int offset)
        {
            return payload[offset] |
                   ((uint)payload[offset + 1] << 8) |
                   ((uint)payload[offset + 2] << 16) |
                   ((uint)payload[offset + 3] << 24);
        }

        private static string FormatAttemptId(Guid? connectAttemptId)
        {
            return connectAttemptId.HasValue ? connectAttemptId.Value.ToString("N") : "none";
        }

        private string ResolveServerPlayerId(string address)
        {
            if (runtimeManager == null)
            {
                return string.Empty;
            }

            if (string.IsNullOrWhiteSpace(address) ||
                string.Equals(address, "host", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(address, "localhost", StringComparison.OrdinalIgnoreCase))
            {
                return runtimeManager.CurrentRoomData.hostId;
            }

            return address.Trim();
        }

        private string FormatPayloadDetail(byte[]? payload)
        {
            if (!IGPLog.ShouldLog(IGPLogLevel.Debug))
            {
                return string.Empty;
            }

            int byteCount = payload?.Length ?? 0;

            // Always log a checksum so identical resends share a stable fingerprint
            // (duplicate detection); additionally show the raw hex for small payloads
            // so the content is directly readable.
            string content = byteCount <= MessageLogHexPreviewMaxBytes
                ? $"hex={ToHex(payload, byteCount)}"
                : $"checksum={Fnv1a32(payload, byteCount):X8}";

            return $" {content}";
        }

        private string FormatPayloadSendLogMessage(
            string localPlayerId,
            string remotePlayerId,
            uint messageType,
            string effectiveTransport,
            byte[] safePayload,
            IGPNetworkResult result,
            PayloadSendDiagnostics sendDiagnostics)
        {
            int wireBytes = safePayload.Length;
            int originalBytes = sendDiagnostics.OriginalBytes;
            bool includeDebugDetail = ShouldLog(IGPLogLevel.Debug);
            bool mirrorReliableChannelData = IsReliableDataPlaneMessageType(messageType);
            bool fragmented = mirrorReliableChannelData && wireBytes > EstimatedKcpDataPlanePayloadMaxBytes;
            int estimatedFragments = mirrorReliableChannelData ? EstimateReliableFragments(wireBytes) : 1;
            string payloadDetail = includeDebugDetail ? FormatPayloadDetail(safePayload) : string.Empty;
            string eventName = IsDataPlaneMessageType(messageType) ? "payload-send" : "control-send";

            return $"event={eventName} direction=send local={FormatValue(localPlayerId)} " +
                   $"target={FormatValue(remotePlayerId)} message={DescribeMessageType(messageType)} " +
                   $"messageType={messageType} logicalChannel={DescribeMessageChannel(messageType)} " +
                   $"effectiveTransport={effectiveTransport} originalBytes={originalBytes} " +
                   $"wireBytes={wireBytes} bytes={wireBytes} compressed={IsCompressedDataMessageType(messageType)} " +
                   $"{FormatCompressionDecision(sendDiagnostics, includeDebugDetail)} " +
                   $"large={IsLargePayloadSummaryCandidate(messageType, originalBytes, wireBytes)} " +
                   $"fragmented={fragmented} estimatedFragments={estimatedFragments} result={result}{payloadDetail}";
        }

        private string FormatPayloadReceiveLogMessage(
            string remotePlayerId,
            int? connectionId,
            uint messageType,
            int channel,
            byte[] payload,
            int wireBytes)
        {
            int originalBytes = payload.Length;
            bool includeDebugDetail = ShouldLog(IGPLogLevel.Debug);
            bool mirrorReliableChannelData = IsReliableDataPlaneMessageType(messageType);
            bool fragmented = mirrorReliableChannelData && wireBytes > EstimatedKcpDataPlanePayloadMaxBytes;
            int estimatedFragments = mirrorReliableChannelData ? EstimateReliableFragments(wireBytes) : 1;
            string payloadDetail = includeDebugDetail ? FormatPayloadDetail(payload) : string.Empty;

            return $"event=payload-receive direction=receive remote={FormatValue(remotePlayerId)} " +
                   $"connectionId={(connectionId.HasValue ? connectionId.Value.ToString() : "none")} " +
                   $"message={DescribeMessageType(messageType)} messageType={messageType} " +
                   $"logicalChannel={DescribeChannel(channel)} originalBytes={originalBytes} wireBytes={wireBytes} " +
                   $"bytes={originalBytes} compressed={IsCompressedDataMessageType(messageType)} " +
                   $"large={IsLargePayloadSummaryCandidate(messageType, originalBytes, wireBytes)} " +
                   $"fragmented={fragmented} estimatedFragments={estimatedFragments}{payloadDetail}";
        }

        private string FormatCompressionDecision(
            PayloadSendDiagnostics sendDiagnostics,
            bool includeDebugDetail)
        {
            if (!sendDiagnostics.CompressionAttempted)
            {
                return "compressionDecision=not-attempted";
            }

            var diagnostics = sendDiagnostics.Compression;
            if (sendDiagnostics.CompressionAccepted)
            {
                return $"compressionDecision=accepted compressedBytes={diagnostics.CompressedBytes} " +
                       $"ratio={diagnostics.ActualCompressionRatio:F3} thresholdBytes={diagnostics.ThresholdBytes} " +
                       $"minRatio={diagnostics.MinCompressionRatio:F3}";
            }

            string payloadProfile = includeDebugDetail && !string.IsNullOrWhiteSpace(diagnostics.PayloadProfile)
                ? $" payloadProfile=({diagnostics.PayloadProfile})"
                : string.Empty;
            return $"compressionDecision=rejected compressionReason={FormatValue(diagnostics.Reason)} " +
                   $"candidateBytes={diagnostics.CompressedBytes} ratio={diagnostics.ActualCompressionRatio:F3} " +
                   $"thresholdBytes={diagnostics.ThresholdBytes} minRatio={diagnostics.MinCompressionRatio:F3}" +
                   payloadProfile;
        }

        private static IGPLogLevel ResolvePayloadSendLogLevel(
            IGPNetworkResult result,
            uint messageType,
            PayloadSendDiagnostics sendDiagnostics,
            int wireBytes)
        {
            if (result != IGPNetworkResult.kSuccess)
            {
                return IGPLogLevel.Warning;
            }

            if (IsConnectionLifecycleMessageType(messageType))
            {
                return IGPLogLevel.Info;
            }

            return IGPLogLevel.Debug;
        }

        private static IGPLogLevel ResolvePayloadReceiveLogLevel(
            uint messageType,
            int originalBytes,
            int wireBytes)
        {
            return IGPLogLevel.Debug;
        }

        private static bool IsLargePayloadSummaryCandidate(uint messageType, int originalBytes, int wireBytes)
        {
            return IsReliableDataPlaneMessageType(messageType) &&
                   (originalBytes > IGPNetworkAnomalyThresholds.LargeReliablePayloadBytes ||
                    wireBytes > EstimatedKcpDataPlanePayloadMaxBytes);
        }

        private static bool IsConnectionLifecycleMessageType(uint messageType)
        {
            return messageType == ConnectRequestMessageType ||
                   messageType == ConnectAcceptMessageType ||
                   messageType == DisconnectMessageType;
        }

        private static int EstimateReliableFragments(int wireBytes)
        {
            if (wireBytes <= 0)
            {
                return 1;
            }

            return Math.Max(1, (wireBytes + EstimatedReliableChunkMaxBytes - 1) / EstimatedReliableChunkMaxBytes);
        }

        private void LogConfigurationOnce(string path)
        {
            if (configurationLogged || !ShouldLog(IGPLogLevel.Info))
            {
                return;
            }

            configurationLogged = true;
            IGPLog.Info(
                "mirror-transport",
                path,
                $"event=configuration reliableBatchThresholdBytes={ReliableBatchThresholdBytes} " +
                $"reliablePacketMaxBytes={ReliablePacketMaxBytes} useRawUdpUnreliableLane={useRawUdpUnreliableLane} " +
                $"unreliablePacketMaxBytes={ResolveUnreliablePacketMaxBytes()}");
        }

        private bool ShouldLog(IGPLogLevel messageLevel)
        {
            return IGPLog.ShouldLog(messageLevel);
        }

        private static void LogAtLevel(IGPLogLevel level, string path, string message)
        {
            switch (level)
            {
                case IGPLogLevel.Error:
                    IGPLog.Error("mirror-transport", path, message);
                    break;
                case IGPLogLevel.Warning:
                    IGPLog.Warning("mirror-transport", path, message);
                    break;
                case IGPLogLevel.Info:
                    IGPLog.Info("mirror-transport", path, message);
                    break;
                case IGPLogLevel.Debug:
                    IGPLog.Debug("mirror-transport", path, message);
                    break;
            }
        }

        private static float NormalizePeerSilenceTimeout(float value) => Math.Max(1f, value);

        private static int NormalizeReliableBatchThreshold(int value)
        {
            return Math.Min(ReliablePacketMaxBytes, Math.Max(1, value));
        }

        private int ResolveUnreliablePacketMaxBytes()
        {
            if (!useRawUdpUnreliableLane)
            {
                return LegacyUnreliablePacketMaxBytes;
            }

            return Math.Max(1, runtimeManager?.UnreliableUdpPayloadMaxBytes ?? DefaultRawUdpUnreliablePacketMaxBytes);
        }

        private static string AppendPath(string path, string next)
        {
            return string.IsNullOrWhiteSpace(path) ? next : $"{path}->{next}";
        }

        private static string FormatValue(string? value)
        {
            return string.IsNullOrWhiteSpace(value) ? "none" : value;
        }

        private static uint Fnv1a32(byte[]? data, int count)
        {
            const uint offsetBasis = 2166136261;
            const uint prime = 16777619;
            uint hash = offsetBasis;
            if (data != null)
            {
                for (int i = 0; i < count; i++)
                {
                    hash ^= data[i];
                    hash *= prime;
                }
            }

            return hash;
        }

        private static string ToHex(byte[]? data, int count)
        {
            if (data == null || count == 0)
            {
                return "(empty)";
            }

            var builder = new StringBuilder(count * 2);
            for (int i = 0; i < count; i++)
            {
                builder.Append(data[i].ToString("x2"));
            }

            return builder.ToString();
        }

        private static string DescribeMessageType(uint messageType)
        {
            switch (messageType)
            {
                case ConnectRequestMessageType: return "ConnectRequest";
                case ConnectAcceptMessageType: return "ConnectAccept";
                case DisconnectMessageType: return "Disconnect";
                case MirrorReliableChannelMessageType: return "MirrorReliableChannelData";
                case MirrorUnreliableChannelMessageType: return "MirrorUnreliableChannelData";
                case MirrorCompressedReliableChannelMessageType: return "MirrorCompressedReliableChannelData";
                case MirrorCompressedUnreliableChannelMessageType: return "MirrorCompressedUnreliableChannelData";
                default: return $"Unknown({messageType})";
            }
        }

        private static string DescribeMessageChannel(uint messageType)
        {
            return IsDataPlaneMessageType(messageType)
                ? DescribeChannel(GetMirrorChannel(messageType))
                : "control";
        }

        private static string DescribeChannel(int channelId)
        {
            return channelId == Channels.Unreliable ? "unreliable" : "reliable";
        }

        private static int NormalizeChannel(int channelId)
        {
            return channelId == Channels.Unreliable ? Channels.Unreliable : Channels.Reliable;
        }

        private static byte[] CopySegment(ArraySegment<byte> segment)
        {
            var buffer = new byte[segment.Count];
            if (segment.Count > 0 && segment.Array != null)
            {
                Buffer.BlockCopy(segment.Array, segment.Offset, buffer, 0, segment.Count);
            }

            return buffer;
        }
    }
}
