//go:build linux

package transport

import (
	"net"
	"reflect"
	"testing"

	"omnisocketgo/cmd/internal/latencylog"
	"omnisocketgo/cmd/internal/protocol"
)

// TestUDPLinuxTimestampingRecordsKernelEvents 验证 UDP 在 Linux 上能正确采集内核时间戳。
func TestUDPLinuxTimestampingRecordsKernelEvents(t *testing.T) {
	tests := []struct {
		name string
		msg  protocol.Message
	}{
		{
			name: "text",
			msg: protocol.Message{
				Type: protocol.MessageTypeText,
				ID:   41,
				From: "peer-a",
				To:   "peer-b",
				Body: []byte("hello over udp"),
			},
		},
		{
			name: "file",
			msg: protocol.Message{
				Type:     protocol.MessageTypeFile,
				ID:       42,
				From:     "peer-a",
				To:       "peer-b",
				FileName: "payload.bin",
				Body:     []byte{0x00, 0x01, 0x02, 0xff},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			senderLogger := &recordingLogger{}
			receiverLogger := &recordingLogger{}

			// 创建 server 侧监听
			serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
			if err != nil {
				t.Fatalf("ResolveUDPAddr() error = %v", err)
			}
			serverRaw, err := net.ListenUDP("udp", serverAddr)
			if err != nil {
				t.Fatalf("ListenUDP() error = %v", err)
			}
			receiver, err := NewUDPConn(
				serverRaw,
				nil,
				WithUDPLogger(receiverLogger, latencylog.NodeRolePeer, "peer-b"),
			)
			if err != nil {
				_ = serverRaw.Close()
				t.Fatalf("NewUDPConn(receiver) error = %v", err)
			}
			t.Cleanup(func() { _ = receiver.Close() })

			// 创建 peer 侧连接
			peerRaw, err := net.DialUDP("udp", nil, serverRaw.LocalAddr().(*net.UDPAddr))
			if err != nil {
				t.Fatalf("DialUDP() error = %v", err)
			}
			sender, err := NewUDPConn(
				peerRaw,
				nil,
				WithUDPLogger(senderLogger, latencylog.NodeRolePeer, "peer-a"),
			)
			if err != nil {
				_ = peerRaw.Close()
				t.Fatalf("NewUDPConn(sender) error = %v", err)
			}
			t.Cleanup(func() { _ = sender.Close() })

			sendErr := make(chan error, 1)
			go func() {
				sendErr <- sender.Send(tt.msg)
			}()

			got, _, err := receiver.Receive()
			if err != nil {
				t.Fatalf("Receive() error = %v", err)
			}
			if err := <-sendErr; err != nil {
				t.Fatalf("Send() error = %v", err)
			}
			if !reflect.DeepEqual(got, tt.msg) {
				t.Fatalf("message mismatch: got %+v want %+v", got, tt.msg)
			}

			assertHasEvent(t, senderLogger.Events(), latencylog.EventATXSched, tt.msg.ID)
			assertHasEvent(t, senderLogger.Events(), latencylog.EventATXSoftware, tt.msg.ID)
			assertHasEvent(t, receiverLogger.Events(), latencylog.EventBRXSoftware, tt.msg.ID)
		})
	}
}
