package loadsim

import (
	"testing"

	"lingniu-vehicle-ingest/go/vehicle-gateway/internal/protocol/gb32960"
	"lingniu-vehicle-ingest/go/vehicle-gateway/internal/protocol/jt808"
)

func TestFrameFactoryGeneratesUniqueParsableJT808Frames(t *testing.T) {
	factory, err := NewFrameFactory(ProtocolJT808, "0200")
	if err != nil {
		t.Fatalf("NewFrameFactory() error = %v", err)
	}

	first, err := factory.Frame(0, 0)
	if err != nil {
		t.Fatalf("first Frame() error = %v", err)
	}
	second, err := factory.Frame(1, 2)
	if err != nil {
		t.Fatalf("second Frame() error = %v", err)
	}
	if string(first) == string(second) {
		t.Fatal("variant frames should not be byte-identical")
	}

	firstEnv := parseJT808Frame(t, first)
	secondEnv := parseJT808Frame(t, second)
	if firstEnv.Phone == secondEnv.Phone {
		t.Fatalf("phones should differ, both %q", firstEnv.Phone)
	}
	if firstEnv.Sequence == secondEnv.Sequence {
		t.Fatalf("sequences should differ, both %d", firstEnv.Sequence)
	}
	if firstEnv.StableEventID() == secondEnv.StableEventID() {
		t.Fatal("stable event ids should differ")
	}
}

func TestFrameFactoryUsesConfiguredJT808PhoneBase(t *testing.T) {
	factory, err := NewFrameFactoryWithJT808PhoneBase(ProtocolJT808, "0200", 138900000000)
	if err != nil {
		t.Fatalf("NewFrameFactoryWithJT808PhoneBase() error = %v", err)
	}
	frame, err := factory.Frame(42, 0)
	if err != nil {
		t.Fatalf("Frame() error = %v", err)
	}
	if got := parseJT808Frame(t, frame).Phone; got != "138900000042" {
		t.Fatalf("phone = %q, want 138900000042", got)
	}
}

func TestFrameFactoryGeneratesUniqueParsableGB32960Frames(t *testing.T) {
	factory, err := NewFrameFactory(ProtocolGB32960, "realtime")
	if err != nil {
		t.Fatalf("NewFrameFactory() error = %v", err)
	}

	first, err := factory.Frame(0, 0)
	if err != nil {
		t.Fatalf("first Frame() error = %v", err)
	}
	second, err := factory.Frame(1, 2)
	if err != nil {
		t.Fatalf("second Frame() error = %v", err)
	}
	if string(first) == string(second) {
		t.Fatal("variant frames should not be byte-identical")
	}

	firstEnv := parseGB32960Frame(t, first)
	secondEnv := parseGB32960Frame(t, second)
	if firstEnv.VIN == secondEnv.VIN {
		t.Fatalf("VINs should differ, both %q", firstEnv.VIN)
	}
	if firstEnv.StableEventID() == secondEnv.StableEventID() {
		t.Fatal("stable event ids should differ")
	}
}

func parseJT808Frame(t *testing.T, frame []byte) parsedEnvelope {
	t.Helper()
	frames, remainder, err := jt808.ExtractFrames(frame)
	if err != nil {
		t.Fatalf("ExtractFrames() error = %v", err)
	}
	if len(remainder) != 0 || len(frames) != 1 {
		t.Fatalf("unexpected split frames=%d remainder=%x", len(frames), remainder)
	}
	env, err := jt808.ParseFrame(frames[0], 1782918600000, "127.0.0.1:808")
	if err != nil {
		t.Fatalf("ParseFrame() error = %v", err)
	}
	return parsedEnvelope{Phone: env.Phone, VIN: env.VIN, Sequence: env.Sequence, StableEventID: env.StableEventID}
}

func parseGB32960Frame(t *testing.T, frame []byte) parsedEnvelope {
	t.Helper()
	frames, remainder, err := gb32960.ExtractFrames(frame)
	if err != nil {
		t.Fatalf("ExtractFrames() error = %v", err)
	}
	if len(remainder) != 0 || len(frames) != 1 {
		t.Fatalf("unexpected split frames=%d remainder=%x", len(frames), remainder)
	}
	env, err := gb32960.ParseFrame(frames[0], 1782918600000, "127.0.0.1:32960")
	if err != nil {
		t.Fatalf("ParseFrame() error = %v", err)
	}
	return parsedEnvelope{Phone: env.Phone, VIN: env.VIN, Sequence: env.Sequence, StableEventID: env.StableEventID}
}

type parsedEnvelope struct {
	Phone         string
	VIN           string
	Sequence      uint16
	StableEventID func() string
}
